Compare commits

..

5 commits

Author SHA1 Message Date
Ludovic Stephan
6a704a31a0 Revert "Doc"
This reverts commit 1ab3d11f639520a2a32c7afb004dcbb004e632d6.
2021-05-05 17:59:27 +02:00
Ludovic Stephan
819b875971 Doc 2021-05-05 17:59:27 +02:00
Ludovic Stephan
e4973367c6 Add clean target 2021-05-05 17:59:27 +02:00
Ludovic Stephan
30ac7817cf Switch to minifier 2021-05-05 17:59:27 +02:00
Ludovic Stephan
e42349bc74 Use ES6 modules 2021-05-05 17:59:27 +02:00
303 changed files with 1480 additions and 4071 deletions

View file

@ -1 +0,0 @@
0x0000000000000000000000000000000000000000

View file

@ -1 +0,0 @@
10000000-ffff-ffff-ffff-000000000001

View file

@ -1 +0,0 @@
k-feste_token

View file

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

1
.envrc
View file

@ -1 +0,0 @@
use nix

2
.gitignore vendored
View file

@ -5,7 +5,6 @@ cof/settings.py
settings.py
*~
venv/
.venv/
.vagrant
/src
media/
@ -20,4 +19,3 @@ media/
# VSCode
.vscode/
.direnv

View file

@ -43,21 +43,13 @@ variables:
# Keep this disabled for now, as it may kill GitLab...
# coverage: '/TOTAL.*\s(\d+\.\d+)\%$/'
kfettest:
stage: test
extends: .test_template
variables:
DJANGO_SETTINGS_MODULE: "gestioasso.settings.cof_prod"
script:
- coverage run manage.py test kfet
coftest:
stage: test
extends: .test_template
variables:
DJANGO_SETTINGS_MODULE: "gestioasso.settings.cof_prod"
script:
- coverage run manage.py test gestioncof bda petitscours shared --parallel
- coverage run manage.py test gestioncof bda kfet petitscours shared --parallel
bdstest:
stage: test

View file

@ -21,87 +21,20 @@ Liste des changements notables dans GestioCOF depuis la version 0.1 (septembre
Uniquement un modèle simple de clubs avec des respos. Aucune gestion des
adhérents ni des cotisations.
## TODO Prod
- Lancer `python manage.py update_translation_fields` après la migration
- Mettre à jour les units systemd `daphne.service` et `worker.service`
- Créer un compte hCaptcha (https://www.hcaptcha.com/), au COF, et remplacer les secrets associés
## Version ??? - ??/??/????
## Version 0.15.1 - 15/06/2023
## Version 0.11
### K-Fêt
- Rattrape les erreurs d'envoi de mail de négatif
- Utilise l'adresse chefs pour les envois de négatifs
## Version 0.15 - 22/05/2023
### K-Fêt
- Rajoute un formulaire de contact
- Rajoute un formulaire de demande de soirée
- Désactive les mails d'envoi de négatifs sur les comptes gelés
## Version 0.14 - 19/05/2023
- Répare les dépendances en spécifiant toutes les versions
### K-Fêt
- Répare la gestion des changement d'heure via moment.js
## Version 0.13 - 19/02/2023
### K-Fêt
- Rajoute la valeur des inventaires
- Résout les problèmes de négatif ne disparaissant pas
- Affiche son surnom s'il y en a un
- Bugfixes
## Version 0.12.1 - 03/10/2022
### K-Fêt
- Fixe un problème de rendu causé par l'agrandissement du menu
- Mise à jour vers Channels 3.x et Django 3.2
## Version 0.12 - 17/06/2022
### K-Fêt
- Ajoute une exception à la limite d'historique pour les comptes `LIQ` et `#13`
- Répare le problème des étiquettes LIQ/Comptes K-Fêt inversées dans les stats des articles K-Fêt
## Version 0.11 - 26/10/2021
### COF
- Répare un problème de rendu sur le wagtail du COF
### K-Fêt
- Ajoute de mails de rappels pour les comptes en négatif
- La recherche de comptes sur K-Psul remarche normalement
- Le pointeur de la souris change de forme quand on survole un item d'autocomplétion
- Modification du gel de compte:
- on ne peut plus geler/dégeler son compte soi-même (il faut la permission "Gérer les permissions K-Fêt")
- on ne peut rien compter sur un compte gelé (aucune override possible), et les K-Fêteux·ses dont le compte est gelé perdent tout accès à K-Psul
- les comptes actuellement gelés (sur l'ancien système) sont dégelés automatiquement
- Modification du fonctionnement des négatifs
- impossible d'avoir des négatifs inférieurs à `kfet_config.overdraft_amount`
- il n'y a plus de limite de temps sur les négatifs
- supression des autorisations de négatif
- il n'est plus possible de réinitialiser la durée d'un négatif en faisant puis en annulant une charge
- La gestion des erreurs passe du client au serveur, ce qui permet d'avoir des messages plus explicites
- La supression d'opérations anciennes est réparée
## Version 0.10 - 18/04/2021
### TODO Prod
- Créer un compte hCaptcha (https://www.hcaptcha.com/), au COF, et remplacer les secrets associés
### K-Fêt
- On fait sauter la limite qui empêchait de vendre plus de 24 unités d'un item à

View file

@ -18,7 +18,7 @@ Il vous faudra installer pip, les librairies de développement de python ainsi
que sqlite3, un moteur de base de données léger et simple d'utilisation. Sous
Debian et dérivées (Ubuntu, ...) :
sudo apt-get install python3-pip python3-dev python3-venv sqlite3 libsasl2-dev python-dev-is-python3 libldap2-dev libssl-dev
sudo apt-get install python3-pip python3-dev python3-venv sqlite3
Si vous décidez d'utiliser un environnement virtuel Python (virtualenv;
fortement conseillé), déplacez-vous dans le dossier où est installé GestioCOF
@ -30,15 +30,7 @@ Pour l'activer, il faut taper
. venv/bin/activate
depuis le même dossier. Pour préparer l'environnement à l'utilisation de `./manage.py`
(qui permet de faire des tests en local), il faut également taper
export CREDENTIALS_DIRECTORY=$(realpath .credentials)
export DJANGO_SETTINGS_MODULE=gestioasso.settings.local
export GESTIOCOF_DEBUG=true
export GESTIOCOF_STATIC_ROOT=$(realpath .static)
export GESTIOBDS_DEBUG=true
export GESTIOBDS_STATIC_ROOT=$(realpath .static)
depuis le même dossier.
Vous pouvez maintenant installer les dépendances Python depuis le fichier
`requirements-devel.txt` :

View file

@ -211,6 +211,7 @@ class AttributionAdminForm(forms.ModelForm):
class AttributionAdmin(ReadOnlyMixin, admin.ModelAdmin):
list_display = ("id", "spectacle", "participant", "given", "paid")
search_fields = (
"spectacle__title",

View file

@ -2,6 +2,7 @@ import random
class Algorithm(object):
shows = None
ranks = None
origranks = None

View file

@ -81,7 +81,7 @@ class Command(MyBaseCommand):
shows = random.sample(
list(tirage.spectacle_set.all()), tirage.spectacle_set.count() // 2
)
for rank, show in enumerate(shows):
for (rank, show) in enumerate(shows):
choices.append(
ChoixSpectacle(
participant=part,

View file

@ -6,6 +6,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)]
operations = [

View file

@ -35,6 +35,7 @@ def fill_tirage_fields(apps, schema_editor):
class Migration(migrations.Migration):
dependencies = [("bda", "0001_initial")]
operations = [

View file

@ -5,6 +5,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("bda", "0002_add_tirage")]
operations = [

View file

@ -5,6 +5,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("bda", "0003_update_tirage_and_spectacle")]
operations = [

View file

@ -5,6 +5,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("bda", "0004_mails-rappel")]
operations = [

View file

@ -18,6 +18,7 @@ def forwards_func(apps, schema_editor):
class Migration(migrations.Migration):
dependencies = [("bda", "0005_encoding")]
operations = [

View file

@ -5,6 +5,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("bda", "0006_add_tirage_switch")]
operations = [

View file

@ -5,6 +5,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("bda", "0007_extends_spectacle")]
operations = [

View file

@ -6,6 +6,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("bda", "0008_py3")]
operations = [

View file

@ -21,6 +21,7 @@ def forwards_func(apps, schema_editor):
class Migration(migrations.Migration):
dependencies = [("bda", "0009_revente")]
operations = [

View file

@ -5,6 +5,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("bda", "0010_spectaclerevente_shotgun")]
operations = [

View file

@ -5,6 +5,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("bda", "0011_tirage_appear_catalogue")]
operations = [

View file

@ -13,6 +13,7 @@ def swap_double_choice(apps, schema_editor):
class Migration(migrations.Migration):
dependencies = [("bda", "0011_tirage_appear_catalogue")]
operations = [

View file

@ -6,6 +6,7 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [("bda", "0012_notif_time"), ("bda", "0012_swap_double_choice")]
operations = []

View file

@ -4,6 +4,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("bda", "0013_merge_20180524_2123")]
operations = [

View file

@ -29,6 +29,7 @@ def set_participant_payment(apps, schema_editor):
class Migration(migrations.Migration):
dependencies = [("bda", "0014_attribution_paid_field")]
operations = [

View file

@ -4,6 +4,7 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [("bda", "0015_move_bda_payment")]
operations = [

View file

@ -4,6 +4,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("bda", "0016_delete_participant_paid")]
operations = [

View file

@ -5,6 +5,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bda", "0017_participant_accepte_charte"),
]

View file

@ -1,23 +0,0 @@
# Generated by Django 3.2.13 on 2022-06-30 10:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bda", "0018_auto_20201021_1818"),
]
operations = [
migrations.AlterUniqueTogether(
name="choixspectacle",
unique_together=set(),
),
migrations.AddConstraint(
model_name="choixspectacle",
constraint=models.UniqueConstraint(
fields=("participant", "spectacle"), name="unique_participation"
),
),
]

View file

@ -253,11 +253,7 @@ class ChoixSpectacle(models.Model):
class Meta:
ordering = ("priority",)
constraints = [
models.UniqueConstraint(
fields=["participant", "spectacle"], name="unique_participation"
)
]
unique_together = (("participant", "spectacle"),)
verbose_name = "voeu"
verbose_name_plural = "voeux"

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %}
{% load static %}
{% load staticfiles %}
{% block extra_head %}
<link type="text/css" rel="stylesheet" href="{% static "bda/css/bda.css" %}" />

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %}
{% load static %}
{% load staticfiles %}
{% block realcontent %}
<h2>État des inscriptions BdA</h2>

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %}
{% load static %}
{% load staticfiles %}
{% block extra_head %}
<script type="text/javascript" src="{% static 'vendor/jquery/jquery-ui.min.js' %}" ></script>

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %}
{% load static %}
{% load staticfiles %}
{% block realcontent %}
<h2>{{ spectacle }}</h2>

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %}
{% load static %}
{% load staticfiles %}
{%block realcontent %}

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %}
{% load static %}
{% load staticfiles %}
{% block realcontent %}
<h2>Inscription à une revente</h2>

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %}
{% load static %}
{% load staticfiles %}
{% block realcontent %}

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %}
{% load static %}
{% load staticfiles %}
{% block realcontent %}

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %}
{% load static %}
{% load staticfiles%}
{% block realcontent %}
<h2>Inscriptions pour BdA-Revente</h2>

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %}
{% load static %}
{% load staticfiles %}
{% block realcontent %}

View file

@ -1,5 +1,5 @@
{% extends "base_title.html" %}
{% load static %}
{% load staticfiles %}
{% block extra_head %}
<link type="text/css" rel="stylesheet" href="{% static "bda/css/bda.css" %}" />

View file

@ -356,9 +356,7 @@ class TestReventeManageTest(TestCase):
def test_can_get(self):
client = Client()
client.force_login(
self.user, backend="django.contrib.auth.backends.ModelBackend"
)
client.force_login(self.user)
r = client.get(self.url)
self.assertEqual(r.status_code, 200)

View file

@ -1,80 +1,74 @@
from django.urls import re_path
from django.conf.urls import url
from bda import views
from bda.views import SpectacleListView
from gestioncof.decorators import buro_required
urlpatterns = [
re_path(
url(
r"^inscription/(?P<tirage_id>\d+)$",
views.inscription,
name="bda-tirage-inscription",
),
re_path(r"^places/(?P<tirage_id>\d+)$", views.places, name="bda-places-attribuees"),
re_path(
r"^etat-places/(?P<tirage_id>\d+)$", views.etat_places, name="bda-etat-places"
),
re_path(r"^tirage/(?P<tirage_id>\d+)$", views.tirage, name="bda-tirage"),
re_path(
url(r"^places/(?P<tirage_id>\d+)$", views.places, name="bda-places-attribuees"),
url(r"^etat-places/(?P<tirage_id>\d+)$", views.etat_places, name="bda-etat-places"),
url(r"^tirage/(?P<tirage_id>\d+)$", views.tirage, name="bda-tirage"),
url(
r"^spectacles/(?P<tirage_id>\d+)$",
buro_required(SpectacleListView.as_view()),
name="bda-liste-spectacles",
),
re_path(
url(
r"^spectacles/(?P<tirage_id>\d+)/(?P<spectacle_id>\d+)$",
views.spectacle,
name="bda-spectacle",
),
re_path(
url(
r"^spectacles/unpaid/(?P<tirage_id>\d+)$",
views.UnpaidParticipants.as_view(),
name="bda-unpaid",
),
re_path(
url(
r"^spectacles/autocomplete$",
views.spectacle_autocomplete,
name="bda-spectacle-autocomplete",
),
re_path(
url(
r"^participants/autocomplete$",
views.participant_autocomplete,
name="bda-participant-autocomplete",
),
# Urls BdA-Revente
re_path(
url(
r"^revente/(?P<tirage_id>\d+)/manage$",
views.revente_manage,
name="bda-revente-manage",
),
re_path(
url(
r"^revente/(?P<tirage_id>\d+)/subscribe$",
views.revente_subscribe,
name="bda-revente-subscribe",
),
re_path(
url(
r"^revente/(?P<tirage_id>\d+)/tirages$",
views.revente_tirages,
name="bda-revente-tirages",
),
re_path(
url(
r"^revente/(?P<spectacle_id>\d+)/buy$",
views.revente_buy,
name="bda-revente-buy",
),
re_path(
url(
r"^revente/(?P<revente_id>\d+)/confirm$",
views.revente_confirm,
name="bda-revente-confirm",
),
re_path(
url(
r"^revente/(?P<tirage_id>\d+)/shotgun$",
views.revente_shotgun,
name="bda-revente-shotgun",
),
re_path(
r"^mails-rappel/(?P<spectacle_id>\d+)$", views.send_rappel, name="bda-rappels"
),
re_path(
r"^catalogue/(?P<request_type>[a-z]+)$", views.catalogue, name="bda-catalogue"
),
url(r"^mails-rappel/(?P<spectacle_id>\d+)$", views.send_rappel, name="bda-rappels"),
url(r"^catalogue/(?P<request_type>[a-z]+)$", views.catalogue, name="bda-catalogue"),
]

View file

@ -274,13 +274,13 @@ def do_tirage(tirage_elt, token):
results = Algorithm(data["shows"], data["members"], choices)(token)
# On compte les places attribuées et les déçus
for _, members, losers in results:
for (_, members, losers) in results:
data["total_slots"] += len(members)
data["total_losers"] += len(losers)
# On calcule le déficit et les bénéfices pour le BdA
# FIXME: le traitement de l'opéra est sale
for show, members, _ in results:
for (show, members, _) in results:
deficit = (show.slots - len(members)) * show.price
data["total_sold"] += show.slots * show.price
if deficit >= 0:
@ -293,8 +293,8 @@ def do_tirage(tirage_elt, token):
# so assign a single object for each Participant id
members_uniq = {}
members2 = {}
for show, members, _ in results:
for member, _, _, _ in members:
for (show, members, _) in results:
for (member, _, _, _) in members:
if member.id not in members_uniq:
members_uniq[member.id] = member
members2[member] = []

View file

@ -0,0 +1 @@
default_app_config = "bds.apps.BdsConfig"

View file

@ -1,4 +1,5 @@
from django.apps import AppConfig, apps as global_apps
from django import apps as global_apps
from django.apps import AppConfig
from django.db.models import Q
from django.db.models.signals import post_migrate

View file

@ -36,6 +36,4 @@ class ProfileForm(forms.ModelForm):
class Meta:
model = BDSProfile
exclude = ["user"]
widgets = {
"birthdate": forms.DateInput(attrs={"type": "date"}, format="%Y-%m-%d")
}
widgets = {"birthdate": forms.DateInput(attrs={"type": "date"})}

View file

@ -8,6 +8,7 @@ import bds.models
class Migration(migrations.Migration):
initial = True
dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)]

View file

@ -9,6 +9,7 @@ def create_bds_buro_group(apps, schema_editor):
class Migration(migrations.Migration):
dependencies = [("bds", "0001_initial")]
operations = [

View file

@ -4,6 +4,7 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("bds", "0002_bds_group"),
]

View file

@ -4,6 +4,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bds", "0003_staff_permission"),
]

View file

@ -4,6 +4,7 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("bds", "0004_is_member_cotiz_type"),
]

View file

@ -4,6 +4,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bds", "0005_remove_bdsprofile_certificate_file"),
]

View file

@ -3,7 +3,6 @@ from os.path import splitext
from django.contrib.auth import get_user_model
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from shared.utils import choices_length
@ -94,16 +93,6 @@ class BDSProfile(models.Model):
),
)
@classmethod
def expired_members(cls):
now = timezone.now()
qs = cls.objects.filter(is_member=True)
if now.month > 1 and now.month < 7:
return qs.filter(cotisation_period="SE1")
elif now.month < 2 or now.month > 8:
return qs.none()
return qs
class Meta:
verbose_name = _("Profil BDS")
verbose_name_plural = _("Profils BDS")

View file

@ -1,4 +1,4 @@
{% load static %}
{% load staticfiles %}
{% load bulma_utils %}
<!DOCTYPE html>

View file

@ -1,22 +0,0 @@
{% extends "bds/base.html" %}
{% block content %}
<h1 class="title">Liste des adhésions expirées</h1>
{% if object_list %}
<div class="content">
<ul>
{% for p in object_list %}
<li>{{ p.user.first_name }} {{ p.user.last_name }} ({{ p.user.username }}), {{ p.get_cotisation_period_display }}</li>
{% endfor %}
</ul>
</div>
<div class="buttons is-centered">
<a class="button is-danger" href="{% url 'bds:members.reset' %}">Réinitialiser les adhésions expirées</a>
</div>
{% endif %}
{% endblock %}

View file

@ -36,8 +36,6 @@
<a class=button href="{% url 'bds:export.members' %}">Télécharger la liste des membres (CSV)</a>
<a class=button href="{% url 'bds:members.expired' %}">Liste des adhésions expirées ({{ nb_expired }})</a>
<br>
<br>

View file

@ -5,100 +5,100 @@
{% block content %}
{% for form in forms.values %}
{% for error in form.non_field_errors %}
<div class="notification is-danger">
{{ error }}
</div>
{% endfor %}
{% for error in form.non_field_errors %}
<div class="notification is-danger">
{{ error }}
</div>
{% endfor %}
{% endfor %}
<h1 class="title">{% trans "Modification du profil " %}{{ view.user.username }}</h1>
<div class="container">
<form method="post" action="" id="user-update-form">
{% csrf_token %}
<form method="post" action="" id="user-update-form">
{% csrf_token %}
{% for form in forms.values %}
{% include "bds/forms/form.html" with form=form errors=False %}
{% endfor %}
</form>
{% for form in forms.values %}
{% include "bds/forms/form.html" with form=form errors=False %}
{% endfor %}
</form>
<form method="post" action="{% url 'bds:user.delete' view.user.pk %}" id="user-delete-form">
{% csrf_token %}
</form>
<form method="post" action="{% url 'bds:user.delete' view.user.pk %}" id="user-delete-form">
{% csrf_token %}
</form>
<div class="columns is-gapless mt-5">
<div class="column is-5">
<button id="user-update-button" class="button is-fullwidth is-primary">Enregistrer</button>
</div>
<div class="column is-2">
</div>
<div class="column is-5">
<button id="user-delete-button" class="button is-fullwidth is-danger">Supprimer</button>
</div>
<div class="columns is-gapless mt-5">
<div class="column is-5">
<button id="user-update-button" class="button is-fullwidth is-primary">Enregistrer</button>
</div>
<div class="column is-2">
</div>
<div class="column is-5">
<button id="user-delete-button" class="button is-fullwidth is-danger">Supprimer</button>
</div>
</div>
</div>
<!-- Hidden by default -->
<div id="confirm-delete-modal" class="modal">
<div class="modal-background"></div>
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">Confirmer la suppression</p>
<button id="modal-close" class="delete" aria-label="close"></button>
</header>
<section class="modal-card-body">
Voulez-vous réellement supprimer ce compte ? Attention, cette opération est irréversible !
</section>
<footer class="modal-card-foot">
<button id="confirm-delete-button" class="button is-primary">Supprimer</button>
<button id="cancel-delete-button" class="button">Annuler</button>
</footer>
</div>
<div class="modal-background"></div>
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">Confirmer la suppression</p>
<button id= "modal-close" class="delete" aria-label="close"></button>
</header>
<section class="modal-card-body">
Voulez-vous réellement supprimer ce compte ? Attention, cette opération est irréversible !
</section>
<footer class="modal-card-foot">
<button id="confirm-delete-button" class="button is-primary">Supprimer</button>
<button id="cancel-delete-button" class="button">Annuler</button>
</footer>
</div>
</div>
<script type="text/javascript">
$(document).ready(function() {
"use strict";
$(document).ready(function() {
"use strict";
// Adapted from https://bulma.io/lib/main.js
function openModal(target) {
$(document).addClass('is-clipped');
$(`#${target}`).addClass('is-active');
}
// Adapted from https://bulma.io/lib/main.js
function openModal(target) {
$(document).addClass('is-clipped');
$(`#${target}`).addClass('is-active');
}
function closeModals() {
$(document).removeClass('is-clipped');
$(".modal").removeClass('is-active');
}
function closeModals() {
$(document).removeClass('is-clipped');
$(".modal").removeClass('is-active');
}
// Si on clique sur enregistrer, ça marche
$("#user-update-button").on("click", function() {
$("#user-update-form").submit();
})
// Si on clique sur supprimer, confirmation demandée
$("#user-delete-button").on("click", function() {
openModal("confirm-delete-modal");
});
$(".modal-background, #modal-close, #cancel-delete-button").on("click", closeModals);
$("#confirm-delete-button").on("click", function() {
$("#user-delete-form").submit();
});
$(document).on("keydown", function(e) {
if (e.key == "Escape") {
closeModals();
}
if (e.key == "Enter") {
$("#user-update-form").submit();
}
});
// Si on clique sur enregistrer, ça marche
$("#user-update-button").on("click", function() {
$("#user-update-form").submit();
})
// Si on clique sur supprimer, confirmation demandée
$("#user-delete-button").on("click", function () {
openModal("confirm-delete-modal");
});
$(".modal-background, #modal-close, #cancel-delete-button").on("click", closeModals);
$("#confirm-delete-button").on("click", function() {
$("#user-delete-form").submit();
});
$(document).on("keydown", function (e) {
if (e.key == "Escape") {
closeModals();
}
if (e.key == "Enter") {
$("#user-update-form").submit();
}
});
});
</script>
{% endblock %}

View file

@ -27,11 +27,9 @@ class TestHomeView(TestCase):
def test_get(self, mock_messages):
user = User.objects.create_user(username="random_user")
give_bds_buro_permissions(user)
self.client.force_login(
user, backend="django.contrib.auth.backends.ModelBackend"
)
self.client.force_login(user)
resp = self.client.get(reverse("bds:home"))
self.assertEqual(resp.status_code, 200)
self.assertEquals(resp.status_code, 200)
class TestRegistrationView(TestCase):
@ -46,14 +44,14 @@ class TestRegistrationView(TestCase):
self.assertRedirects(resp, login_url(next=url))
# Logged-in but unprivileged GET
client.force_login(user, backend="django.contrib.auth.backends.ModelBackend")
client.force_login(user)
resp = client.get(url)
self.assertEqual(resp.status_code, 403)
self.assertEquals(resp.status_code, 403)
# Burô user GET
give_bds_buro_permissions(user)
resp = client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertEquals(resp.status_code, 200)
@mock.patch("gestioncof.signals.messages")
def test_get(self, mock_messages):
@ -66,11 +64,11 @@ class TestRegistrationView(TestCase):
self.assertRedirects(resp, login_url(next=url))
# Logged-in but unprivileged GET
client.force_login(user, backend="django.contrib.auth.backends.ModelBackend")
client.force_login(user)
resp = client.get(url)
self.assertEqual(resp.status_code, 403)
self.assertEquals(resp.status_code, 403)
# Burô user GET
give_bds_buro_permissions(user)
resp = client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertEquals(resp.status_code, 200)

View file

@ -15,10 +15,4 @@ urlpatterns = [
),
path("user/delete/<int:pk>", views.UserDeleteView.as_view(), name="user.delete"),
path("members", views.export_members, name="export.members"),
path(
"members/expired",
views.ResetMembershipListView.as_view(),
name="members.expired",
),
path("members/reset", views.ResetMembershipView.as_view(), name="members.reset"),
]

View file

@ -8,7 +8,7 @@ from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.urls import reverse, reverse_lazy
from django.utils.translation import gettext_lazy as _
from django.views.generic import DeleteView, ListView, RedirectView, TemplateView
from django.views.generic import DeleteView, TemplateView
from bds.autocomplete import bds_search
from bds.forms import ProfileForm, UserForm, UserFromClipperForm, UserFromScratchForm
@ -30,7 +30,6 @@ class Home(StaffRequiredMixin, TemplateView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["member_count"] = BDSProfile.objects.filter(is_member=True).count()
context["nb_expired"] = BDSProfile.expired_members().count()
return context
@ -144,28 +143,6 @@ class UserDeleteView(StaffRequiredMixin, DeleteView):
return super().delete(request, *args, **kwargs)
class ResetMembershipListView(StaffRequiredMixin, ListView):
model = BDSProfile
template_name = "bds/expired_members.html"
def get_queryset(self):
return BDSProfile.expired_members()
class ResetMembershipView(StaffRequiredMixin, RedirectView):
url = reverse_lazy("bds:members.expired")
def get(self, request, *args, **kwargs):
qs = BDSProfile.expired_members()
nb = qs.count()
qs.update(cotisation_period="NO", is_member=False, mails_bds=False)
messages.success(request, f"{nb} adhésions réinitialisées")
return super().get(request, *args, **kwargs)
@permission_required("bds.is_team")
def export_members(request):
response = HttpResponse(content_type="text/csv")

View file

@ -5,6 +5,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)]

View file

@ -4,6 +4,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = []

View file

@ -5,6 +5,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("events", "0001_event"),

View file

@ -6,6 +6,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("events", "0002_event_subscribers"),

View file

@ -5,6 +5,7 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("events", "0003_options_and_extra_fields"),

View file

@ -1,63 +0,0 @@
# Generated by Django 3.2.13 on 2022-06-30 10:39
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("events", "0004_unique_constraints"),
]
operations = [
migrations.AlterUniqueTogether(
name="extrafield",
unique_together=set(),
),
migrations.AlterUniqueTogether(
name="extrafieldcontent",
unique_together=set(),
),
migrations.AlterUniqueTogether(
name="option",
unique_together=set(),
),
migrations.AlterUniqueTogether(
name="optionchoice",
unique_together=set(),
),
migrations.AlterUniqueTogether(
name="registration",
unique_together=set(),
),
migrations.AddConstraint(
model_name="extrafield",
constraint=models.UniqueConstraint(
fields=("event", "name"), name="unique_extra_field"
),
),
migrations.AddConstraint(
model_name="extrafieldcontent",
constraint=models.UniqueConstraint(
fields=("field", "registration"), name="unique_extra_field_content"
),
),
migrations.AddConstraint(
model_name="option",
constraint=models.UniqueConstraint(
fields=("event", "name"), name="unique_event_option"
),
),
migrations.AddConstraint(
model_name="optionchoice",
constraint=models.UniqueConstraint(
fields=("option", "choice"), name="unique_option_choice"
),
),
migrations.AddConstraint(
model_name="registration",
constraint=models.UniqueConstraint(
fields=("event", "user"), name="unique_registration"
),
),
]

View file

@ -72,13 +72,9 @@ class Option(models.Model):
multi_choices = models.BooleanField(_("choix multiples"), default=False)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["event", "name"], name="unique_event_option"
)
]
verbose_name = _("option d'événement")
verbose_name_plural = _("options d'événement")
unique_together = [["event", "name"]]
def __str__(self):
return self.name
@ -91,13 +87,9 @@ class OptionChoice(models.Model):
choice = models.CharField(_("choix"), max_length=200)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["option", "choice"], name="unique_option_choice"
)
]
verbose_name = _("choix d'option d'événement")
verbose_name_plural = _("choix d'option d'événement")
unique_together = [["option", "choice"]]
def __str__(self):
return self.choice
@ -126,9 +118,7 @@ class ExtraField(models.Model):
field_type = models.CharField(_("type de champ"), max_length=9, choices=FIELD_TYPE)
class Meta:
constraints = [
models.UniqueConstraint(fields=["event", "name"], name="unique_extra_field")
]
unique_together = [["event", "name"]]
class ExtraFieldContent(models.Model):
@ -147,13 +137,9 @@ class ExtraFieldContent(models.Model):
)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["field", "registration"], name="unique_extra_field_content"
)
]
verbose_name = _("contenu d'un champ événement supplémentaire")
verbose_name_plural = _("contenus d'un champ événement supplémentaire")
unique_together = [["field", "registration"]]
def __str__(self):
max_length = 50
@ -177,13 +163,9 @@ class Registration(models.Model):
)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["event", "user"], name="unique_registration"
)
]
verbose_name = _("inscription à un événement")
verbose_name_plural = _("inscriptions à un événement")
unique_together = [["event", "user"]]
def __str__(self):
return "inscription de {} à {}".format(self.user, self.event)

View file

@ -54,9 +54,7 @@ class CSVExportAccessTest(MessagePatch, TestCase):
def test_get(self):
client = Client()
client.force_login(
self.staff, backend="django.contrib.auth.backends.ModelBackend"
)
client.force_login(self.staff)
r = client.get(self.url)
self.assertEqual(r.status_code, 200)
@ -68,7 +66,7 @@ class CSVExportAccessTest(MessagePatch, TestCase):
def test_unauthorised(self):
client = Client()
client.force_login(self.u1, backend="django.contrib.auth.backends.ModelBackend")
client.force_login(self.u1)
r = client.get(self.url)
self.assertEqual(r.status_code, 403)
@ -88,9 +86,7 @@ class CSVExportContentTest(MessagePatch, CSVResponseMixin, TestCase):
)
self.staff = make_staff_user("staff")
self.client = Client()
self.client.force_login(
self.staff, backend="django.contrib.auth.backends.ModelBackend"
)
self.client.force_login(self.staff)
def test_simple_event(self):
self.event.subscribers.set([self.u1, self.u2])

View file

@ -1,15 +1,8 @@
"""
ASGI entrypoint. Configures Django and then runs the application
defined in the ASGI_APPLICATION setting.
"""
import os
import django
from channels.routing import get_default_application
from channels.asgi import get_channel_layer
if "DJANGO_SETTINGS_MODULE" not in os.environ:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gestioasso.settings.local")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gestioasso.settings")
django.setup()
application = get_default_application()
channel_layer = get_channel_layer()

View file

@ -1,20 +1,3 @@
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from django.urls import path
from channels.routing import include
from kfet.routing import KFRouter
application = ProtocolTypeRouter(
{
# WebSocket chat handler
"websocket": AuthMiddlewareStack(
URLRouter(
[
path("ws/k-fet", KFRouter),
]
)
),
"http": get_asgi_application(),
}
)
routing = [include("kfet.routing.routing", path=r"^/ws/k-fet")]

View file

@ -7,8 +7,6 @@ Surcharge les settings définis dans common.py
import os
from datetime import timedelta
from django.utils import timezone
from .common import * # NOQA
from .common import (
AUTHENTICATION_BACKENDS,
@ -67,8 +65,8 @@ INSTALLED_APPS = (
"wagtail.images",
"wagtail.search",
"wagtail.admin",
"wagtail",
# "wagtail.contrib.modeladmin",
"wagtail.core",
"wagtail.contrib.modeladmin",
"wagtail.contrib.routable_page",
"wagtailmenus",
"modelcluster",
@ -85,6 +83,7 @@ MIDDLEWARE = (
+ MIDDLEWARE
+ [
"djconfig.middleware.DjConfigMiddleware",
"wagtail.core.middleware.SiteMiddleware",
"wagtail.contrib.redirects.middleware.RedirectMiddleware",
]
)
@ -108,23 +107,15 @@ MEDIA_URL = "/gestion/media/"
CORS_ORIGIN_WHITELIST = ("bda.ens.fr", "www.bda.ens.fr" "cof.ens.fr", "www.cof.ens.fr")
ASGI_APPLICATION = "gestioasso.routing.application"
# ---
# Auth-related stuff
# ---
AUTHENTICATION_BACKENDS = (
[
# Must be in first
"kfet.auth.backends.BlockFrozenAccountBackend"
]
+ AUTHENTICATION_BACKENDS
+ [
"gestioncof.shared.COFCASBackend",
"kfet.auth.backends.GenericBackend",
]
)
AUTHENTICATION_BACKENDS += [
"gestioncof.shared.COFCASBackend",
"kfet.auth.backends.GenericBackend",
]
LOGIN_URL = "cof-login"
LOGIN_REDIRECT_URL = "home"
@ -148,7 +139,7 @@ CACHES = {
CHANNEL_LAYERS = {
"default": {
"BACKEND": "shared.channels.ChannelLayer",
"BACKEND": "asgi_redis.RedisChannelLayer",
"CONFIG": {
"hosts": [
(
@ -161,9 +152,11 @@ CHANNEL_LAYERS = {
)
]
},
"ROUTING": "gestioasso.routing.routing",
}
}
# ---
# reCAPTCHA settings
# https://github.com/praekelt/django-recaptcha
@ -205,10 +198,6 @@ MAIL_DATA = {
"REPLYTO": "cof@ens.fr",
},
"rappels": {"FROM": "Le BdA <bda@ens.fr>", "REPLYTO": "Le BdA <bda@ens.fr>"},
"kfet": {
"FROM": "La K-Fêt <chefs-k-fet@ens.fr>",
"REPLYTO": "La K-Fêt <chefs-k-fet@ens.fr>",
},
"revente": {
"FROM": "BdA-Revente <bda-revente@ens.fr>",
"REPLYTO": "BdA-Revente <bda-revente@ens.fr>",
@ -226,8 +215,3 @@ KFET_HISTORY_DATE_LIMIT = timedelta(days=7)
# Limite plus longue pour les chefs/trez
# (qui ont la permission kfet.access_old_history)
KFET_HISTORY_LONG_DATE_LIMIT = timedelta(days=30)
# These accounts don't represent actual people and can be freely accessed
# Identification based on trigrammes
KFET_HISTORY_NO_DATE_LIMIT_TRIGRAMMES = ["LIQ", "#13"]
KFET_HISTORY_NO_DATE_LIMIT = timezone.datetime(1794, 10, 30) # AKA the distant past

View file

@ -101,7 +101,7 @@ TEMPLATES = [
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"ENGINE": "django.db.backends.postgresql_psycopg2",
"NAME": DBNAME,
"USER": DBUSER,
"PASSWORD": DBPASSWD,
@ -111,7 +111,6 @@ DATABASES = {
SITE_ID = 1
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
# ---
# Internationalization

View file

@ -47,7 +47,8 @@ CACHES = {"default": {"BACKEND": "django.core.cache.backends.locmem.LocMemCache"
# Use the default in memory asgi backend for local development
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels.layers.InMemoryChannelLayer",
"BACKEND": "asgiref.inmemory.ChannelLayer",
"ROUTING": "gestioasso.routing.routing",
}
}

View file

@ -1,194 +0,0 @@
"""
Django settings for the gestioBDS project.
"""
import os
from pathlib import Path
from loadcredential import Credentials
credentials = Credentials(env_prefix="GESTIOBDS_")
# 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", [])
SERVER_EMAIL = credentials.get("SERVER_EMAIL")
EMAIL_HOST = credentials.get("EMAIL_HOST")
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
##
# Installed Apps configuration
INSTALLED_APPS = [
"shared",
# Must be before 'django.contrib.admin'.
# https://django-autocomplete-light.readthedocs.io/en/master/install.html
"dal",
"dal_select2",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.sites",
"django.contrib.messages",
"django.contrib.admin",
"django.contrib.admindocs",
"gestioasso.apps.IgnoreSrcStaticFilesConfig",
"django_cas_ng",
"bootstrapform",
"widget_tweaks",
"bds",
"events",
"clubs",
"authens",
]
##
# Middleware configuration
MIDDLEWARE = [
"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",
"django.middleware.security.SecurityMiddleware",
"django.middleware.locale.LocaleMiddleware",
]
##
# URL configuration
ROOT_URLCONF = "gestioasso.urls"
##
# Templates configuration
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"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",
"django.template.context_processors.i18n",
"django.template.context_processors.media",
"django.template.context_processors.static",
]
},
}
]
##
# Database configuration
DATABASES = credentials.get_json(
"DATABASES",
default={
"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",
},
},
)
CORS_ORIGIN_WHITELIST = credentials.get("CORS_ORIGIN_WHITELIST", [])
SITE_ID = 1
###
# Staticfiles configuration
STATIC_ROOT = credentials["STATIC_ROOT"]
STATIC_URL = "/static/"
MEDIA_ROOT = credentials.get("MEDIA_ROOT", (BASE_DIR / "media"))
MEDIA_URL = "/media/"
##
# Authens and Authentication configuration
AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend",
"authens.backends.ENSCASBackend",
"authens.backends.OldCASBackend",
]
AUTHENS_USE_OLDCAS = False
LOGIN_URL = "authens:login"
LOGIN_REDIRECT_URL = "bds:home"
LOGOUT_REDIRECT_URL = "bds:home"
# ---
# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/
# ---
LANGUAGE_CODE = "fr-fr"
TIME_ZONE = "Europe/Paris"
USE_I18N = True
USE_L10N = True
USE_TZ = True
LANGUAGES = (("fr", "Français"), ("en", "English"))
FORMAT_MODULE_PATH = "gestioasso.locale"
##
# Development configuration
if DEBUG:
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
def show_toolbar(request):
"""
On active la debug-toolbar en mode développement local sauf :
- dans l'admin où ça ne sert pas à grand chose;
- si la variable d'environnement DJANGO_NO_DDT est à 1 → ça permet de la désactiver
sans modifier ce fichier en exécutant `export DJANGO_NO_DDT=1` dans le terminal
qui lance `./manage.py runserver`.
Autre side effect de cette fonction : on ne fait pas la vérification de INTERNAL_IPS
que ferait la debug-toolbar par défaut, ce qui la fait fonctionner aussi à
l'intérieur de Vagrant (comportement non testé depuis un moment…)
"""
env_no_ddt = bool(os.environ.get("DJANGO_NO_DDT", None))
return not (env_no_ddt or request.path.startswith("/admin/"))
##
# Django Debug Toolbar configuration
DEBUG_TOOLBAR_CONFIG = {"SHOW_TOOLBAR_CALLBACK": show_toolbar}
INSTALLED_APPS += ["debug_toolbar"]
MIDDLEWARE = ["debug_toolbar.middleware.DebugToolbarMiddleware"] + MIDDLEWARE

View file

@ -1,318 +0,0 @@
"""
Django settings for the gestioCOF project.
"""
import os
from datetime import datetime, timedelta
from pathlib import Path
from django.urls import reverse_lazy
from loadcredential import Credentials
credentials = Credentials(env_prefix="GESTIOCOF_")
# 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", [])
SERVER_EMAIL = credentials.get("SERVER_EMAIL")
EMAIL_HOST = credentials.get("EMAIL_HOST")
LDAP_SERVER_URL = credentials.get("LDAP_SERVER_URL")
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
##
# Installed Apps configuration
INSTALLED_APPS = [
"gestioncof",
# Must be before django admin
# https://github.com/infoportugal/wagtail-modeltranslation/issues/193
"wagtail_modeltranslation",
"wagtail_modeltranslation.makemigrations",
"wagtail_modeltranslation.migrate",
"modeltranslation",
"shared",
# Must be before 'django.contrib.admin'.
# https://django-autocomplete-light.readthedocs.io/en/master/install.html
"dal",
"dal_select2",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.sites",
"django.contrib.messages",
"django.contrib.admin",
"django.contrib.admindocs",
"gestioasso.apps.IgnoreSrcStaticFilesConfig",
"django_cas_ng",
"bootstrapform",
"widget_tweaks",
"bda",
"petitscours",
"hcaptcha",
"kfet",
"kfet.open",
"channels",
"djconfig",
"wagtail.contrib.forms",
"wagtail.contrib.redirects",
"wagtail.embeds",
"wagtail.sites",
"wagtail.users",
"wagtail.snippets",
"wagtail.documents",
"wagtail.images",
"wagtail.search",
"wagtail.admin",
"wagtail",
# "wagtail.contrib.modeladmin",
"wagtail.contrib.routable_page",
"wagtailmenus",
"modelcluster",
"taggit",
"kfet.auth",
"kfet.cms",
"gestioncof.cms",
"django_js_reverse",
]
##
# Middleware configuration
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"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",
"django.middleware.security.SecurityMiddleware",
"django.middleware.locale.LocaleMiddleware",
"djconfig.middleware.DjConfigMiddleware",
"wagtail.contrib.redirects.middleware.RedirectMiddleware",
]
##
# URL configuration
ROOT_URLCONF = "gestioasso.urls"
##
# Templates configuration
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"wagtailmenus.context_processors.wagtailmenus",
"djconfig.context_processors.config",
"gestioncof.shared.context_processor",
"kfet.auth.context_processors.temporary_auth",
"kfet.context_processors.config",
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
"django.template.context_processors.i18n",
"django.template.context_processors.media",
"django.template.context_processors.static",
]
},
}
]
##
# Wagtail configuration
WAGTAIL_SITE_NAME = "GestioCOF"
WAGTAIL_ENABLE_UPDATE_CHECK = False
TAGGIT_CASE_INSENSITIVE = True
##
# Django-js-reverse settings
JS_REVERSE_JS_VAR_NAME = "django_urls"
# Quand on aura namespace les urls...
# JS_REVERSE_INCLUDE_ONLY_NAMESPACES = ['k-fet']
##
# K-Fêt history configuration
# L'historique n'est accesible que d'aujourd'hui
# à aujourd'hui - KFET_HISTORY_DATE_LIMIT
KFET_HISTORY_DATE_LIMIT = timedelta(days=7)
# Limite plus longue pour les chefs/trez
# (qui ont la permission kfet.access_old_history)
KFET_HISTORY_LONG_DATE_LIMIT = timedelta(days=30)
# These accounts don't represent actual people and can be freely accessed
# Identification based on trigrammes
KFET_HISTORY_NO_DATE_LIMIT_TRIGRAMMES = ["LIQ", "#13"]
KFET_HISTORY_NO_DATE_LIMIT = datetime(1794, 10, 30) # AKA the distant past
##
# Database configuration
DATABASES = credentials.get_json(
"DATABASES",
default={
"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",
},
},
)
CHANNEL_LAYERS = credentials.get_json(
"CHANNEL_LAYERS",
default={
"default": {
"BACKEND": "channels.layers.InMemoryChannelLayer",
}
},
)
CORS_ORIGIN_WHITELIST = credentials.get("CORS_ORIGIN_WHITELIST", [])
SITE_ID = 1
###
# Staticfiles configuration
STATIC_ROOT = credentials["STATIC_ROOT"]
STATIC_URL = "/static/"
MEDIA_ROOT = credentials.get("MEDIA_ROOT", (BASE_DIR / "media"))
MEDIA_URL = "/media/"
##
# Authentication configuration
AUTHENTICATION_BACKENDS = [
"kfet.auth.backends.BlockFrozenAccountBackend", # Must be in first
"django.contrib.auth.backends.ModelBackend",
"gestioncof.shared.COFCASBackend",
"kfet.auth.backends.GenericBackend",
]
LOGIN_URL = "cof-login"
LOGIN_REDIRECT_URL = reverse_lazy("home")
# FIXME: Switch to authens
CAS_SERVER_URL = "https://cas.eleves.ens.fr/"
CAS_VERSION = "2"
CAS_LOGIN_MSG = None
CAS_IGNORE_REFERER = True
CAS_REDIRECT_URL = "/"
CAS_EMAIL_FORMAT = "%s@clipper.ens.fr"
##
# h-captcha configuration
HCAPTCHA_SITEKEY = credentials["HCAPTCHA_SITEKEY"]
HCAPTCHA_SECRET = credentials["HCAPTCHA_SECRET"]
##
# K-Fêt token for the openness indicator
KFETOPEN_TOKEN = credentials["KFETOPEN_TOKEN"]
##
# Mail configuration
MAIL_DATA = {
"petits_cours": {
"FROM": "Le COF <cof@ens.fr>",
"BCC": "archivescof@gmail.com",
"REPLYTO": "cof@ens.fr",
},
"rappels": {
"FROM": "Le BdA <bda@ens.fr>",
"REPLYTO": "Le BdA <bda@ens.fr>",
},
"rappel_negatif": {
"FROM": "La K-Fêt <chefs-k-fet@ens.fr>",
"REPLYTO": "La K-Fêt <chefs-k-fet@ens.fr>",
},
"revente": {
"FROM": "BdA-Revente <bda-revente@ens.fr>",
"REPLYTO": "BdA-Revente <bda-revente@ens.fr>",
},
}
# ---
# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/
# ---
LANGUAGE_CODE = "fr-fr"
TIME_ZONE = "Europe/Paris"
USE_I18N = True
USE_L10N = True
USE_TZ = True
LANGUAGES = (("fr", "Français"), ("en", "English"))
FORMAT_MODULE_PATH = "gestioasso.locale"
##
# Development configuration
if DEBUG:
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
def show_toolbar(request):
"""
On active la debug-toolbar en mode développement local sauf :
- dans l'admin où ça ne sert pas à grand chose;
- si la variable d'environnement DJANGO_NO_DDT est à 1 → ça permet de la désactiver
sans modifier ce fichier en exécutant `export DJANGO_NO_DDT=1` dans le terminal
qui lance `./manage.py runserver`.
Autre side effect de cette fonction : on ne fait pas la vérification de INTERNAL_IPS
que ferait la debug-toolbar par défaut, ce qui la fait fonctionner aussi à
l'intérieur de Vagrant (comportement non testé depuis un moment…)
"""
env_no_ddt = bool(os.environ.get("DJANGO_NO_DDT", None))
return not (env_no_ddt or request.path.startswith("/admin/"))
##
# Django Debug Toolbar configuration
DEBUG_TOOLBAR_CONFIG = {"SHOW_TOOLBAR_CALLBACK": show_toolbar}
INSTALLED_APPS += ["debug_toolbar"]
MIDDLEWARE = ["debug_toolbar.middleware.DebugToolbarMiddleware"] + MIDDLEWARE

View file

@ -1,7 +1,6 @@
"""
Fichier principal de configuration des urls du projet GestioCOF
"""
from django.conf import settings
from django.conf.urls.i18n import i18n_patterns
from django.conf.urls.static import static
@ -36,7 +35,7 @@ app_dict = {
"events": "gestion/event_v2/", # the events module is still experimental !
"authens": "gestion/authens/",
}
for app_name, url_prefix in app_dict.items():
for (app_name, url_prefix) in app_dict.items():
if app_name in settings.INSTALLED_APPS:
urlpatterns += [path(url_prefix, include("{}.urls".format(app_name)))]
@ -59,10 +58,10 @@ if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# Wagtail URLs (wagtail urls must be last, as catch-all)
if "wagtail" in settings.INSTALLED_APPS:
from wagtail import urls as wagtail_urls
# Wagtail URLs (wagtail.core urls must be last, as catch-all)
if "wagtail.core" in settings.INSTALLED_APPS:
from wagtail.admin import urls as wagtailadmin_urls
from wagtail.core import urls as wagtail_urls
from wagtail.documents import urls as wagtaildocs_urls
urlpatterns += [

View file

@ -0,0 +1 @@
default_app_config = "gestioncof.apps.GestioncofConfig"

View file

@ -6,7 +6,7 @@ from django.contrib.auth.models import Group, Permission, User
from django.db.models import Q
from django.urls import reverse
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
from django.utils.translation import ugettext_lazy as _
from gestioncof.models import (
Club,

View file

@ -0,0 +1 @@
default_app_config = "gestioncof.cms.apps.COFCMSAppConfig"

View file

@ -3,9 +3,9 @@
from __future__ import unicode_literals
import django.db.models.deletion
import wagtail.blocks
import wagtail.contrib.routable_page.models
import wagtail.fields
import wagtail.core.blocks
import wagtail.core.fields
import wagtail.images.blocks
from django.db import migrations, models
@ -13,6 +13,7 @@ import gestioncof.cms.models
class Migration(migrations.Migration):
initial = True
dependencies = [
@ -72,14 +73,18 @@ class Migration(migrations.Migration):
blank=True, null=True, verbose_name="Description rapide"
),
),
("body", wagtail.fields.RichTextField(verbose_name="Contenu")),
("body", wagtail.core.fields.RichTextField(verbose_name="Contenu")),
(
"body_fr",
wagtail.fields.RichTextField(null=True, verbose_name="Contenu"),
wagtail.core.fields.RichTextField(
null=True, verbose_name="Contenu"
),
),
(
"body_en",
wagtail.fields.RichTextField(null=True, verbose_name="Contenu"),
wagtail.core.fields.RichTextField(
null=True, verbose_name="Contenu"
),
),
(
"is_event",
@ -134,40 +139,46 @@ class Migration(migrations.Migration):
to="wagtailcore.Page",
),
),
("body", wagtail.fields.RichTextField(verbose_name="Description")),
("body", wagtail.core.fields.RichTextField(verbose_name="Description")),
(
"body_fr",
wagtail.fields.RichTextField(null=True, verbose_name="Description"),
wagtail.core.fields.RichTextField(
null=True, verbose_name="Description"
),
),
(
"body_en",
wagtail.fields.RichTextField(null=True, verbose_name="Description"),
wagtail.core.fields.RichTextField(
null=True, verbose_name="Description"
),
),
(
"links",
wagtail.fields.StreamField(
wagtail.core.fields.StreamField(
[
(
"lien",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
(
"url",
wagtail.blocks.URLBlock(required=True),
wagtail.core.blocks.URLBlock(required=True),
),
("texte", wagtail.blocks.CharBlock()),
("texte", wagtail.core.blocks.CharBlock()),
]
),
),
(
"contact",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
(
"email",
wagtail.blocks.EmailBlock(required=True),
wagtail.core.blocks.EmailBlock(
required=True
),
),
("texte", wagtail.blocks.CharBlock()),
("texte", wagtail.core.blocks.CharBlock()),
]
),
),
@ -176,29 +187,31 @@ class Migration(migrations.Migration):
),
(
"links_fr",
wagtail.fields.StreamField(
wagtail.core.fields.StreamField(
[
(
"lien",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
(
"url",
wagtail.blocks.URLBlock(required=True),
wagtail.core.blocks.URLBlock(required=True),
),
("texte", wagtail.blocks.CharBlock()),
("texte", wagtail.core.blocks.CharBlock()),
]
),
),
(
"contact",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
(
"email",
wagtail.blocks.EmailBlock(required=True),
wagtail.core.blocks.EmailBlock(
required=True
),
),
("texte", wagtail.blocks.CharBlock()),
("texte", wagtail.core.blocks.CharBlock()),
]
),
),
@ -208,29 +221,31 @@ class Migration(migrations.Migration):
),
(
"links_en",
wagtail.fields.StreamField(
wagtail.core.fields.StreamField(
[
(
"lien",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
(
"url",
wagtail.blocks.URLBlock(required=True),
wagtail.core.blocks.URLBlock(required=True),
),
("texte", wagtail.blocks.CharBlock()),
("texte", wagtail.core.blocks.CharBlock()),
]
),
),
(
"contact",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
(
"email",
wagtail.blocks.EmailBlock(required=True),
wagtail.core.blocks.EmailBlock(
required=True
),
),
("texte", wagtail.blocks.CharBlock()),
("texte", wagtail.core.blocks.CharBlock()),
]
),
),
@ -272,17 +287,17 @@ class Migration(migrations.Migration):
),
(
"introduction",
wagtail.fields.RichTextField(verbose_name="Introduction"),
wagtail.core.fields.RichTextField(verbose_name="Introduction"),
),
(
"introduction_fr",
wagtail.fields.RichTextField(
wagtail.core.fields.RichTextField(
null=True, verbose_name="Introduction"
),
),
(
"introduction_en",
wagtail.fields.RichTextField(
wagtail.core.fields.RichTextField(
null=True, verbose_name="Introduction"
),
),
@ -315,27 +330,27 @@ class Migration(migrations.Migration):
),
(
"body",
wagtail.fields.StreamField(
wagtail.core.fields.StreamField(
[
(
"heading",
wagtail.blocks.CharBlock(classname="full title"),
wagtail.core.blocks.CharBlock(classname="full title"),
),
("paragraph", wagtail.blocks.RichTextBlock()),
("paragraph", wagtail.core.blocks.RichTextBlock()),
("image", wagtail.images.blocks.ImageChooserBlock()),
(
"iframe",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
(
"url",
wagtail.blocks.URLBlock(
wagtail.core.blocks.URLBlock(
"Adresse de la page"
),
),
(
"height",
wagtail.blocks.CharBlock(
wagtail.core.blocks.CharBlock(
"Hauteur (en pixels)"
),
),
@ -347,27 +362,27 @@ class Migration(migrations.Migration):
),
(
"body_fr",
wagtail.fields.StreamField(
wagtail.core.fields.StreamField(
[
(
"heading",
wagtail.blocks.CharBlock(classname="full title"),
wagtail.core.blocks.CharBlock(classname="full title"),
),
("paragraph", wagtail.blocks.RichTextBlock()),
("paragraph", wagtail.core.blocks.RichTextBlock()),
("image", wagtail.images.blocks.ImageChooserBlock()),
(
"iframe",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
(
"url",
wagtail.blocks.URLBlock(
wagtail.core.blocks.URLBlock(
"Adresse de la page"
),
),
(
"height",
wagtail.blocks.CharBlock(
wagtail.core.blocks.CharBlock(
"Hauteur (en pixels)"
),
),
@ -380,27 +395,27 @@ class Migration(migrations.Migration):
),
(
"body_en",
wagtail.fields.StreamField(
wagtail.core.fields.StreamField(
[
(
"heading",
wagtail.blocks.CharBlock(classname="full title"),
wagtail.core.blocks.CharBlock(classname="full title"),
),
("paragraph", wagtail.blocks.RichTextBlock()),
("paragraph", wagtail.core.blocks.RichTextBlock()),
("image", wagtail.images.blocks.ImageChooserBlock()),
(
"iframe",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
(
"url",
wagtail.blocks.URLBlock(
wagtail.core.blocks.URLBlock(
"Adresse de la page"
),
),
(
"height",
wagtail.blocks.CharBlock(
wagtail.core.blocks.CharBlock(
"Hauteur (en pixels)"
),
),
@ -434,17 +449,17 @@ class Migration(migrations.Migration):
),
(
"introduction",
wagtail.fields.RichTextField(verbose_name="Introduction"),
wagtail.core.fields.RichTextField(verbose_name="Introduction"),
),
(
"introduction_fr",
wagtail.fields.RichTextField(
wagtail.core.fields.RichTextField(
null=True, verbose_name="Introduction"
),
),
(
"introduction_en",
wagtail.fields.RichTextField(
wagtail.core.fields.RichTextField(
null=True, verbose_name="Introduction"
),
),

View file

@ -4,6 +4,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("cofcms", "0001_initial")]
operations = [

View file

@ -1,11 +1,12 @@
# Generated by Django 2.2.8 on 2019-12-20 16:22
import wagtail.blocks
import wagtail.fields
import wagtail.core.blocks
import wagtail.core.fields
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("cofcms", "0002_auto_20190523_1521"),
]
@ -14,26 +15,26 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name="cofdirectoryentrypage",
name="links",
field=wagtail.fields.StreamField(
field=wagtail.core.fields.StreamField(
[
(
"lien",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
("url", wagtail.blocks.URLBlock(required=True)),
("texte", wagtail.blocks.CharBlock()),
("url", wagtail.core.blocks.URLBlock(required=True)),
("texte", wagtail.core.blocks.CharBlock()),
]
),
),
(
"contact",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
(
"email",
wagtail.blocks.EmailBlock(required=True),
wagtail.core.blocks.EmailBlock(required=True),
),
("texte", wagtail.blocks.CharBlock()),
("texte", wagtail.core.blocks.CharBlock()),
]
),
),
@ -44,26 +45,26 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name="cofdirectoryentrypage",
name="links_en",
field=wagtail.fields.StreamField(
field=wagtail.core.fields.StreamField(
[
(
"lien",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
("url", wagtail.blocks.URLBlock(required=True)),
("texte", wagtail.blocks.CharBlock()),
("url", wagtail.core.blocks.URLBlock(required=True)),
("texte", wagtail.core.blocks.CharBlock()),
]
),
),
(
"contact",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
(
"email",
wagtail.blocks.EmailBlock(required=True),
wagtail.core.blocks.EmailBlock(required=True),
),
("texte", wagtail.blocks.CharBlock()),
("texte", wagtail.core.blocks.CharBlock()),
]
),
),
@ -75,26 +76,26 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name="cofdirectoryentrypage",
name="links_fr",
field=wagtail.fields.StreamField(
field=wagtail.core.fields.StreamField(
[
(
"lien",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
("url", wagtail.blocks.URLBlock(required=True)),
("texte", wagtail.blocks.CharBlock()),
("url", wagtail.core.blocks.URLBlock(required=True)),
("texte", wagtail.core.blocks.CharBlock()),
]
),
),
(
"contact",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
(
"email",
wagtail.blocks.EmailBlock(required=True),
wagtail.core.blocks.EmailBlock(required=True),
),
("texte", wagtail.blocks.CharBlock()),
("texte", wagtail.core.blocks.CharBlock()),
]
),
),

View file

@ -1,11 +1,12 @@
# Generated by Django 2.2.15 on 2020-08-29 21:14
import wagtail.blocks
import wagtail.fields
import wagtail.core.blocks
import wagtail.core.fields
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("cofcms", "0003_directory_entry_optional_links"),
]
@ -14,35 +15,35 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name="cofdirectoryentrypage",
name="links",
field=wagtail.fields.StreamField(
field=wagtail.core.fields.StreamField(
[
(
"lien",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
("url", wagtail.blocks.URLBlock(required=True)),
("texte", wagtail.blocks.CharBlock()),
("url", wagtail.core.blocks.URLBlock(required=True)),
("texte", wagtail.core.blocks.CharBlock()),
]
),
),
(
"contact",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
(
"email",
wagtail.blocks.EmailBlock(required=True),
wagtail.core.blocks.EmailBlock(required=True),
),
("texte", wagtail.blocks.CharBlock()),
("texte", wagtail.core.blocks.CharBlock()),
]
),
),
(
"info",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
("nom", wagtail.blocks.CharBlock(required=False)),
("texte", wagtail.blocks.CharBlock(required=True)),
("nom", wagtail.core.blocks.CharBlock(required=False)),
("texte", wagtail.core.blocks.CharBlock(required=True)),
]
),
),
@ -53,35 +54,35 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name="cofdirectoryentrypage",
name="links_en",
field=wagtail.fields.StreamField(
field=wagtail.core.fields.StreamField(
[
(
"lien",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
("url", wagtail.blocks.URLBlock(required=True)),
("texte", wagtail.blocks.CharBlock()),
("url", wagtail.core.blocks.URLBlock(required=True)),
("texte", wagtail.core.blocks.CharBlock()),
]
),
),
(
"contact",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
(
"email",
wagtail.blocks.EmailBlock(required=True),
wagtail.core.blocks.EmailBlock(required=True),
),
("texte", wagtail.blocks.CharBlock()),
("texte", wagtail.core.blocks.CharBlock()),
]
),
),
(
"info",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
("nom", wagtail.blocks.CharBlock(required=False)),
("texte", wagtail.blocks.CharBlock(required=True)),
("nom", wagtail.core.blocks.CharBlock(required=False)),
("texte", wagtail.core.blocks.CharBlock(required=True)),
]
),
),
@ -93,35 +94,35 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name="cofdirectoryentrypage",
name="links_fr",
field=wagtail.fields.StreamField(
field=wagtail.core.fields.StreamField(
[
(
"lien",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
("url", wagtail.blocks.URLBlock(required=True)),
("texte", wagtail.blocks.CharBlock()),
("url", wagtail.core.blocks.URLBlock(required=True)),
("texte", wagtail.core.blocks.CharBlock()),
]
),
),
(
"contact",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
(
"email",
wagtail.blocks.EmailBlock(required=True),
wagtail.core.blocks.EmailBlock(required=True),
),
("texte", wagtail.blocks.CharBlock()),
("texte", wagtail.core.blocks.CharBlock()),
]
),
),
(
"info",
wagtail.blocks.StructBlock(
wagtail.core.blocks.StructBlock(
[
("nom", wagtail.blocks.CharBlock(required=False)),
("texte", wagtail.blocks.CharBlock(required=True)),
("nom", wagtail.core.blocks.CharBlock(required=False)),
("texte", wagtail.core.blocks.CharBlock(required=True)),
]
),
),

View file

@ -1,203 +0,0 @@
# Generated by Django 4.2.17 on 2024-12-19 12:27
import wagtail.blocks
import wagtail.fields
import wagtail.images.blocks
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("cofcms", "0004_auto_20200829_2314"),
]
operations = [
migrations.AlterField(
model_name="cofdirectoryentrypage",
name="links",
field=wagtail.fields.StreamField(
[
(
"lien",
wagtail.blocks.StructBlock(
[
("url", wagtail.blocks.URLBlock(required=True)),
("texte", wagtail.blocks.CharBlock()),
]
),
),
(
"contact",
wagtail.blocks.StructBlock(
[
("email", wagtail.blocks.EmailBlock(required=True)),
("texte", wagtail.blocks.CharBlock()),
]
),
),
(
"info",
wagtail.blocks.StructBlock(
[
("nom", wagtail.blocks.CharBlock(required=False)),
("texte", wagtail.blocks.CharBlock(required=True)),
]
),
),
],
blank=True,
use_json_field=True,
),
),
migrations.AlterField(
model_name="cofdirectoryentrypage",
name="links_en",
field=wagtail.fields.StreamField(
[
(
"lien",
wagtail.blocks.StructBlock(
[
("url", wagtail.blocks.URLBlock(required=True)),
("texte", wagtail.blocks.CharBlock()),
]
),
),
(
"contact",
wagtail.blocks.StructBlock(
[
("email", wagtail.blocks.EmailBlock(required=True)),
("texte", wagtail.blocks.CharBlock()),
]
),
),
(
"info",
wagtail.blocks.StructBlock(
[
("nom", wagtail.blocks.CharBlock(required=False)),
("texte", wagtail.blocks.CharBlock(required=True)),
]
),
),
],
blank=True,
null=True,
use_json_field=True,
),
),
migrations.AlterField(
model_name="cofdirectoryentrypage",
name="links_fr",
field=wagtail.fields.StreamField(
[
(
"lien",
wagtail.blocks.StructBlock(
[
("url", wagtail.blocks.URLBlock(required=True)),
("texte", wagtail.blocks.CharBlock()),
]
),
),
(
"contact",
wagtail.blocks.StructBlock(
[
("email", wagtail.blocks.EmailBlock(required=True)),
("texte", wagtail.blocks.CharBlock()),
]
),
),
(
"info",
wagtail.blocks.StructBlock(
[
("nom", wagtail.blocks.CharBlock(required=False)),
("texte", wagtail.blocks.CharBlock(required=True)),
]
),
),
],
blank=True,
null=True,
use_json_field=True,
),
),
migrations.AlterField(
model_name="cofpage",
name="body",
field=wagtail.fields.StreamField(
[
("heading", wagtail.blocks.CharBlock(form_classname="full title")),
("paragraph", wagtail.blocks.RichTextBlock()),
("image", wagtail.images.blocks.ImageChooserBlock()),
(
"iframe",
wagtail.blocks.StructBlock(
[
("url", wagtail.blocks.URLBlock("Adresse de la page")),
(
"height",
wagtail.blocks.CharBlock("Hauteur (en pixels)"),
),
]
),
),
],
use_json_field=True,
),
),
migrations.AlterField(
model_name="cofpage",
name="body_en",
field=wagtail.fields.StreamField(
[
("heading", wagtail.blocks.CharBlock(form_classname="full title")),
("paragraph", wagtail.blocks.RichTextBlock()),
("image", wagtail.images.blocks.ImageChooserBlock()),
(
"iframe",
wagtail.blocks.StructBlock(
[
("url", wagtail.blocks.URLBlock("Adresse de la page")),
(
"height",
wagtail.blocks.CharBlock("Hauteur (en pixels)"),
),
]
),
),
],
null=True,
use_json_field=True,
),
),
migrations.AlterField(
model_name="cofpage",
name="body_fr",
field=wagtail.fields.StreamField(
[
("heading", wagtail.blocks.CharBlock(form_classname="full title")),
("paragraph", wagtail.blocks.RichTextBlock()),
("image", wagtail.images.blocks.ImageChooserBlock()),
(
"iframe",
wagtail.blocks.StructBlock(
[
("url", wagtail.blocks.URLBlock("Adresse de la page")),
(
"height",
wagtail.blocks.CharBlock("Hauteur (en pixels)"),
),
]
),
),
],
null=True,
use_json_field=True,
),
),
]

View file

@ -1,11 +1,12 @@
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from django.db import models
from wagtail import blocks
from wagtail.admin.panels import FieldPanel
from wagtail.admin.edit_handlers import FieldPanel, StreamFieldPanel
from wagtail.contrib.routable_page.models import RoutablePageMixin, route
from wagtail.fields import RichTextField, StreamField
from wagtail.core import blocks
from wagtail.core.fields import RichTextField, StreamField
from wagtail.core.models import Page
from wagtail.images.blocks import ImageChooserBlock
from wagtail.models import Page
from wagtail.images.edit_handlers import ImageChooserPanel
# Page pouvant afficher des actualités
@ -68,11 +69,10 @@ class COFPage(Page):
("paragraph", blocks.RichTextBlock()),
("image", ImageChooserBlock()),
("iframe", IFrameBlock()),
],
use_json_field=True,
]
)
content_panels = Page.content_panels + [FieldPanel("body")]
content_panels = Page.content_panels + [StreamFieldPanel("body")]
subpage_types = ["COFDirectoryPage", "COFPage"]
parent_page_types = ["COFPage", "COFRootPage"]
@ -127,7 +127,7 @@ class COFActuPage(RoutablePageMixin, Page):
all_day = models.BooleanField("Toute la journée", default=False, blank=True)
content_panels = Page.content_panels + [
FieldPanel("image"),
ImageChooserPanel("image"),
FieldPanel("chapo"),
FieldPanel("body", classname="full"),
FieldPanel("is_event"),
@ -204,7 +204,6 @@ class COFDirectoryEntryPage(Page):
),
],
blank=True,
use_json_field=True,
)
image = models.ForeignKey(
@ -217,9 +216,9 @@ class COFDirectoryEntryPage(Page):
)
content_panels = Page.content_panels + [
FieldPanel("image"),
ImageChooserPanel("image"),
FieldPanel("body", classname="full"),
FieldPanel("links"),
StreamFieldPanel("links"),
]
subpage_types = []

View file

@ -33,19 +33,19 @@
<nav>
{% flat_menu "cof-nav-int" template="cofcms/base_nav.html" apply_active_classes=True %}
{% get_current_language as curlang %}
{% get_current_language as curlang %}
<div class="lang-select">
<div class="lang-select">
{% if curlang == 'en' %}
{% language 'fr' %}
<a href="{% pageurl self %}" title="Français"><img src="{% static "cofcms/images/fr.png" %}"></a>
{% endlanguage %}
{% language 'fr' %}
<a href="{% pageurl self %}" title="Français"><img src="{% static "cofcms/images/fr.png" %}"></a>
{% endlanguage %}
{% else %}
{% language 'en' %}
<a href="{% pageurl self %}" title="English"><img src="{% static "cofcms/images/en.png" %}"></a>
{% language 'en' %}
<a href="{% pageurl self %}" title="English"><img src="{% static "cofcms/images/en.png" %}"></a>
{% endlanguage %}
{% endif %}
</div>
</div>
</nav>
</section>
</header>

View file

@ -17,16 +17,16 @@
{% block content %}
<section class="intro">
<h1>{{ page.title }}</h1>
<div>{{ page.introduction|richtext }}</div>
<div>{{ page.introduction|safe }}</div>
</section>
<section class="actulist">
{% if actus.has_previous %}
<a class="block prev-actus" href="?page={{ actus.previous_page_number }}{% for key,value in request.GET.items %}{% ifnotequal key 'page' %}&amp;{{ key }}={{ value }}{% endifnotequal %}{% endfor %}">{% trans "Actualités plus récentes" %}</a>
{% endif %}
<a class="block prev-actus" href="?page={{ actus.previous_page_number }}{% for key,value in request.GET.items %}{% ifnotequal key 'page' %}&amp;{{ key }}={{ value }}{% endifnotequal %}{% endfor %}">{% trans "Actualités plus récentes" %}</a>
{% endif %}
{% if actus.has_next %}
<a class="block next-actus" href="?page={{ actus.next_page_number }}{% for key,value in request.GET.items %}{% ifnotequal key 'page' %}&amp;{{ key }}={{ value }}{% endifnotequal %}{% endfor %}">{% trans "Actualités plus anciennes" %}</a>
{% endif %}
<a class="block next-actus" href="?page={{ actus.next_page_number }}{% for key,value in request.GET.items %}{% ifnotequal key 'page' %}&amp;{{ key }}={{ value }}{% endifnotequal %}{% endfor %}">{% trans "Actualités plus anciennes" %}</a>
{% endif %}
{% for actu in page.actus %}
<article class="actu">
@ -36,7 +36,7 @@
{% if actu.is_event %}
<p><span class="actu-dates">{{ actu|dates|capfirst }}</span><br />{{ actu.chapo }}</p>
{% else %}
{{ actu.body|richtext|truncatewords_html:15 }}
{{ actu.body|safe|truncatewords_html:15 }}
{% endif %}
<a href="{% pageurl actu %}">{% trans "Lire plus" %} &gt;</a>
</div>
@ -44,10 +44,10 @@
{% endfor %}
{% if actus.has_previous %}
<a class="block prev-actus" href="?page={{ actus.previous_page_number }}{% for key,value in request.GET.items %}{% ifnotequal key 'page' %}&amp;{{ key }}={{ value }}{% endifnotequal %}{% endfor %}">{% trans "Actualités plus récentes" %}</a>
{% endif %}
<a class="block prev-actus" href="?page={{ actus.previous_page_number }}{% for key,value in request.GET.items %}{% ifnotequal key 'page' %}&amp;{{ key }}={{ value }}{% endifnotequal %}{% endfor %}">{% trans "Actualités plus récentes" %}</a>
{% endif %}
{% if actus.has_next %}
<a class="block next-actus" href="?page={{ actus.next_page_number }}{% for key,value in request.GET.items %}{% ifnotequal key 'page' %}&amp;{{ key }}={{ value }}{% endifnotequal %}{% endfor %}">{% trans "Actualités plus anciennes" %}</a>
{% endif %}
<a class="block next-actus" href="?page={{ actus.next_page_number }}{% for key,value in request.GET.items %}{% ifnotequal key 'page' %}&amp;{{ key }}={{ value }}{% endifnotequal %}{% endfor %}">{% trans "Actualités plus anciennes" %}</a>
{% endif %}
</section>
{% endblock %}

View file

@ -1,5 +1,5 @@
{% extends "cofcms/base.html" %}
{% load wagtailcore_tags wagtailimages_tags cofcms_tags i18n %}
{% load wagtailimages_tags cofcms_tags i18n %}
{% block content %}
<section class="intro">
@ -11,7 +11,7 @@
<section class="pagecontent">
<div class="image">{% image page.image width-700 %}</div>
<article>
{{ page.body|richtext }}
{{ page.body|safe }}
</article>
</section>
{% endblock %}

View file

@ -1,5 +1,5 @@
{% extends "cofcms/base_aside.html" %}
{% load wagtailcore_tags wagtailimages_tags cofcms_tags static i18n %}
{% load wagtailimages_tags cofcms_tags static i18n %}
{% block extra_head %}
{{ block.super }}
@ -18,7 +18,7 @@
{% block content %}
<section class="intro">
<h1>{{ page.title }}</h1>
<div>{{ page.introduction|richtext }}</div>
<div>{{ page.introduction|safe }}</div>
</section>
<section class="directory">
@ -28,7 +28,7 @@
<div class="entry-image">{% image entry.image width-150 class="entry-img" %}</div>
{% endif %}
<h2>{{ entry.title }}</h2>
<div class="desc">{{ entry.body|richtext }}</div>
<div class="desc">{{ entry.body|safe }}</div>
{% if entry.links %}
<ul class="links">
{% for block in entry.links %}

View file

@ -1,10 +1,10 @@
{% extends "cofcms/base.html" %}
{% load wagtailcore_tags wagtailimages_tags cofcms_tags %}
{% load wagtailimages_tags cofcms_tags %}
{% block content %}
<section class="intro">
<h1>{{ page.title }}</h1>
<div>{{ page.introduction|richtext }}</div>
<div>{{ page.introduction|safe }}</div>
</section>
<section class="pagecontent">
@ -13,7 +13,7 @@
<h2>{{ block.value }}</h2>
{% elif block.block_type == "paragraph" %}
<article class="paragraph">
{{ block.value|richtext }}
{{ block.value|safe }}
</article>
{% elif block.block_type == "image" %}
<div class="image">

View file

@ -18,7 +18,7 @@
{% block content %}
<section class="intro">
<h1>{{ page.title }}</h1>
<div>{{ page.introduction|richtext }}</div>
<div>{{ page.introduction|safe }}</div>
</section>
<section class="actuhome">
@ -31,7 +31,7 @@
{% if actu.is_event %}
<span class="actu-minical">{% mini_calendar actu %}</span><span class="actu-dates">{{ actu|dates }}</span>
{% else %}
{{ actu.body|richtext|truncatewords_html:10 }}
{{ actu.body|safe|truncatewords_html:10 }}
{% endif %}
</div>
<a href="{% pageurl actu %}" class="actu-overlay"></a>

View file

@ -2,7 +2,7 @@ from datetime import date, timedelta
from django import template
from django.utils import formats, timezone
from django.utils.translation import gettext as _
from django.utils.translation import ugettext as _
from ..models import COFActuPage, COFRootPage

View file

@ -3,7 +3,7 @@ from django.contrib.auth import get_user_model
from django.contrib.auth.forms import AuthenticationForm
from django.forms.formsets import BaseFormSet, formset_factory
from django.forms.widgets import CheckboxSelectMultiple, RadioSelect
from django.utils.translation import gettext_lazy as _
from django.utils.translation import ugettext_lazy as _
from djconfig.forms import ConfigForm
from bda.models import Spectacle
@ -276,9 +276,7 @@ class RegistrationProfileForm(forms.ModelForm):
self.fields["mailing_bda_revente"].initial = True
self.fields["mailing_unernestaparis"].initial = True
class Meta:
model = CofProfile
fields = [
self.fields.keyOrder = [
"login_clipper",
"phone",
"occupation",
@ -292,6 +290,22 @@ class RegistrationProfileForm(forms.ModelForm):
"comments",
]
class Meta:
model = CofProfile
fields = (
"login_clipper",
"phone",
"occupation",
"departement",
"is_cof",
"type_cotiz",
"mailing_cof",
"mailing_bda",
"mailing_bda_revente",
"mailing_unernestaparis",
"comments",
)
STATUS_CHOICES = (
("no", "Non"),

View file

@ -6,6 +6,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)]
operations = [

View file

@ -5,6 +5,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("gestioncof", "0001_initial")]
operations = [

View file

@ -5,6 +5,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("gestioncof", "0002_enable_unprocessed_demandes")]
operations = [

Some files were not shown because too many files have changed in this diff Show more