Merge branch 'archicubes' into 'master'
Accès archicubes See merge request klub-dev-ens/experiENS!5
This commit is contained in:
commit
bc17ff9e7c
25 changed files with 958 additions and 232 deletions
20
avisstage/allauth_adapter.py
Normal file
20
avisstage/allauth_adapter.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
from allauth.account.adapter import DefaultAccountAdapter
|
||||||
|
from allauth_ens.adapter import LongTermClipperAccountAdapter
|
||||||
|
|
||||||
|
class AccountAdapter(DefaultAccountAdapter):
|
||||||
|
def is_open_for_signup(self, request):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class SocialAccountAdapter(LongTermClipperAccountAdapter):
|
||||||
|
def is_open_for_signup(self, request, sociallogin):
|
||||||
|
# sociallogin.account is a SocialAccount instance.
|
||||||
|
# See https://github.com/pennersr/django-allauth/blob/master/allauth/socialaccount/models.py
|
||||||
|
|
||||||
|
if sociallogin.account.provider == 'clipper':
|
||||||
|
return True
|
||||||
|
|
||||||
|
# It returns AccountAdapter.is_open_for_signup().
|
||||||
|
# See https://github.com/pennersr/django-allauth/blob/master/allauth/socialaccount/adapter.py
|
||||||
|
return super().is_open_for_signup(request, sociallogin)
|
||||||
|
|
|
@ -9,10 +9,16 @@ from django.urls import reverse
|
||||||
|
|
||||||
from .models import Lieu, Stage, Normalien, StageMatiere
|
from .models import Lieu, Stage, Normalien, StageMatiere
|
||||||
|
|
||||||
|
class EnScolariteAuthentication(SessionAuthentication):
|
||||||
|
def is_authenticated(self, request, **kwargs):
|
||||||
|
if super().is_authenticated(request, **kwargs):
|
||||||
|
return request.user.profil.en_scolarite
|
||||||
|
return False
|
||||||
|
|
||||||
# API principale pour les lieux
|
# API principale pour les lieux
|
||||||
class LieuResource(ModelResource):
|
class LieuResource(ModelResource):
|
||||||
stages = fields.ToManyField("avisstage.api.StageResource",
|
#stages = fields.ToManyField("avisstage.api.StageResource",
|
||||||
"stages", use_in="detail", full=True)
|
# "stages", use_in="detail", full=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
queryset = Lieu.objects.all()
|
queryset = Lieu.objects.all()
|
||||||
|
@ -74,7 +80,7 @@ class StageResource(ModelResource):
|
||||||
fields = ["sujet", "date_debut", "date_fin", "matieres", "id"]
|
fields = ["sujet", "date_debut", "date_fin", "matieres", "id"]
|
||||||
|
|
||||||
#login_required
|
#login_required
|
||||||
authentication = SessionAuthentication()
|
authentication = EnScolariteAuthentication()
|
||||||
|
|
||||||
# Filtres personnalisés
|
# Filtres personnalisés
|
||||||
def build_filters(self, filters=None, **kwargs):
|
def build_filters(self, filters=None, **kwargs):
|
||||||
|
@ -114,4 +120,4 @@ class AuteurResource(ModelResource):
|
||||||
fields = ["id", "nom", "stages"]
|
fields = ["id", "nom", "stages"]
|
||||||
|
|
||||||
#login_required
|
#login_required
|
||||||
authentication = SessionAuthentication()
|
authentication = EnScolariteAuthentication()
|
||||||
|
|
12
avisstage/decorators.py
Normal file
12
avisstage/decorators.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
|
||||||
|
def en_scolarite_required(view_func):
|
||||||
|
@wraps(view_func)
|
||||||
|
def _wrapped_view(request, *args, **kwargs):
|
||||||
|
if request.user.profil.en_scolarite:
|
||||||
|
return view_func(request, *args, **kwargs)
|
||||||
|
return redirect(reverse("avisstage:403-archicubes"))
|
||||||
|
return _wrapped_view
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from allauth.account.models import EmailAddress
|
||||||
|
from allauth.socialaccount.models import SocialAccount
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.signals import post_save
|
from django.db.models.signals import post_save
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
@ -9,7 +12,9 @@ from django.contrib.gis.db import models as geomodels
|
||||||
from django.template.defaultfilters import slugify
|
from django.template.defaultfilters import slugify
|
||||||
from django.forms.widgets import DateInput
|
from django.forms.widgets import DateInput
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.utils.functional import cached_property
|
||||||
from django.utils.html import strip_tags
|
from django.utils.html import strip_tags
|
||||||
|
|
||||||
from taggit_autosuggest.managers import TaggableManager
|
from taggit_autosuggest.managers import TaggableManager
|
||||||
|
@ -47,54 +52,52 @@ class Normalien(models.Model):
|
||||||
def stages_publics(self):
|
def stages_publics(self):
|
||||||
return self.stages.filter(public=True).order_by('-date_debut')
|
return self.stages.filter(public=True).order_by('-date_debut')
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def en_scolarite(self):
|
||||||
|
return SocialAccount.objects.filter(user_id=self.user_id,
|
||||||
|
provider="clipper").exists()
|
||||||
|
|
||||||
|
def has_nonENS_email(self):
|
||||||
|
a = EmailAddress.objects.filter(user_id=self.user_id,
|
||||||
|
verified=True) \
|
||||||
|
.exclude(email__endswith="ens.fr")
|
||||||
|
return a.exists()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def preferred_email(self):
|
||||||
|
a = EmailAddress.objects.filter(user_id=self.user_id,
|
||||||
|
verified=True) \
|
||||||
|
.exclude(email__endswith="ens.fr")\
|
||||||
|
.order_by('-primary')
|
||||||
|
if len(a) == 0:
|
||||||
|
a = EmailAddress.objects.filter(user_id=self.user_id,
|
||||||
|
verified=True) \
|
||||||
|
.order_by('-primary')
|
||||||
|
if len(a) == 0:
|
||||||
|
return ""
|
||||||
|
else:
|
||||||
|
return a[0].email
|
||||||
|
|
||||||
# Hook à la création d'un nouvel utilisateur : récupération de ses infos par LDAP
|
# Hook à la création d'un nouvel utilisateur : récupération de ses infos par LDAP
|
||||||
def create_user_profile(sender, instance, created, **kwargs):
|
def create_user_profile(sender, instance, created, **kwargs):
|
||||||
if created:
|
if created:
|
||||||
profil, created = Normalien.objects.get_or_create(user=instance)
|
profil, created = Normalien.objects.get_or_create(user=instance)
|
||||||
try:
|
try:
|
||||||
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
|
saccount = SocialAccount.objects.get(user=instance,
|
||||||
l = ldap.initialize("ldaps://ldap.spi.ens.fr:636")
|
provider="clipper")
|
||||||
l.set_option(ldap.OPT_REFERRALS, 0)
|
except SocialAccount.DoesNotExist:
|
||||||
l.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
|
return
|
||||||
l.set_option(ldap.OPT_X_TLS,ldap.OPT_X_TLS_DEMAND)
|
edata = saccount.extra_data.get("ldap", {})
|
||||||
l.set_option(ldap.OPT_X_TLS_DEMAND, True)
|
dep = ""
|
||||||
l.set_option(ldap.OPT_DEBUG_LEVEL, 255)
|
if "department_code" in edata:
|
||||||
l.set_option(ldap.OPT_NETWORK_TIMEOUT, 10)
|
dep = dict(DEPARTEMENTS_DEFAUT).get(
|
||||||
l.set_option(ldap.OPT_TIMEOUT, 10)
|
edata["department_code"].lower(), '')
|
||||||
|
|
||||||
info = l.search_s('dc=spi,dc=ens,dc=fr',
|
|
||||||
ldap.SCOPE_SUBTREE,
|
|
||||||
('(uid=%s)' % (instance.username,)),
|
|
||||||
[str("cn"),
|
|
||||||
str("mailRoutingAddress"),
|
|
||||||
str("homeDirectory")])
|
|
||||||
|
|
||||||
# Si des informations sont disponibles
|
|
||||||
if len(info) > 0:
|
|
||||||
infos = info[0][1]
|
|
||||||
|
|
||||||
# Nom
|
|
||||||
profil.nom = infos.get('cn', [''])[0]
|
|
||||||
|
|
||||||
# Parsing du homeDirectory pour la promotion
|
|
||||||
if 'homeDirectory' in infos:
|
|
||||||
dirs = infos['homeDirectory'][0].split('/')
|
|
||||||
if dirs[1] == 'users':
|
|
||||||
annee = dirs[2]
|
|
||||||
dep = dirs[3]
|
|
||||||
dep = dict(DEPARTEMENTS_DEFAUT).get(dep.lower(), '')
|
|
||||||
profil.promotion = u'%s %s' % (dep, annee)
|
|
||||||
|
|
||||||
# Mail
|
|
||||||
pmail = infos.get('mailRoutingAddress',
|
|
||||||
['%s@clipper.ens.fr'%instance.username])
|
|
||||||
if len(pmail) > 0:
|
|
||||||
profil.mail = pmail[0]
|
|
||||||
|
|
||||||
|
profil.promotion = "%s %s" % (dep, edata["entrance_year"])
|
||||||
|
profil.nom = edata.get("name", "")
|
||||||
profil.save()
|
profil.save()
|
||||||
except ldap.LDAPError:
|
|
||||||
pass
|
post_save.connect(create_user_profile, sender=User)
|
||||||
#post_save.connect(create_user_profile, sender=User)
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Lieu de stage
|
# Lieu de stage
|
||||||
|
@ -217,6 +220,10 @@ class Stage(models.Model):
|
||||||
def niveau_scol_fancy(self):
|
def niveau_scol_fancy(self):
|
||||||
return NIVEAU_SCOL_DICT.get(self.niveau_scol, "")
|
return NIVEAU_SCOL_DICT.get(self.niveau_scol, "")
|
||||||
|
|
||||||
|
# Optimisation de requêtes
|
||||||
|
@cached_property
|
||||||
|
def all_lieux(self):
|
||||||
|
return self.lieux.all()
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse('avisstage:stage', self)
|
return reverse('avisstage:stage', self)
|
||||||
|
|
|
@ -161,6 +161,19 @@ header {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.warning {
|
||||||
|
background-color: #c20;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #fff;
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
margin-top: 15px;
|
||||||
|
font-size: 0.8em;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
// Liste des stages condensée sur le profil
|
// Liste des stages condensée sur le profil
|
||||||
|
|
||||||
.condensed-stages {
|
.condensed-stages {
|
||||||
|
@ -753,6 +766,13 @@ a.lieu-change {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 15px auto;
|
margin: 15px auto;
|
||||||
|
|
||||||
|
.archicubes {
|
||||||
|
border-top: 2px solid $vert;
|
||||||
|
margin-top: 5px;
|
||||||
|
padding-top: 5px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
article.promo {
|
article.promo {
|
||||||
|
|
|
@ -229,29 +229,44 @@ header h1 {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 167, ../../sass/screen.scss */
|
/* line 164, ../../sass/screen.scss */
|
||||||
|
p.warning {
|
||||||
|
background-color: #c20;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #fff;
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* line 171, ../../sass/screen.scss */
|
||||||
|
.footer {
|
||||||
|
margin-top: 15px;
|
||||||
|
font-size: 0.8em;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* line 180, ../../sass/screen.scss */
|
||||||
.condensed-stages li {
|
.condensed-stages li {
|
||||||
display: table;
|
display: table;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
margin: 12px;
|
margin: 12px;
|
||||||
}
|
}
|
||||||
/* line 174, ../../sass/screen.scss */
|
/* line 187, ../../sass/screen.scss */
|
||||||
.condensed-stages li > *, .condensed-stages li:before {
|
.condensed-stages li > *, .condensed-stages li:before {
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
}
|
}
|
||||||
/* line 179, ../../sass/screen.scss */
|
/* line 192, ../../sass/screen.scss */
|
||||||
.condensed-stages li a {
|
.condensed-stages li a {
|
||||||
width: auto;
|
width: auto;
|
||||||
}
|
}
|
||||||
/* line 181, ../../sass/screen.scss */
|
/* line 194, ../../sass/screen.scss */
|
||||||
.condensed-stages li a:hover {
|
.condensed-stages li a:hover {
|
||||||
background: #e08206;
|
background: #e08206;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
/* line 186, ../../sass/screen.scss */
|
/* line 199, ../../sass/screen.scss */
|
||||||
.condensed-stages li:before {
|
.condensed-stages li:before {
|
||||||
content: "";
|
content: "";
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
@ -259,77 +274,77 @@ header h1 {
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
/* line 193, ../../sass/screen.scss */
|
/* line 206, ../../sass/screen.scss */
|
||||||
.condensed-stages li.stage-brouillon:before {
|
.condensed-stages li.stage-brouillon:before {
|
||||||
content: "Brouillon";
|
content: "Brouillon";
|
||||||
background: #f93a93;
|
background: #f93a93;
|
||||||
}
|
}
|
||||||
/* line 197, ../../sass/screen.scss */
|
/* line 210, ../../sass/screen.scss */
|
||||||
.condensed-stages li.stage-publie:before {
|
.condensed-stages li.stage-publie:before {
|
||||||
content: "Publié";
|
content: "Publié";
|
||||||
background: #419be9;
|
background: #419be9;
|
||||||
}
|
}
|
||||||
/* line 201, ../../sass/screen.scss */
|
/* line 214, ../../sass/screen.scss */
|
||||||
.condensed-stages li.stage-ajout:before {
|
.condensed-stages li.stage-ajout:before {
|
||||||
content: "+";
|
content: "+";
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 209, ../../sass/screen.scss */
|
/* line 222, ../../sass/screen.scss */
|
||||||
.stage-liste li {
|
.stage-liste li {
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
/* line 213, ../../sass/screen.scss */
|
/* line 226, ../../sass/screen.scss */
|
||||||
.stage-liste li.date-maj {
|
.stage-liste li.date-maj {
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
padding: 3px 0;
|
padding: 3px 0;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
/* line 219, ../../sass/screen.scss */
|
/* line 232, ../../sass/screen.scss */
|
||||||
.stage-liste li.stage {
|
.stage-liste li.stage {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
border-left: 5px solid #f99b20;
|
border-left: 5px solid #f99b20;
|
||||||
}
|
}
|
||||||
/* line 225, ../../sass/screen.scss */
|
/* line 238, ../../sass/screen.scss */
|
||||||
.stage-liste li.stage h3 {
|
.stage-liste li.stage h3 {
|
||||||
font-size: 1.4em;
|
font-size: 1.4em;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
/* line 229, ../../sass/screen.scss */
|
/* line 242, ../../sass/screen.scss */
|
||||||
.stage-liste li.stage h3 > a {
|
.stage-liste li.stage h3 > a {
|
||||||
color: #0f4c82;
|
color: #0f4c82;
|
||||||
}
|
}
|
||||||
/* line 233, ../../sass/screen.scss */
|
/* line 246, ../../sass/screen.scss */
|
||||||
.stage-liste li.stage h3 .auteur {
|
.stage-liste li.stage h3 .auteur {
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
}
|
}
|
||||||
/* line 236, ../../sass/screen.scss */
|
/* line 249, ../../sass/screen.scss */
|
||||||
.stage-liste li.stage h3 .auteur, .stage-liste li.stage h3 .auteur a {
|
.stage-liste li.stage h3 .auteur, .stage-liste li.stage h3 .auteur a {
|
||||||
font-family: "Dosis", sans-serif;
|
font-family: "Dosis", sans-serif;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
/* line 243, ../../sass/screen.scss */
|
/* line 256, ../../sass/screen.scss */
|
||||||
.stage-liste li .misc-hdr {
|
.stage-liste li .misc-hdr {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
/* line 247, ../../sass/screen.scss */
|
/* line 260, ../../sass/screen.scss */
|
||||||
.stage-liste li .misc-hdr .dates > span {
|
.stage-liste li .misc-hdr .dates > span {
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
/* line 251, ../../sass/screen.scss */
|
/* line 264, ../../sass/screen.scss */
|
||||||
.stage-liste li .misc-hdr .dates .year {
|
.stage-liste li .misc-hdr .dates .year {
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
}
|
}
|
||||||
/* line 254, ../../sass/screen.scss */
|
/* line 267, ../../sass/screen.scss */
|
||||||
.stage-liste li .misc-hdr .dates svg text {
|
.stage-liste li .misc-hdr .dates svg text {
|
||||||
font-size: 0.8;
|
font-size: 0.8;
|
||||||
}
|
}
|
||||||
/* line 260, ../../sass/screen.scss */
|
/* line 273, ../../sass/screen.scss */
|
||||||
.stage-liste li a.hoverlink {
|
.stage-liste li a.hoverlink {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -340,7 +355,7 @@ header h1 {
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 272, ../../sass/screen.scss */
|
/* line 285, ../../sass/screen.scss */
|
||||||
ul.infos {
|
ul.infos {
|
||||||
margin: 0 -3px;
|
margin: 0 -3px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -349,7 +364,7 @@ ul.infos {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
width: 100;
|
width: 100;
|
||||||
}
|
}
|
||||||
/* line 280, ../../sass/screen.scss */
|
/* line 293, ../../sass/screen.scss */
|
||||||
ul.infos li {
|
ul.infos li {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
|
@ -361,28 +376,28 @@ ul.infos li {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: #ddd;
|
background-color: #ddd;
|
||||||
}
|
}
|
||||||
/* line 291, ../../sass/screen.scss */
|
/* line 304, ../../sass/screen.scss */
|
||||||
ul.infos li.thematique {
|
ul.infos li.thematique {
|
||||||
color: #0d3f6b;
|
color: #0d3f6b;
|
||||||
background-color: #86bff1;
|
background-color: #86bff1;
|
||||||
}
|
}
|
||||||
/* line 295, ../../sass/screen.scss */
|
/* line 308, ../../sass/screen.scss */
|
||||||
ul.infos li.matiere {
|
ul.infos li.matiere {
|
||||||
color: #395214;
|
color: #395214;
|
||||||
background-color: #c7e699;
|
background-color: #c7e699;
|
||||||
}
|
}
|
||||||
/* line 299, ../../sass/screen.scss */
|
/* line 312, ../../sass/screen.scss */
|
||||||
ul.infos li.lieu {
|
ul.infos li.lieu {
|
||||||
color: #7c043c;
|
color: #7c043c;
|
||||||
background-color: #fb84bc;
|
background-color: #fb84bc;
|
||||||
}
|
}
|
||||||
/* line 303, ../../sass/screen.scss */
|
/* line 316, ../../sass/screen.scss */
|
||||||
ul.infos li.year {
|
ul.infos li.year {
|
||||||
background-color: #950548;
|
background-color: #950548;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
/* line 308, ../../sass/screen.scss */
|
/* line 321, ../../sass/screen.scss */
|
||||||
ul.infos li.avis-len {
|
ul.infos li.avis-len {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: 1px solid #eee;
|
border: 1px solid #eee;
|
||||||
|
@ -390,29 +405,29 @@ ul.infos li.avis-len {
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
padding-bottom: 2px;
|
padding-bottom: 2px;
|
||||||
}
|
}
|
||||||
/* line 315, ../../sass/screen.scss */
|
/* line 328, ../../sass/screen.scss */
|
||||||
ul.infos li.avis-len.avis-vide {
|
ul.infos li.avis-len.avis-vide {
|
||||||
border-bottom-color: #ddd;
|
border-bottom-color: #ddd;
|
||||||
}
|
}
|
||||||
/* line 318, ../../sass/screen.scss */
|
/* line 331, ../../sass/screen.scss */
|
||||||
ul.infos li.avis-len.avis-court {
|
ul.infos li.avis-len.avis-court {
|
||||||
border-bottom-color: #ffff66;
|
border-bottom-color: #ffff66;
|
||||||
}
|
}
|
||||||
/* line 321, ../../sass/screen.scss */
|
/* line 334, ../../sass/screen.scss */
|
||||||
ul.infos li.avis-len.avis-moyen {
|
ul.infos li.avis-len.avis-moyen {
|
||||||
border-bottom-color: #86bff1;
|
border-bottom-color: #86bff1;
|
||||||
}
|
}
|
||||||
/* line 324, ../../sass/screen.scss */
|
/* line 337, ../../sass/screen.scss */
|
||||||
ul.infos li.avis-len.avis-long {
|
ul.infos li.avis-len.avis-long {
|
||||||
border-bottom-color: #a5d65c;
|
border-bottom-color: #a5d65c;
|
||||||
}
|
}
|
||||||
/* line 330, ../../sass/screen.scss */
|
/* line 343, ../../sass/screen.scss */
|
||||||
ul.infos:after {
|
ul.infos:after {
|
||||||
content: "";
|
content: "";
|
||||||
flex: 1000;
|
flex: 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 336, ../../sass/screen.scss */
|
/* line 349, ../../sass/screen.scss */
|
||||||
section.profil {
|
section.profil {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
|
@ -420,7 +435,7 @@ section.profil {
|
||||||
margin: 5px auto;
|
margin: 5px auto;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
/* line 343, ../../sass/screen.scss */
|
/* line 356, ../../sass/screen.scss */
|
||||||
section.profil div.infos {
|
section.profil div.infos {
|
||||||
border-bottom: 3px solid #1a82dd;
|
border-bottom: 3px solid #1a82dd;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -712,7 +727,7 @@ article.stage .section-wrapper .toc .toc-active a {
|
||||||
border: 1px solid #ad0654;
|
border: 1px solid #ad0654;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 364, ../../sass/screen.scss */
|
/* line 377, ../../sass/screen.scss */
|
||||||
input, textarea, select, div.tinymce, option, optgroup:before {
|
input, textarea, select, div.tinymce, option, optgroup:before {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
|
@ -722,13 +737,13 @@ input, textarea, select, div.tinymce, option, optgroup:before {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
/* line 373, ../../sass/screen.scss */
|
/* line 386, ../../sass/screen.scss */
|
||||||
input:focus, input.mce-edit-focus, textarea:focus, textarea.mce-edit-focus, select:focus, select.mce-edit-focus, div.tinymce:focus, div.tinymce.mce-edit-focus, option:focus, option.mce-edit-focus, optgroup:before:focus, optgroup:before.mce-edit-focus {
|
input:focus, input.mce-edit-focus, textarea:focus, textarea.mce-edit-focus, select:focus, select.mce-edit-focus, div.tinymce:focus, div.tinymce.mce-edit-focus, option:focus, option.mce-edit-focus, optgroup:before:focus, optgroup:before.mce-edit-focus {
|
||||||
background-color: #e9f5d6;
|
background-color: #e9f5d6;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 380, ../../sass/screen.scss */
|
/* line 393, ../../sass/screen.scss */
|
||||||
input[type='text'], input[type='password'],
|
input[type='text'], input[type='password'],
|
||||||
input[type='email'], input[type='number'], textarea, select {
|
input[type='email'], input[type='number'], textarea, select {
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -738,7 +753,7 @@ input[type='email'], input[type='number'], textarea, select {
|
||||||
transition: border 1s ease-out, background 1s ease-out;
|
transition: border 1s ease-out, background 1s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 389, ../../sass/screen.scss */
|
/* line 402, ../../sass/screen.scss */
|
||||||
select {
|
select {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
|
@ -752,21 +767,21 @@ select {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
}
|
}
|
||||||
/* line 402, ../../sass/screen.scss */
|
/* line 415, ../../sass/screen.scss */
|
||||||
select option {
|
select option {
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
/* line 408, ../../sass/screen.scss */
|
/* line 421, ../../sass/screen.scss */
|
||||||
select optgroup option {
|
select optgroup option {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
/* line 411, ../../sass/screen.scss */
|
/* line 424, ../../sass/screen.scss */
|
||||||
select optgroup:before {
|
select optgroup:before {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 417, ../../sass/screen.scss */
|
/* line 430, ../../sass/screen.scss */
|
||||||
input[type="submit"], .btn {
|
input[type="submit"], .btn {
|
||||||
font: 19px "Dosis", sans-serif;
|
font: 19px "Dosis", sans-serif;
|
||||||
background-color: #8fcc33;
|
background-color: #8fcc33;
|
||||||
|
@ -777,17 +792,17 @@ input[type="submit"], .btn {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 427, ../../sass/screen.scss */
|
/* line 440, ../../sass/screen.scss */
|
||||||
p.submits {
|
p.submits {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 431, ../../sass/screen.scss */
|
/* line 444, ../../sass/screen.scss */
|
||||||
form .commentaire {
|
form .commentaire {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 435, ../../sass/screen.scss */
|
/* line 448, ../../sass/screen.scss */
|
||||||
.edit-btn {
|
.edit-btn {
|
||||||
border-color: #706c00;
|
border-color: #706c00;
|
||||||
color: #000;
|
color: #000;
|
||||||
|
@ -796,14 +811,14 @@ form .commentaire {
|
||||||
background-origin: content-box;
|
background-origin: content-box;
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
}
|
}
|
||||||
/* line 443, ../../sass/screen.scss */
|
/* line 456, ../../sass/screen.scss */
|
||||||
.edit-btn:after {
|
.edit-btn:after {
|
||||||
content: "";
|
content: "";
|
||||||
width: 30px;
|
width: 30px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 450, ../../sass/screen.scss */
|
/* line 463, ../../sass/screen.scss */
|
||||||
textarea, div.tinymce {
|
textarea, div.tinymce {
|
||||||
font-family: "Lato", sans-serif;
|
font-family: "Lato", sans-serif;
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -813,20 +828,20 @@ textarea, div.tinymce {
|
||||||
transition: border 1s ease-out, background 1s ease-out;
|
transition: border 1s ease-out, background 1s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 459, ../../sass/screen.scss */
|
/* line 472, ../../sass/screen.scss */
|
||||||
textarea {
|
textarea {
|
||||||
height: 200px;
|
height: 200px;
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 467, ../../sass/screen.scss */
|
/* line 480, ../../sass/screen.scss */
|
||||||
form .field {
|
form .field {
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
/* line 473, ../../sass/screen.scss */
|
/* line 486, ../../sass/screen.scss */
|
||||||
form .field label, form .field .label {
|
form .field label, form .field .label {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
|
@ -835,39 +850,39 @@ form .field label, form .field .label {
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
/* line 481, ../../sass/screen.scss */
|
/* line 494, ../../sass/screen.scss */
|
||||||
form .field label.required:before, form .field .label.required:before {
|
form .field label.required:before, form .field .label.required:before {
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
content: "*";
|
content: "*";
|
||||||
color: #f70978;
|
color: #f70978;
|
||||||
}
|
}
|
||||||
/* line 487, ../../sass/screen.scss */
|
/* line 500, ../../sass/screen.scss */
|
||||||
form .field label {
|
form .field label {
|
||||||
font-family: Alegreya, serif;
|
font-family: Alegreya, serif;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
/* line 491, ../../sass/screen.scss */
|
/* line 504, ../../sass/screen.scss */
|
||||||
form .field .help_text {
|
form .field .help_text {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
}
|
}
|
||||||
/* line 495, ../../sass/screen.scss */
|
/* line 508, ../../sass/screen.scss */
|
||||||
form .field .input {
|
form .field .input {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 505, ../../sass/screen.scss */
|
/* line 518, ../../sass/screen.scss */
|
||||||
ul.as-selections {
|
ul.as-selections {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
/* line 509, ../../sass/screen.scss */
|
/* line 522, ../../sass/screen.scss */
|
||||||
ul.as-selections li {
|
ul.as-selections li {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
/* line 513, ../../sass/screen.scss */
|
/* line 526, ../../sass/screen.scss */
|
||||||
ul.as-selections .as-selection-item {
|
ul.as-selections .as-selection-item {
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
background: #f99b20;
|
background: #f99b20;
|
||||||
|
@ -876,53 +891,53 @@ ul.as-selections .as-selection-item {
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
/* line 521, ../../sass/screen.scss */
|
/* line 534, ../../sass/screen.scss */
|
||||||
ul.as-selections .as-selection-item a.as-close {
|
ul.as-selections .as-selection-item a.as-close {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
-webkit-cursor: pointer;
|
-webkit-cursor: pointer;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
/* line 528, ../../sass/screen.scss */
|
/* line 541, ../../sass/screen.scss */
|
||||||
ul.as-selections .as-selection-item.selected {
|
ul.as-selections .as-selection-item.selected {
|
||||||
background: #8fcc33;
|
background: #8fcc33;
|
||||||
}
|
}
|
||||||
/* line 533, ../../sass/screen.scss */
|
/* line 546, ../../sass/screen.scss */
|
||||||
ul.as-selections .as-original {
|
ul.as-selections .as-original {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
}
|
}
|
||||||
/* line 537, ../../sass/screen.scss */
|
/* line 550, ../../sass/screen.scss */
|
||||||
ul.as-selections .as-original input {
|
ul.as-selections .as-original input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 543, ../../sass/screen.scss */
|
/* line 556, ../../sass/screen.scss */
|
||||||
div.as-results {
|
div.as-results {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
/* line 547, ../../sass/screen.scss */
|
/* line 560, ../../sass/screen.scss */
|
||||||
div.as-results ul {
|
div.as-results ul {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border: 1px solid #d2ebad;
|
border: 1px solid #d2ebad;
|
||||||
}
|
}
|
||||||
/* line 554, ../../sass/screen.scss */
|
/* line 567, ../../sass/screen.scss */
|
||||||
div.as-results ul li {
|
div.as-results ul li {
|
||||||
padding: 3px 5px;
|
padding: 3px 5px;
|
||||||
}
|
}
|
||||||
/* line 560, ../../sass/screen.scss */
|
/* line 573, ../../sass/screen.scss */
|
||||||
div.as-results ul li.as-result-item.active {
|
div.as-results ul li.as-result-item.active {
|
||||||
background: #fddeb5;
|
background: #fddeb5;
|
||||||
}
|
}
|
||||||
/* line 565, ../../sass/screen.scss */
|
/* line 578, ../../sass/screen.scss */
|
||||||
div.as-results ul li.as-message {
|
div.as-results ul li.as-message {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 575, ../../sass/screen.scss */
|
/* line 588, ../../sass/screen.scss */
|
||||||
.window {
|
.window {
|
||||||
display: none;
|
display: none;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -933,11 +948,11 @@ div.as-results ul li.as-message {
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 50;
|
z-index: 50;
|
||||||
}
|
}
|
||||||
/* line 585, ../../sass/screen.scss */
|
/* line 598, ../../sass/screen.scss */
|
||||||
.window.visible {
|
.window.visible {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
/* line 589, ../../sass/screen.scss */
|
/* line 602, ../../sass/screen.scss */
|
||||||
.window .window-bg {
|
.window .window-bg {
|
||||||
background: #000;
|
background: #000;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
|
@ -948,7 +963,7 @@ div.as-results ul li.as-message {
|
||||||
top: 0;
|
top: 0;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
}
|
}
|
||||||
/* line 600, ../../sass/screen.scss */
|
/* line 613, ../../sass/screen.scss */
|
||||||
.window .window-content {
|
.window .window-content {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
@ -962,11 +977,11 @@ div.as-results ul li.as-message {
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
/* line 614, ../../sass/screen.scss */
|
/* line 627, ../../sass/screen.scss */
|
||||||
.window .window-content form label, .window .window-content form .label {
|
.window .window-content form label, .window .window-content form .label {
|
||||||
width: 150px;
|
width: 150px;
|
||||||
}
|
}
|
||||||
/* line 620, ../../sass/screen.scss */
|
/* line 633, ../../sass/screen.scss */
|
||||||
.window .window-closer {
|
.window .window-closer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -974,65 +989,65 @@ div.as-results ul li.as-message {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
}
|
}
|
||||||
/* line 626, ../../sass/screen.scss */
|
/* line 639, ../../sass/screen.scss */
|
||||||
.window .window-closer:after {
|
.window .window-closer:after {
|
||||||
content: "×";
|
content: "×";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 637, ../../sass/screen.scss */
|
/* line 650, ../../sass/screen.scss */
|
||||||
#lieu_widget .lieu-ui {
|
#lieu_widget .lieu-ui {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
/* line 639, ../../sass/screen.scss */
|
/* line 652, ../../sass/screen.scss */
|
||||||
#lieu_widget .lieu-ui .map {
|
#lieu_widget .lieu-ui .map {
|
||||||
height: 400px;
|
height: 400px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
/* line 643, ../../sass/screen.scss */
|
/* line 656, ../../sass/screen.scss */
|
||||||
#lieu_widget .lieu-ui.hidden {
|
#lieu_widget .lieu-ui.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
/* line 646, ../../sass/screen.scss */
|
/* line 659, ../../sass/screen.scss */
|
||||||
#lieu_widget .lieu-ui .masked {
|
#lieu_widget .lieu-ui .masked {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
/* line 651, ../../sass/screen.scss */
|
/* line 664, ../../sass/screen.scss */
|
||||||
#lieu_widget .lieu-choixmodif {
|
#lieu_widget .lieu-choixmodif {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
/* line 656, ../../sass/screen.scss */
|
/* line 669, ../../sass/screen.scss */
|
||||||
#lieu_widget.modif .lieu-choixmodif {
|
#lieu_widget.modif .lieu-choixmodif {
|
||||||
display: unset;
|
display: unset;
|
||||||
}
|
}
|
||||||
/* line 661, ../../sass/screen.scss */
|
/* line 674, ../../sass/screen.scss */
|
||||||
#lieu_widget.modif .lieu-ui, #lieu_widget.attente .lieu-ui {
|
#lieu_widget.modif .lieu-ui, #lieu_widget.attente .lieu-ui {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
/* line 668, ../../sass/screen.scss */
|
/* line 681, ../../sass/screen.scss */
|
||||||
#lieu_widget.edit .lieu-ui .lieu-acinput {
|
#lieu_widget.edit .lieu-ui .lieu-acinput {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
/* line 671, ../../sass/screen.scss */
|
/* line 684, ../../sass/screen.scss */
|
||||||
#lieu_widget.edit .lieu-ui .map {
|
#lieu_widget.edit .lieu-ui .map {
|
||||||
height: 200px;
|
height: 200px;
|
||||||
}
|
}
|
||||||
/* line 677, ../../sass/screen.scss */
|
/* line 690, ../../sass/screen.scss */
|
||||||
#lieu_widget #avis_lieu_vide {
|
#lieu_widget #avis_lieu_vide {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
/* line 681, ../../sass/screen.scss */
|
/* line 694, ../../sass/screen.scss */
|
||||||
#lieu_widget .message {
|
#lieu_widget .message {
|
||||||
background: #fddeb5;
|
background: #fddeb5;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
}
|
}
|
||||||
/* line 687, ../../sass/screen.scss */
|
/* line 700, ../../sass/screen.scss */
|
||||||
#lieu_widget .message.hidden {
|
#lieu_widget .message.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 693, ../../sass/screen.scss */
|
/* line 706, ../../sass/screen.scss */
|
||||||
a.lieu-change {
|
a.lieu-change {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: #f99b20;
|
background: #f99b20;
|
||||||
|
@ -1045,25 +1060,25 @@ a.lieu-change {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
margin-right: 7px;
|
margin-right: 7px;
|
||||||
}
|
}
|
||||||
/* line 705, ../../sass/screen.scss */
|
/* line 718, ../../sass/screen.scss */
|
||||||
a.lieu-change.ajout:before {
|
a.lieu-change.ajout:before {
|
||||||
content: "+";
|
content: "+";
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 711, ../../sass/screen.scss */
|
/* line 724, ../../sass/screen.scss */
|
||||||
#stages-map {
|
#stages-map {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 600px;
|
height: 600px;
|
||||||
max-height: 90vh;
|
max-height: 90vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 718, ../../sass/screen.scss */
|
/* line 731, ../../sass/screen.scss */
|
||||||
#id_stage-thematiques {
|
#id_stage-thematiques {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 724, ../../sass/screen.scss */
|
/* line 737, ../../sass/screen.scss */
|
||||||
.homeh1 {
|
.homeh1 {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
@ -1073,26 +1088,26 @@ a.lieu-change.ajout:before {
|
||||||
border-bottom: 3px solid #000;
|
border-bottom: 3px solid #000;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
/* line 733, ../../sass/screen.scss */
|
/* line 746, ../../sass/screen.scss */
|
||||||
.homeh1 h1 {
|
.homeh1 h1 {
|
||||||
margin-bottom: 3px;
|
margin-bottom: 3px;
|
||||||
}
|
}
|
||||||
/* line 737, ../../sass/screen.scss */
|
/* line 750, ../../sass/screen.scss */
|
||||||
.homeh1 > * {
|
.homeh1 > * {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
/* line 740, ../../sass/screen.scss */
|
/* line 753, ../../sass/screen.scss */
|
||||||
.homeh1 p {
|
.homeh1 p {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 745, ../../sass/screen.scss */
|
/* line 758, ../../sass/screen.scss */
|
||||||
.betacadre {
|
.betacadre {
|
||||||
background: #fa6cae;
|
background: #fa6cae;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 750, ../../sass/screen.scss */
|
/* line 763, ../../sass/screen.scss */
|
||||||
.entrer {
|
.entrer {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
|
@ -1100,85 +1115,92 @@ a.lieu-change.ajout:before {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 15px auto;
|
margin: 15px auto;
|
||||||
}
|
}
|
||||||
|
/* line 770, ../../sass/screen.scss */
|
||||||
|
.entrer .archicubes {
|
||||||
|
border-top: 2px solid #1a82dd;
|
||||||
|
margin-top: 5px;
|
||||||
|
padding-top: 5px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
/* line 758, ../../sass/screen.scss */
|
/* line 778, ../../sass/screen.scss */
|
||||||
article.promo {
|
article.promo {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 1.1em;
|
font-size: 1.1em;
|
||||||
}
|
}
|
||||||
/* line 762, ../../sass/screen.scss */
|
/* line 782, ../../sass/screen.scss */
|
||||||
article.promo .explications {
|
article.promo .explications {
|
||||||
display: table;
|
display: table;
|
||||||
}
|
}
|
||||||
/* line 765, ../../sass/screen.scss */
|
/* line 785, ../../sass/screen.scss */
|
||||||
article.promo .explications:first-child {
|
article.promo .explications:first-child {
|
||||||
direction: rtl;
|
direction: rtl;
|
||||||
}
|
}
|
||||||
/* line 767, ../../sass/screen.scss */
|
/* line 787, ../../sass/screen.scss */
|
||||||
article.promo .explications:first-child > * {
|
article.promo .explications:first-child > * {
|
||||||
direction: ltr;
|
direction: ltr;
|
||||||
}
|
}
|
||||||
/* line 772, ../../sass/screen.scss */
|
/* line 792, ../../sass/screen.scss */
|
||||||
article.promo .explications > div {
|
article.promo .explications > div {
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
/* line 777, ../../sass/screen.scss */
|
/* line 797, ../../sass/screen.scss */
|
||||||
article.promo .explications > div p {
|
article.promo .explications > div p {
|
||||||
margin: 15px 15px;
|
margin: 15px 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 785, ../../sass/screen.scss */
|
/* line 805, ../../sass/screen.scss */
|
||||||
.faq-toc {
|
.faq-toc {
|
||||||
font-family: "Lato", sans-serif;
|
font-family: "Lato", sans-serif;
|
||||||
display: block;
|
display: block;
|
||||||
max-width: 700px;
|
max-width: 700px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
/* line 790, ../../sass/screen.scss */
|
/* line 810, ../../sass/screen.scss */
|
||||||
.faq-toc ul {
|
.faq-toc ul {
|
||||||
margin: 20px;
|
margin: 20px;
|
||||||
}
|
}
|
||||||
/* line 794, ../../sass/screen.scss */
|
/* line 814, ../../sass/screen.scss */
|
||||||
.faq-toc ul li a {
|
.faq-toc ul li a {
|
||||||
color: #000;
|
color: #000;
|
||||||
display: block;
|
display: block;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
/* line 800, ../../sass/screen.scss */
|
/* line 820, ../../sass/screen.scss */
|
||||||
.faq-toc ul li.toc-h1 {
|
.faq-toc ul li.toc-h1 {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
/* line 804, ../../sass/screen.scss */
|
/* line 824, ../../sass/screen.scss */
|
||||||
.faq-toc ul li.toc-h2 a {
|
.faq-toc ul li.toc-h2 a {
|
||||||
background: #fcc883;
|
background: #fcc883;
|
||||||
}
|
}
|
||||||
/* line 808, ../../sass/screen.scss */
|
/* line 828, ../../sass/screen.scss */
|
||||||
.faq-toc ul li.toc-h3 a {
|
.faq-toc ul li.toc-h3 a {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
/* line 814, ../../sass/screen.scss */
|
/* line 834, ../../sass/screen.scss */
|
||||||
.faq-toc ul li a:hover {
|
.faq-toc ul li a:hover {
|
||||||
color: #395214;
|
color: #395214;
|
||||||
background: #bce085 !important;
|
background: #bce085 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 823, ../../sass/screen.scss */
|
/* line 843, ../../sass/screen.scss */
|
||||||
.faq article {
|
.faq article {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
}
|
}
|
||||||
/* line 826, ../../sass/screen.scss */
|
/* line 846, ../../sass/screen.scss */
|
||||||
.faq article h2 {
|
.faq article h2 {
|
||||||
background-color: #fcc883;
|
background-color: #fcc883;
|
||||||
color: #ae6505;
|
color: #ae6505;
|
||||||
margin: -15px;
|
margin: -15px;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
}
|
}
|
||||||
/* line 833, ../../sass/screen.scss */
|
/* line 853, ../../sass/screen.scss */
|
||||||
.faq article h3 {
|
.faq article h3 {
|
||||||
color: #0f4c82;
|
color: #0f4c82;
|
||||||
background-color: #9dcbf3;
|
background-color: #9dcbf3;
|
||||||
|
@ -1186,19 +1208,19 @@ article.promo .explications > div p {
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
padding: 10px 15px;
|
padding: 10px 15px;
|
||||||
}
|
}
|
||||||
/* line 840, ../../sass/screen.scss */
|
/* line 860, ../../sass/screen.scss */
|
||||||
.faq article h3:nth-child(2) {
|
.faq article h3:nth-child(2) {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
/* line 845, ../../sass/screen.scss */
|
/* line 865, ../../sass/screen.scss */
|
||||||
.faq article ul {
|
.faq article ul {
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
}
|
}
|
||||||
/* line 847, ../../sass/screen.scss */
|
/* line 867, ../../sass/screen.scss */
|
||||||
.faq article ul li {
|
.faq article ul li {
|
||||||
list-style: initial;
|
list-style: initial;
|
||||||
}
|
}
|
||||||
/* line 852, ../../sass/screen.scss */
|
/* line 872, ../../sass/screen.scss */
|
||||||
.faq article p, .faq article ul {
|
.faq article p, .faq article ul {
|
||||||
font-family: "Lato", sans-serif;
|
font-family: "Lato", sans-serif;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
@ -1207,20 +1229,20 @@ article.promo .explications > div p {
|
||||||
margin-right: 5%;
|
margin-right: 5%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* line 866, ../../sass/screen.scss */
|
/* line 886, ../../sass/screen.scss */
|
||||||
table.stats {
|
table.stats {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
cellspacing: 1px;
|
cellspacing: 1px;
|
||||||
}
|
}
|
||||||
/* line 871, ../../sass/screen.scss */
|
/* line 891, ../../sass/screen.scss */
|
||||||
table.stats th {
|
table.stats th {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
border-top: 1px solid #000;
|
border-top: 1px solid #000;
|
||||||
border-bottom: 1px solid #999;
|
border-bottom: 1px solid #999;
|
||||||
}
|
}
|
||||||
/* line 876, ../../sass/screen.scss */
|
/* line 896, ../../sass/screen.scss */
|
||||||
table.stats td, table.stats th {
|
table.stats td, table.stats th {
|
||||||
padding: 5px 3px;
|
padding: 5px 3px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
13
avisstage/templates/404.html
Normal file
13
avisstage/templates/404.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{% extends "avisstage/base.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
|
||||||
|
{% block title %}Page non trouvée{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<article>
|
||||||
|
<section>
|
||||||
|
<h1>Page non trouvée</h1>
|
||||||
|
<p>Cette page n'existe pas, ou peut-être que vous n'y avez pas accès.</p>
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
|
{% endblock %}
|
14
avisstage/templates/avisstage/403-archicubes.html
Normal file
14
avisstage/templates/avisstage/403-archicubes.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{% extends "avisstage/base.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
|
||||||
|
{% block title %}Accès interdit{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<article>
|
||||||
|
<section>
|
||||||
|
<h1>Accès réservé aux personnes en scolarité</h1>
|
||||||
|
<p>Vous pouvez pas consulter cette page : après la fin de votre scolarité, vous ne pouvez accéder qu'à votre profil et vos fiches de stages pour les tenir à jour.</p>
|
||||||
|
<p><a href="{% url "avisstage:perso" %}">Aller à mon tableau de bord</a></p>
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
|
{% endblock %}
|
|
@ -27,16 +27,18 @@
|
||||||
<ul id="menu">
|
<ul id="menu">
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<li><a href="{% url 'avisstage:perso' %}">Mon expérience</a></li>
|
<li><a href="{% url 'avisstage:perso' %}">Mon expérience</a></li>
|
||||||
|
{% if user.profil.en_scolarite %}
|
||||||
<li><a href="{% url 'avisstage:recherche' %}">Recherche</a></li>
|
<li><a href="{% url 'avisstage:recherche' %}">Recherche</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
<li><a href="{% url 'avisstage:faq' %}">FAQ</a></li>
|
<li><a href="{% url 'avisstage:faq' %}">FAQ</a></li>
|
||||||
{% if user.is_staff %}
|
{% if user.is_staff %}
|
||||||
<li><a href="{% url 'avisstage:moderation' %}">Modo</a></li>
|
<li><a href="{% url 'avisstage:moderation' %}">Modo</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<li><a href="{% url 'logout' %}"><span class="username">{{ user.username }}</span><br/> Déconnexion</a></li>
|
<li><a href="{% url "account_logout" %}"><span class="username">{{ user.username }}</span><br/> Déconnexion</a></li>
|
||||||
{% else %}
|
{% else %}
|
||||||
<li><a href="{% url 'login' %}">Connexion</a></li>
|
<li><a href="{% url "account_login" %}">Connexion</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<p class="promo">Promotion : <b>{{ object.promotion }}</b></p>
|
<p class="promo">Promotion : <b>{{ object.promotion }}</b></p>
|
||||||
<p class="contact">
|
<p class="contact">
|
||||||
{% if object.contactez_moi %}
|
{% if object.contactez_moi %}
|
||||||
Contact : <a href="mailto:{{ object.mail }}">{{ object.mail }}</a>
|
Contact : <a href="mailto:{{ object.preferred_email }}">{{ object.preferred_email }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<article class="stage">
|
<article class="stage">
|
||||||
<section class="misc">
|
<section class="misc">
|
||||||
<div class="misc-content {% if object.lieux.all %}withmap{% endif %}">
|
<div class="misc-content {% if object.all_lieux %}withmap{% endif %}">
|
||||||
<div class="desc">
|
<div class="desc">
|
||||||
<div class="misc-hdr">
|
<div class="misc-hdr">
|
||||||
<h1>{{ object.sujet }}</h1>
|
<h1>{{ object.sujet }}</h1>
|
||||||
|
@ -65,8 +65,8 @@
|
||||||
a fait {{ object.type_stage_fem|yesno:"cette,ce" }} <b>{{ object.type_stage_fancy }}</b>
|
a fait {{ object.type_stage_fem|yesno:"cette,ce" }} <b>{{ object.type_stage_fancy }}</b>
|
||||||
{% if object.niveau_scol %}{{ object.niveau_scol_fancy }},{% endif %}
|
{% if object.niveau_scol %}{{ object.niveau_scol_fancy }},{% endif %}
|
||||||
{% if object.structure %}au sein de {{ object.structure }}{% endif %}{% if object.encadrants %}, supervisé par {{ object.encadrants }}{% endif %}.</p>
|
{% if object.structure %}au sein de {{ object.structure }}{% endif %}{% if object.encadrants %}, supervisé par {{ object.encadrants }}{% endif %}.</p>
|
||||||
{% if object.lieux.all %}<p>Cela s'est passé à :
|
{% if object.all_lieux %}<p>Cela s'est passé à :
|
||||||
{% for lieu in object.lieux.all %}{{ lieu.nom }} ({{ lieu.ville }}){% if not forloop.last %}, {% endif %}{% endfor %}.</p>
|
{% for lieu in object.all_lieux %}{{ lieu.nom }} ({{ lieu.ville }}){% if not forloop.last %}, {% endif %}{% endfor %}.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<ul class="infos">
|
<ul class="infos">
|
||||||
|
@ -79,12 +79,12 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if object.lieux.all %}
|
{% if object.all_lieux %}
|
||||||
<div class="map">
|
<div class="map">
|
||||||
<div id="stage-map"></div>
|
<div id="stage-map"></div>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var lieux = [
|
var lieux = [
|
||||||
{% for lieu in object.lieux.all %}
|
{% for lieu in object.all_lieux %}
|
||||||
{
|
{
|
||||||
coord: {lat: "{{ lieu.coord.y|escapejs }}", lon: "{{ lieu.coord.x|escapejs }}" },
|
coord: {lat: "{{ lieu.coord.y|escapejs }}", lon: "{{ lieu.coord.x|escapejs }}" },
|
||||||
popup: "<h3>{{ lieu.nom|escapejs }}</h3>" +
|
popup: "<h3>{{ lieu.nom|escapejs }}</h3>" +
|
||||||
|
|
|
@ -74,7 +74,8 @@
|
||||||
|
|
||||||
<h3>Je n'ai plus de compte clipper, puis-je accéder à ce site ?</h3>
|
<h3>Je n'ai plus de compte clipper, puis-je accéder à ce site ?</h3>
|
||||||
<p>Pour conserver l'accès à ce site limité, et garantir une certaine liberté de parole, seuls les normalien⋅ne⋅s en scolarité ont accès au site entier.</p>
|
<p>Pour conserver l'accès à ce site limité, et garantir une certaine liberté de parole, seuls les normalien⋅ne⋅s en scolarité ont accès au site entier.</p>
|
||||||
<p>En revanche, si vous écrivez des avis ici, vous pourrez toujours les modifier ou les supprimer. Une procédure de connexion spécifique est prévue, mais pas encore implémentée.</p>
|
<p>En revanche, si vous écrivez des avis ici, vous pourrez toujours les modifier ou les supprimer. Il suffira d'utiliser l'accès archicubes, avec des identifiants spécifiques à ce site.</p>
|
||||||
|
<p>Si vous aviez un compte dont vous avez perdu l'accès, vous pouvez contacter le <a href="https://www.eleves.ens.fr/home/klub-dev/">Klub Dev ENS</a> pour qu'on vous donne des accès.
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article>
|
<article>
|
||||||
|
@ -88,7 +89,7 @@
|
||||||
<p>Faites-en part en cliquant sur le bouton feedback, on est preneur !</p>
|
<p>Faites-en part en cliquant sur le bouton feedback, on est preneur !</p>
|
||||||
|
|
||||||
<h3>Qui est derrière ?</h3>
|
<h3>Qui est derrière ?</h3>
|
||||||
<p>Cette plateforme a été réalisée par <a href="http://www.robin-champenois.fr">Robin Champenois</a> (Info 2012) en django, sur une idée originale de Damien Moulin (Physique 2013). Le code source est disponible <a href="https://git.eleves.ens.fr/champeno/experiENS">ici</a>. Le site est hébergé sur le serveur des élèves.</p>
|
<p>Cette plateforme a été lancée en 2017 par <a href="http://www.robin-champenois.fr">Robin Champenois</a> (Info 2012) en django, sur une idée originale de Damien Moulin (Physique 2013). Il est désormais maintenu et développé au sein du <a href="https://www.eleves.ens.fr/home/klub-dev/">Klub Dev ENS</a>. Le code source est disponible <a href="https://git.eleves.ens.fr/klub-dev-ens/experiENS">ici</a>. Le site est hébergé sur le serveur des élèves.</p>
|
||||||
|
|
||||||
</article>
|
</article>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -11,8 +11,9 @@
|
||||||
|
|
||||||
{% if not user.is_authenticated %}
|
{% if not user.is_authenticated %}
|
||||||
<div class="entrer">
|
<div class="entrer">
|
||||||
<p><a href="{% url 'login' %}" class="btn">Connexion</a></p>
|
<p><a href="{% url "clipper_login" %}" class="btn">Connexion</a></p>
|
||||||
<p class="helptext">Connexion via le serveur central d'authentification ENS (identifiants clipper)</p>
|
<p class="helptext">Connexion via le serveur central d'authentification ENS <br />(identifiants clipper)</p>
|
||||||
|
<p class="archicubes"><a href="{% url "account_login" %}">Accès archicubes</a> <br /><i>Pour continuer à tenir à jour ses fiches, sans voir celles des autres</i></p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -23,7 +24,13 @@
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p>Ne partez plus en stage en terre inconnue : nourrissez-vous des {{ num_stages }} expériences de séjours effectués par la communauté normalienne, repérez les bons plans, et ne faites pas les mêmes erreurs !</p>
|
<p>Ne partez plus en stage en terre inconnue : nourrissez-vous des {{ num_stages }} expériences de séjours effectués par la communauté normalienne, repérez les bons plans, et ne faites pas les mêmes erreurs !</p>
|
||||||
{% if user.is_authenticated %}<p><a href="{% url 'avisstage:recherche' %}" class="btn">Rechercher des stages</a></p>{% endif %}
|
{% if user.is_authenticated %}
|
||||||
|
{% if user.profil.en_scolarite %}
|
||||||
|
<p><a href="{% url 'avisstage:recherche' %}" class="btn">Rechercher des stages</a></p>
|
||||||
|
{% else %}
|
||||||
|
<p><i>Accès restreint aux personnes en scolarité</i></p>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="explications">
|
<div class="explications">
|
||||||
|
|
|
@ -6,6 +6,55 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Bonjour {{ user.profil.nom }} !</h1>
|
<h1>Bonjour {{ user.profil.nom }} !</h1>
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<h2>Mon compte</h2>
|
||||||
|
<section class="profil">
|
||||||
|
{% if user.profil.en_scolarite %}
|
||||||
|
<h3 class="scolarite">Statut : En scolarité</h3>
|
||||||
|
<p>Vous pouvez accéder à l'ensemble du site, et aux fiches de stages.</p>
|
||||||
|
<p>Quand vous n'aurez plus de compte clipper (après votre scolarité), votre accès sera restreint à vos propres expériences, que vous pourrez ajouter, modifier, supprimer.</p>
|
||||||
|
<p>Pensez à renseigner une adresse e-mail non-ENS pour conserver cet accès, et permettre aux futur⋅e⋅s normalien⋅ne⋅s de toujours vous contacter !</p>
|
||||||
|
{% else %}
|
||||||
|
<h3 class="scolarite">Statut : Archicube</h3>
|
||||||
|
<p>Vous ne pouvez plus accéder qu'à vos propres expériences pour les modifier, et tenir à jour votre profil.</p>
|
||||||
|
<p>Si vous êtes encore en scolarité, merci de vous <a href="{% url "clipper_login" %}?process=connect">reconnecter en passant par le serveur d'authentification de l'ENS</a> pour mettre à jour votre statut.</p>
|
||||||
|
{% endif %}
|
||||||
|
<p><i>Le statut est mis à jour automatiquement chaque année selon le mode de connexion que vous utilisez.</i></p>
|
||||||
|
</section>
|
||||||
|
<section class="profil">
|
||||||
|
<h3>Adresses e-mail</h3>
|
||||||
|
{% if not user.profil.has_nonENS_email %}<p align="center" class="warning">Vous n'avez pas renseigné d'adresse mail autre que celle de l'ENS. Pensez à le faire, pour que les générations futures puissent toujours vous contacter !</p>{% endif %}
|
||||||
|
<p><a href="{% url "account_email" %}">Gérer les adresses e-mail liées à mon compte</a></p>
|
||||||
|
</section>
|
||||||
|
<section class="profil">
|
||||||
|
<h3>Mode de connexion</h3>
|
||||||
|
{% if user.profil.en_scolarite %}<p>En scolarité, utilisez le serveur central d'authentification pour vous connecter. Quand vous n'aurez plus de compte clipper, vous devrez vous connecter directement via l'accès archicubes, avec l'identifiant {{ user.username }}</p>{% endif %}
|
||||||
|
{% if not user.password %}<p class="warning" align="center">Vous n'avez pas créé de mot de passe interne à ExperiENS. Pensez-y pour garder l'accès au site quand vous n'aurez plus de compte clipper !</p>{% endif %}
|
||||||
|
<p><a href="{% url "account_change_password" %}">Créer / changer mon mot de passe ExperiENS</a></p>
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<h2><a href="{% url "avisstage:profil" user.username %}">Mon profil public</a> <a href="{% url "avisstage:profil_edit" %}" class="edit-btn btn">Modifier mes infos</a></h2>
|
||||||
|
{% with object=user.profil %}
|
||||||
|
<section class="profil">
|
||||||
|
<div class="infos">
|
||||||
|
<p class="promo">Promotion : <b>{{ object.promotion }}</b></p>
|
||||||
|
<p class="contact">
|
||||||
|
{% if object.contactez_moi %}
|
||||||
|
Contact : {{ object.preferred_email }}
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% if object.bio %}
|
||||||
|
<div class="bio">{{ object.bio|linebreaks }}</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="bio"><p><i>Vous n'avez rien mis ici. <a href="{% url "avisstage:profil_edit" %}">Écrivez un peu à propos de vous !</a></i></p></div>
|
||||||
|
{% endif %}
|
||||||
|
</section>
|
||||||
|
{% endwith %}
|
||||||
|
</article>
|
||||||
|
|
||||||
<article>
|
<article>
|
||||||
<h2>Mes stages</h2>
|
<h2>Mes stages</h2>
|
||||||
<ul class="condensed-stages">
|
<ul class="condensed-stages">
|
||||||
|
@ -23,25 +72,4 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2><a href="{% url "avisstage:profil" user.username %}">Mon profil public</a> <a href="{% url "avisstage:profil_edit" %}" class="edit-btn btn">Modifier mes infos</a></h2>
|
|
||||||
{% with object=user.profil %}
|
|
||||||
<section class="profil">
|
|
||||||
<div class="infos">
|
|
||||||
<p class="promo">Promotion : <b>{{ object.promotion }}</b></p>
|
|
||||||
<p class="contact">
|
|
||||||
{% if object.contactez_moi %}
|
|
||||||
Contact : {{ object.mail }}
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
{% if object.bio %}
|
|
||||||
<div class="bio">{{ object.bio|linebreaks }}</div>
|
|
||||||
{% else %}
|
|
||||||
<div class="bio"><p><i>Vous n'avez rien mis ici. <a href="{% url "avisstage:profil_edit" %}">Écrivez un peu à propos de vous !</a></i></p></div>
|
|
||||||
{% endif %}
|
|
||||||
</section>
|
|
||||||
{% endwith %}
|
|
||||||
</article>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,3 +1,482 @@
|
||||||
from django.test import TestCase
|
from allauth.socialaccount.models import SocialAccount
|
||||||
|
from allauth_cas.test.testcases import CASTestCase
|
||||||
|
|
||||||
# Create your tests here.
|
from datetime import date
|
||||||
|
|
||||||
|
from django.test import TestCase
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
from .models import User, Normalien, Lieu, Stage, StageMatiere, AvisLieu
|
||||||
|
|
||||||
|
class ExperiENSTestCase(CASTestCase):
|
||||||
|
|
||||||
|
# Dummy database
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.u_conscrit = User.objects.create_user('conscrit',
|
||||||
|
'conscrit@ens.fr',
|
||||||
|
'conscrit')
|
||||||
|
self.p_conscrit = self.u_conscrit.profil
|
||||||
|
self.p_conscrit.nom="Petit conscrit"
|
||||||
|
self.p_conscrit.promotion="Serpentard 2000"
|
||||||
|
self.p_conscrit.bio="Je suis un petit conscrit"
|
||||||
|
self.p_conscrit.save()
|
||||||
|
|
||||||
|
self.sa_conscrit = SocialAccount(user=self.u_conscrit,
|
||||||
|
provider="clipper",
|
||||||
|
uid="conscrit")
|
||||||
|
self.sa_conscrit.save()
|
||||||
|
|
||||||
|
self.u_archi = User.objects.create_user('archicube',
|
||||||
|
'archicube@ens.fr',
|
||||||
|
'archicube')
|
||||||
|
self.p_archi = self.u_archi.profil
|
||||||
|
self.p_archi.nom="Vieil archicube"
|
||||||
|
self.p_archi.promotion="Gryffondor 1994"
|
||||||
|
self.p_archi.bio="Je suis un vieil archicube"
|
||||||
|
|
||||||
|
self.lieu1 = Lieu(nom="Beaux-Bâtons", type_lieu="universite",
|
||||||
|
ville="Brocéliande", pays="FR",
|
||||||
|
coord="POINT(-1.63971 48.116382)")
|
||||||
|
self.lieu1.save()
|
||||||
|
self.lieu2 = Lieu(nom="Durmstrang", type_lieu="universite",
|
||||||
|
ville="Edimbourg", pays="GB",
|
||||||
|
coord="POINT(56.32153 -1.259715)")
|
||||||
|
self.lieu2.save()
|
||||||
|
|
||||||
|
self.matiere1 = StageMatiere(nom="Arithmancie", slug="arithmancie")
|
||||||
|
self.matiere1.save()
|
||||||
|
self.matiere2 = StageMatiere(nom="Sortilège", slug="sortilege")
|
||||||
|
self.matiere2.save()
|
||||||
|
|
||||||
|
self.cstage1 = Stage(auteur=self.p_conscrit, sujet="Wingardium Leviosa",
|
||||||
|
date_debut=date(2000, 5, 10),
|
||||||
|
date_fin=date(2000, 8, 26),
|
||||||
|
type_stage="recherche",
|
||||||
|
niveau_scol="M1", public=True)
|
||||||
|
self.cstage1.save()
|
||||||
|
self.cstage1.matieres.add(self.matiere1)
|
||||||
|
alieu1 = AvisLieu(stage=self.cstage1, lieu=self.lieu1,
|
||||||
|
chapo="Trop bien")
|
||||||
|
alieu1.save()
|
||||||
|
|
||||||
|
self.cstage2 = Stage(auteur=self.p_conscrit, sujet="Avada Kedavra",
|
||||||
|
date_debut=date(2001, 5, 10),
|
||||||
|
date_fin=date(2001, 8, 26),
|
||||||
|
type_stage="sejour_dri",
|
||||||
|
niveau_scol="M2", public=False)
|
||||||
|
self.cstage2.save()
|
||||||
|
self.cstage2.matieres.add(self.matiere2)
|
||||||
|
alieu2 = AvisLieu(stage=self.cstage2, lieu=self.lieu2,
|
||||||
|
chapo="Trop nul")
|
||||||
|
alieu2.save()
|
||||||
|
|
||||||
|
|
||||||
|
self.astage1 = Stage(auteur=self.p_archi, sujet="Alohomora",
|
||||||
|
date_debut=date(1994, 5, 10),
|
||||||
|
date_fin=date(1994, 8, 26),
|
||||||
|
type_stage="recherche",
|
||||||
|
niveau_scol="M2", public=True)
|
||||||
|
self.astage1.save()
|
||||||
|
self.astage1.matieres.add(self.matiere2)
|
||||||
|
alieu3 = AvisLieu(stage=self.astage1, lieu=self.lieu1,
|
||||||
|
chapo="Trop moyen")
|
||||||
|
alieu3.save()
|
||||||
|
|
||||||
|
def assertRedirectToLogin(self, testurl):
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
return self.assertRedirects(r, settings.LOGIN_URL+"?next="+testurl)
|
||||||
|
|
||||||
|
def assertPageNotFound(self, testurl):
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
ACCÈS PUBLICS
|
||||||
|
"""
|
||||||
|
class PublicViewsTest(ExperiENSTestCase):
|
||||||
|
"""
|
||||||
|
Vérifie que les fiches de stages ne sont pas visibles hors connexion
|
||||||
|
"""
|
||||||
|
def test_stage_visibility_public(self):
|
||||||
|
self.assertRedirectToLogin(reverse('avisstage:stage',
|
||||||
|
kwargs={'pk':self.cstage1.id}))
|
||||||
|
|
||||||
|
self.assertRedirectToLogin(reverse('avisstage:stage',
|
||||||
|
kwargs={'pk':self.cstage2.id}))
|
||||||
|
|
||||||
|
self.assertRedirectToLogin(reverse('avisstage:stage',
|
||||||
|
kwargs={'pk':self.astage1.id}))
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Vérifie que les profils de normaliens ne sont pas visibles hors connexion
|
||||||
|
"""
|
||||||
|
def test_profil_visibility_public(self):
|
||||||
|
self.assertRedirectToLogin(reverse(
|
||||||
|
'avisstage:profil', kwargs={'username': self.u_conscrit.username}))
|
||||||
|
|
||||||
|
self.assertRedirectToLogin(reverse(
|
||||||
|
'avisstage:profil', kwargs={'username': self.u_archi.username}))
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Vérifie que la recherche n'est pas accessible hors connexion
|
||||||
|
"""
|
||||||
|
def test_pages_visibility_public(self):
|
||||||
|
self.assertRedirectToLogin(reverse('avisstage:recherche'))
|
||||||
|
|
||||||
|
self.assertRedirectToLogin(reverse('avisstage:recherche_resultats'))
|
||||||
|
|
||||||
|
self.assertRedirectToLogin(reverse('avisstage:stage_items'))
|
||||||
|
|
||||||
|
self.assertRedirectToLogin(reverse('avisstage:feedback'))
|
||||||
|
|
||||||
|
self.assertRedirectToLogin(reverse('avisstage:moderation'))
|
||||||
|
|
||||||
|
"""
|
||||||
|
Vérifie que l'API n'est pas accessible hors connexion
|
||||||
|
"""
|
||||||
|
def test_api_visibility_public(self):
|
||||||
|
testurl = reverse('avisstage:api_dispatch_list',
|
||||||
|
kwargs={"resource_name": "lieu",
|
||||||
|
"api_name": "v1"})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 401)
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:api_dispatch_list',
|
||||||
|
kwargs={"resource_name": "stage",
|
||||||
|
"api_name": "v1"})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 401)
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:api_dispatch_list',
|
||||||
|
kwargs={"resource_name": "profil",
|
||||||
|
"api_name": "v1"})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 401)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Vérifie que les pages d'édition ne sont pas accessible hors connexion
|
||||||
|
"""
|
||||||
|
def test_edit_visibility_public(self):
|
||||||
|
self.assertRedirectToLogin(reverse(
|
||||||
|
'avisstage:stage_edit', kwargs={'pk':self.cstage1.id}))
|
||||||
|
|
||||||
|
self.assertRedirectToLogin(reverse(
|
||||||
|
'avisstage:stage_edit', kwargs={'pk':self.astage1.id}))
|
||||||
|
|
||||||
|
self.assertRedirectToLogin(reverse(
|
||||||
|
'avisstage:stage_publication', kwargs={'pk':self.cstage1.id}))
|
||||||
|
|
||||||
|
self.assertRedirectToLogin(reverse(
|
||||||
|
'avisstage:stage_publication', kwargs={'pk':self.astage1.id}))
|
||||||
|
|
||||||
|
self.assertRedirectToLogin(reverse('avisstage:stage_ajout'))
|
||||||
|
|
||||||
|
self.assertRedirectToLogin(reverse('avisstage:profil_edit'))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
ACCÈS ARCHICUBE
|
||||||
|
"""
|
||||||
|
class ArchicubeViewsTest(ExperiENSTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
self.client.login(username='archicube', password='archicube')
|
||||||
|
|
||||||
|
def assert403Archicubes(self, testurl):
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
return self.assertRedirects(r, reverse('avisstage:403-archicubes'))
|
||||||
|
|
||||||
|
"""
|
||||||
|
Vérifie que les seules fiches de stages visibles sont les siennes
|
||||||
|
"""
|
||||||
|
def test_stage_visibility_archi(self):
|
||||||
|
self.assertPageNotFound(reverse('avisstage:stage',
|
||||||
|
kwargs={'pk':self.cstage1.id}))
|
||||||
|
|
||||||
|
self.assertPageNotFound(reverse('avisstage:stage',
|
||||||
|
kwargs={'pk':self.cstage2.id}))
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:stage',
|
||||||
|
kwargs={'pk':self.astage1.id})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Vérifie que le seul profil visible est le sien
|
||||||
|
"""
|
||||||
|
def test_profil_visibility_archi(self):
|
||||||
|
self.assertPageNotFound(reverse(
|
||||||
|
'avisstage:profil', kwargs={'username': self.u_conscrit.username}))
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:profil',
|
||||||
|
kwargs={'username': self.u_archi.username})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Vérifie que la recherche n'est pas accessible
|
||||||
|
"""
|
||||||
|
def test_pages_visibility_archi(self):
|
||||||
|
self.assert403Archicubes(reverse('avisstage:recherche'))
|
||||||
|
|
||||||
|
self.assert403Archicubes(reverse('avisstage:recherche_resultats'))
|
||||||
|
|
||||||
|
self.assert403Archicubes(reverse('avisstage:stage_items'))
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:feedback')
|
||||||
|
r = self.client.post(testurl, {"objet": "Contact",
|
||||||
|
"message": "Ceci est un texte"})
|
||||||
|
self.assertRedirects(r, reverse('avisstage:index'))
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:moderation')
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertRedirects(r, reverse('admin:login')+"?next="+testurl)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Vérifie que la seule API accessible est celle des lieux
|
||||||
|
"""
|
||||||
|
def test_api_visibility_archi(self):
|
||||||
|
testurl = reverse('avisstage:api_dispatch_list',
|
||||||
|
kwargs={"resource_name": "lieu",
|
||||||
|
"api_name": "v1"})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:api_dispatch_list',
|
||||||
|
kwargs={"resource_name": "stage",
|
||||||
|
"api_name": "v1"})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 401)
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:api_dispatch_list',
|
||||||
|
kwargs={"resource_name": "profil",
|
||||||
|
"api_name": "v1"})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 401)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Vérifie que le seul stage modifiable est le sien
|
||||||
|
"""
|
||||||
|
def test_edit_visibility_archi(self):
|
||||||
|
testurl = reverse('avisstage:stage_edit', kwargs={'pk':self.cstage1.id})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 403)
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:stage_edit', kwargs={'pk':self.astage1.id})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:stage_publication',
|
||||||
|
kwargs={'pk':self.cstage1.id})
|
||||||
|
r = self.client.post(testurl, {"publier": True})
|
||||||
|
self.assertEqual(r.status_code, 403)
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:stage_publication',
|
||||||
|
kwargs={'pk':self.astage1.id})
|
||||||
|
r = self.client.post(testurl, {"publier": True})
|
||||||
|
self.assertRedirects(r, reverse('avisstage:stage',
|
||||||
|
kwargs={"pk": self.astage1.id}))
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:stage_ajout')
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:profil_edit')
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
# TODO : test post()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
ACCÈS EN SCOLARITE
|
||||||
|
"""
|
||||||
|
class ScolariteViewsTest(ExperiENSTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
|
||||||
|
self.u_vieuxcon = User.objects.create_user('vieuxcon',
|
||||||
|
'vieuxcon@ens.fr',
|
||||||
|
'vieuxcon')
|
||||||
|
self.p_vieuxcon = self.u_vieuxcon.profil
|
||||||
|
self.p_vieuxcon.nom="Vieux con"
|
||||||
|
self.p_vieuxcon.promotion="Poufsouffle 1997"
|
||||||
|
self.p_vieuxcon.bio="Je suis un vieux con encore en scolarité"
|
||||||
|
self.p_vieuxcon.save()
|
||||||
|
|
||||||
|
self.sa_vieuxcon = SocialAccount(user=self.u_vieuxcon,
|
||||||
|
provider="clipper",
|
||||||
|
uid="vieuxcon")
|
||||||
|
self.sa_vieuxcon.save()
|
||||||
|
|
||||||
|
self.vstage1 = Stage(auteur=self.p_vieuxcon, sujet="Oubliettes",
|
||||||
|
date_debut=date(1998, 5, 10),
|
||||||
|
date_fin=date(1998, 8, 26),
|
||||||
|
type_stage="recherche",
|
||||||
|
niveau_scol="M1", public=False)
|
||||||
|
self.vstage1.save()
|
||||||
|
self.vstage1.matieres.add(self.matiere2)
|
||||||
|
alieu1 = AvisLieu(stage=self.vstage1, lieu=self.lieu2,
|
||||||
|
chapo="Pas si mal")
|
||||||
|
alieu1.save()
|
||||||
|
|
||||||
|
self.client.login(username='vieuxcon', password='vieuxcon')
|
||||||
|
|
||||||
|
"""
|
||||||
|
Vérifie que les seules fiches de stages visibles sont les siennes ou celles
|
||||||
|
publiques
|
||||||
|
"""
|
||||||
|
def test_stage_visibility_scolarite(self):
|
||||||
|
testurl = reverse('avisstage:stage',
|
||||||
|
kwargs={'pk':self.cstage1.id})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
self.assertPageNotFound(reverse('avisstage:stage',
|
||||||
|
kwargs={'pk':self.cstage2.id}))
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:stage',
|
||||||
|
kwargs={'pk':self.vstage1.id})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Vérifie que tous les profils sont visibles
|
||||||
|
"""
|
||||||
|
def test_profil_visibility_scolarite(self):
|
||||||
|
testurl = reverse('avisstage:profil',
|
||||||
|
kwargs={'username': self.u_conscrit.username})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:profil',
|
||||||
|
kwargs={'username': self.u_archi.username})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:profil',
|
||||||
|
kwargs={'username': self.u_vieuxcon.username})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Vérifie que la recherche et les autres pages sont accessible
|
||||||
|
"""
|
||||||
|
def test_pages_visibility_scolarite(self):
|
||||||
|
testurl = reverse('avisstage:recherche')
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:recherche_resultats')
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertContains(r, "Wingardium Leviosa") # Public
|
||||||
|
self.assertNotContains(r, "Avada Kedavra") # Brouillon
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:stage_items') + "?ids=" \
|
||||||
|
+ ";".join(("%d" % k.id) for k in [self.cstage1,
|
||||||
|
self.cstage2,
|
||||||
|
self.astage1])
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertContains(r, "Wingardium Leviosa") # Public
|
||||||
|
self.assertNotContains(r, "Avada Kedavra") # Brouillon
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:feedback')
|
||||||
|
r = self.client.post(testurl, {"objet": "Contact",
|
||||||
|
"message": "Ceci est un texte"})
|
||||||
|
self.assertRedirects(r, reverse('avisstage:index'))
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:moderation')
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertRedirects(r, reverse('admin:login')+"?next="+testurl)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Vérifie que toutes les API sont accessibles et qu'elles ne montrent que les
|
||||||
|
stages publics
|
||||||
|
"""
|
||||||
|
def test_api_visibility_scolarite(self):
|
||||||
|
testurl = reverse('avisstage:api_dispatch_list',
|
||||||
|
kwargs={"resource_name": "lieu",
|
||||||
|
"api_name": "v1"})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:api_dispatch_list',
|
||||||
|
kwargs={"resource_name": "stage",
|
||||||
|
"api_name": "v1"})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertContains(r, "Wingardium Leviosa") # Public
|
||||||
|
self.assertNotContains(r, "Avada Kedavra") # Brouillon
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:api_dispatch_list',
|
||||||
|
kwargs={"resource_name": "profil",
|
||||||
|
"api_name": "v1"})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Vérifie que le seul stage modifiable est le sien
|
||||||
|
"""
|
||||||
|
def test_edit_visibility_scolarite(self):
|
||||||
|
testurl = reverse('avisstage:stage_edit', kwargs={'pk':self.cstage1.id})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 403)
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:stage_edit', kwargs={'pk':self.astage1.id})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 403)
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:stage_edit', kwargs={'pk':self.vstage1.id})
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:stage_publication',
|
||||||
|
kwargs={'pk':self.cstage1.id})
|
||||||
|
r = self.client.post(testurl, {"publier": True})
|
||||||
|
self.assertEqual(r.status_code, 403)
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:stage_publication',
|
||||||
|
kwargs={'pk':self.vstage1.id})
|
||||||
|
r = self.client.post(testurl, {"publier": True})
|
||||||
|
self.assertRedirects(r, reverse('avisstage:stage',
|
||||||
|
kwargs={"pk": self.vstage1.id}))
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:stage_ajout')
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
testurl = reverse('avisstage:profil_edit')
|
||||||
|
r = self.client.get(testurl)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
# TODO : test post()
|
||||||
|
|
|
@ -14,15 +14,18 @@ urlpatterns = [
|
||||||
url(r'^stage/nouveau/$', views.manage_stage, name='stage_ajout'),
|
url(r'^stage/nouveau/$', views.manage_stage, name='stage_ajout'),
|
||||||
url(r'^stage/(?P<pk>\w+)/$', views.StageView.as_view(), name='stage'),
|
url(r'^stage/(?P<pk>\w+)/$', views.StageView.as_view(), name='stage'),
|
||||||
url(r'^stage/(?P<pk>\w+)/edit/$', views.manage_stage, name='stage_edit'),
|
url(r'^stage/(?P<pk>\w+)/edit/$', views.manage_stage, name='stage_edit'),
|
||||||
url(r'^stage/(?P<pk>\w+)/publication/$', views.publier_stage, name='stage_publication'),
|
url(r'^stage/(?P<pk>\w+)/publication/$', views.publier_stage,
|
||||||
url(r'^stages/majs/$', views.StageListe.as_view(), name='stage_majs'),
|
name='stage_publication'),
|
||||||
|
url(r'^403/archicubes/$', views.archicubes_interdits,
|
||||||
|
name='403-archicubes'),
|
||||||
|
|
||||||
url(r'^lieu/save/$', views.save_lieu, name='lieu_ajout'),
|
url(r'^lieu/save/$', views.save_lieu, name='lieu_ajout'),
|
||||||
url(r'^profil/show/(?P<username>\w+)/$', views.ProfilView.as_view(),
|
url(r'^profil/show/(?P<username>[\w@]+)/$', views.ProfilView.as_view(),
|
||||||
name='profil'),
|
name='profil'),
|
||||||
url(r'^profil/edit/$', views.ProfilEdit.as_view(), name='profil_edit'),
|
url(r'^profil/edit/$', views.ProfilEdit.as_view(), name='profil_edit'),
|
||||||
url(r'^recherche/$', views.recherche, name='recherche'),
|
url(r'^recherche/$', views.recherche, name='recherche'),
|
||||||
url(r'^recherche/resultats/$', views.recherche_resultats, name='recherche_resultats'),
|
url(r'^recherche/resultats/$', views.recherche_resultats,
|
||||||
|
name='recherche_resultats'),
|
||||||
url(r'^recherche/items/$', views.stage_items, name='stage_items'),
|
url(r'^recherche/items/$', views.stage_items, name='stage_items'),
|
||||||
url(r'^feedback/$', views.feedback, name='feedback'),
|
url(r'^feedback/$', views.feedback, name='feedback'),
|
||||||
url(r'^moderation/$', views.statistiques, name='moderation'),
|
url(r'^moderation/$', views.statistiques, name='moderation'),
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
|
from allauth.socialaccount.models import SocialAccount
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
|
||||||
def choices_length (choices):
|
def choices_length (choices):
|
||||||
return reduce (lambda m, choice: max (m, len (choice[0])), choices, 0)
|
return reduce (lambda m, choice: max (m, len (choice[0])), choices, 0)
|
||||||
|
|
||||||
|
def en_scolarite(user):
|
||||||
|
return user.profil.en_scolarite
|
||||||
|
|
|
@ -9,14 +9,16 @@ from django.urls import reverse
|
||||||
from django.contrib.admin.views.decorators import staff_member_required
|
from django.contrib.admin.views.decorators import staff_member_required
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from braces.views import LoginRequiredMixin
|
from braces.views import LoginRequiredMixin
|
||||||
from django.http import JsonResponse, HttpResponseForbidden
|
from django.http import JsonResponse, HttpResponseForbidden, Http404
|
||||||
from django.core.mail import send_mail
|
from django.core.mail import send_mail
|
||||||
from django.db.models import Q, Count
|
from django.db.models import Q, Count
|
||||||
from collections import Counter, defaultdict
|
from collections import Counter, defaultdict
|
||||||
|
|
||||||
from avisstage.models import Normalien, Stage, Lieu, AvisLieu, AvisStage
|
from .models import Normalien, Stage, Lieu, AvisLieu, AvisStage
|
||||||
from avisstage.forms import StageForm, LieuForm, AvisStageForm, AvisLieuForm, FeedbackForm
|
from .forms import StageForm, LieuForm, AvisStageForm, AvisLieuForm, FeedbackForm
|
||||||
from avisstage.views_search import *
|
from .utils import en_scolarite
|
||||||
|
|
||||||
|
from .views_search import *
|
||||||
|
|
||||||
import random, math
|
import random, math
|
||||||
|
|
||||||
|
@ -35,6 +37,11 @@ def index(request):
|
||||||
def perso(request):
|
def perso(request):
|
||||||
return render(request, 'avisstage/perso.html')
|
return render(request, 'avisstage/perso.html')
|
||||||
|
|
||||||
|
# 403 Archicubes
|
||||||
|
@login_required
|
||||||
|
def archicubes_interdits(request):
|
||||||
|
return render(request, 'avisstage/403-archicubes.html')
|
||||||
|
|
||||||
# Profil
|
# Profil
|
||||||
#login_required
|
#login_required
|
||||||
class ProfilView(LoginRequiredMixin, DetailView):
|
class ProfilView(LoginRequiredMixin, DetailView):
|
||||||
|
@ -43,7 +50,14 @@ class ProfilView(LoginRequiredMixin, DetailView):
|
||||||
|
|
||||||
# Récupération du profil
|
# Récupération du profil
|
||||||
def get_object(self):
|
def get_object(self):
|
||||||
return Normalien.objects.get(user__username=self.kwargs.get('username'))
|
|
||||||
|
# Restriction d'accès pour les archicubes
|
||||||
|
if (en_scolarite(self.request.user) or
|
||||||
|
self.kwargs.get('username') == self.request.user.username):
|
||||||
|
return Normalien.objects.get(user__username=
|
||||||
|
self.kwargs.get('username'))
|
||||||
|
else:
|
||||||
|
raise Http404
|
||||||
|
|
||||||
# Stage
|
# Stage
|
||||||
#login_required
|
#login_required
|
||||||
|
@ -53,19 +67,15 @@ class StageView(LoginRequiredMixin, DetailView):
|
||||||
|
|
||||||
# Restriction aux stages publics ou personnels
|
# Restriction aux stages publics ou personnels
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
filtre = Q(auteur__user_id=self.request.user.id) | Q(public=True)
|
filtre = Q(auteur__user_id=self.request.user.id)
|
||||||
|
|
||||||
|
# Restriction d'accès pour les archicubes
|
||||||
|
if en_scolarite(self.request.user):
|
||||||
|
filtre |= Q(public=True)
|
||||||
|
|
||||||
return Stage.objects.filter(filtre)
|
return Stage.objects.filter(filtre)
|
||||||
|
|
||||||
|
|
||||||
# Liste des stages par dernière modification
|
|
||||||
#login_required
|
|
||||||
class StageListe(LoginRequiredMixin, ListView):
|
|
||||||
model = Stage
|
|
||||||
template_name = 'avisstage/recherche/stage.html'
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
return Stage.objects.filter(public=True).order_by('-date_maj')
|
|
||||||
|
|
||||||
# FAQ
|
# FAQ
|
||||||
def faq(request):
|
def faq(request):
|
||||||
return render(request, 'avisstage/faq.html')
|
return render(request, 'avisstage/faq.html')
|
||||||
|
@ -78,7 +88,7 @@ def faq(request):
|
||||||
#login_required
|
#login_required
|
||||||
class ProfilEdit(LoginRequiredMixin, UpdateView):
|
class ProfilEdit(LoginRequiredMixin, UpdateView):
|
||||||
model = Normalien
|
model = Normalien
|
||||||
fields = ['nom', 'promotion', 'mail', 'contactez_moi', 'bio']
|
fields = ['nom', 'promotion', 'contactez_moi', 'bio']
|
||||||
template_name = 'avisstage/formulaires/profil.html'
|
template_name = 'avisstage/formulaires/profil.html'
|
||||||
|
|
||||||
# Limitation à son propre profil
|
# Limitation à son propre profil
|
||||||
|
@ -276,7 +286,7 @@ def feedback(request):
|
||||||
"errors": form.errors})
|
"errors": form.errors})
|
||||||
else:
|
else:
|
||||||
form = FeedbackForm()
|
form = FeedbackForm()
|
||||||
return render(request, 'avisstage/formulaire/feedback.html', {"form": form})
|
raise Http404()
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -14,6 +14,7 @@ import json
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from .documents import StageDocument
|
from .documents import StageDocument
|
||||||
|
from .decorators import en_scolarite_required
|
||||||
from .models import Stage
|
from .models import Stage
|
||||||
from .statics import TYPE_LIEU_OPTIONS, TYPE_STAGE_OPTIONS, NIVEAU_SCOL_OPTIONS
|
from .statics import TYPE_LIEU_OPTIONS, TYPE_STAGE_OPTIONS, NIVEAU_SCOL_OPTIONS
|
||||||
|
|
||||||
|
@ -131,12 +132,14 @@ def cherche(**kwargs):
|
||||||
return resultat, tri
|
return resultat, tri
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@en_scolarite_required
|
||||||
def recherche(request):
|
def recherche(request):
|
||||||
form = SearchForm()
|
form = SearchForm()
|
||||||
return render(request, 'avisstage/recherche/recherche.html',
|
return render(request, 'avisstage/recherche/recherche.html',
|
||||||
{"form": form})
|
{"form": form})
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@en_scolarite_required
|
||||||
def recherche_resultats(request):
|
def recherche_resultats(request):
|
||||||
stages = []
|
stages = []
|
||||||
tri = ''
|
tri = ''
|
||||||
|
@ -203,6 +206,7 @@ def recherche_resultats(request):
|
||||||
"tri": tri, "vue": vue, "lieux": lieux})
|
"tri": tri, "vue": vue, "lieux": lieux})
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@en_scolarite_required
|
||||||
def stage_items(request):
|
def stage_items(request):
|
||||||
try:
|
try:
|
||||||
stageids = [int(a) for a in request.GET.get("ids", "").split(';')]
|
stageids = [int(a) for a in request.GET.get("ids", "").split(';')]
|
||||||
|
|
|
@ -29,11 +29,21 @@ INSTALLED_APPS = (
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'django.contrib.gis',
|
'django.contrib.gis',
|
||||||
|
'django.contrib.sites',
|
||||||
|
|
||||||
'django_elasticsearch_dsl',
|
'django_elasticsearch_dsl',
|
||||||
|
|
||||||
|
'widget_tweaks',
|
||||||
|
'allauth_ens',
|
||||||
|
|
||||||
|
'allauth',
|
||||||
|
'allauth.account',
|
||||||
|
'allauth.socialaccount',
|
||||||
|
'allauth_cas',
|
||||||
|
|
||||||
|
'allauth_ens.providers.clipper',
|
||||||
|
|
||||||
'tastypie',
|
'tastypie',
|
||||||
'django_cas_ng',
|
|
||||||
'braces',
|
'braces',
|
||||||
'tinymce',
|
'tinymce',
|
||||||
'taggit',
|
'taggit',
|
||||||
|
@ -94,6 +104,7 @@ USE_L10N = True
|
||||||
|
|
||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|
||||||
|
SITE_ID = 1
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
# Static files (CSS, JavaScript, Images)
|
||||||
# https://docs.djangoproject.com/en/1.7/howto/static-files/
|
# https://docs.djangoproject.com/en/1.7/howto/static-files/
|
||||||
|
@ -113,9 +124,13 @@ CAS_EMAIL_FORMAT = "%s@clipper.ens.fr"
|
||||||
CAS_FORCE_CHANGE_USERNAME_CASE = "lower"
|
CAS_FORCE_CHANGE_USERNAME_CASE = "lower"
|
||||||
CAS_VERSION = 'CAS_2_SAML_1_0'
|
CAS_VERSION = 'CAS_2_SAML_1_0'
|
||||||
|
|
||||||
LOGIN_URL = reverse_lazy('login')
|
ACCOUNT_ADAPTER = 'avisstage.allauth_adapter.AccountAdapter'
|
||||||
LOGOUT_URL = reverse_lazy('logout')
|
SOCIALACCOUNT_ADAPTER = 'avisstage.allauth_adapter.SocialAccountAdapter'
|
||||||
|
|
||||||
|
LOGIN_URL = reverse_lazy('account_login')
|
||||||
|
LOGOUT_URL = reverse_lazy('account_logout')
|
||||||
|
LOGIN_REDIRECT_URL = reverse_lazy('avisstage:perso')
|
||||||
|
ACCOUNT_HOME_URL = reverse_lazy('avisstage:index')
|
||||||
|
|
||||||
LOGGING = {
|
LOGGING = {
|
||||||
'version': 1,
|
'version': 1,
|
||||||
|
|
|
@ -34,3 +34,6 @@ ELASTICSEARCH_DSL = {
|
||||||
'hosts': 'localhost:9200'
|
'hosts': 'localhost:9200'
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CLIPPER_LDAP_SERVER = 'ldaps://localhost:636'
|
||||||
|
|
|
@ -50,3 +50,6 @@ ELASTICSEARCH_DSL = {
|
||||||
'hosts': '127.0.0.1:9200'
|
'hosts': '127.0.0.1:9200'
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CLIPPER_LDAP_SERVER = 'ldaps://ldap.spi.ens.fr:636'
|
||||||
|
|
|
@ -2,13 +2,11 @@ from django.conf import settings
|
||||||
from django.conf.urls import include, url
|
from django.conf.urls import include, url
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from django_cas_ng import views as django_cas_views
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^', include('avisstage.urls', namespace='avisstage')),
|
url(r'^', include('avisstage.urls', namespace='avisstage')),
|
||||||
|
|
||||||
url(r'^login/$', django_cas_views.login, name = "login"),
|
url(r'^account/', include('allauth_ens.urls')),
|
||||||
url(r'^logout/$', django_cas_views.logout, name = "logout"),
|
|
||||||
url(r'^tinymce/', include('tinymce.urls')),
|
url(r'^tinymce/', include('tinymce.urls')),
|
||||||
url(r'^taggit_autosuggest/', include('taggit_autosuggest.urls')),
|
url(r'^taggit_autosuggest/', include('taggit_autosuggest.urls')),
|
||||||
url(r'^admin/', include(admin.site.urls)),
|
url(r'^admin/', include(admin.site.urls)),
|
||||||
|
|
|
@ -9,3 +9,4 @@ pytz==2018.*
|
||||||
django-tastypie==0.14.*
|
django-tastypie==0.14.*
|
||||||
lxml==4.2.*
|
lxml==4.2.*
|
||||||
django-elasticsearch-dsl==0.4.*
|
django-elasticsearch-dsl==0.4.*
|
||||||
|
django-allauth-ens==1.1.*
|
||||||
|
|
54
scripts/initalize_allauth.py
Normal file
54
scripts/initalize_allauth.py
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from allauth.account.models import EmailAddress
|
||||||
|
from allauth.socialaccount.models import SocialAccount
|
||||||
|
|
||||||
|
from avisstage.models import Normalien
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
accounts = SocialAccount.objects.all().prefetch_related("user")
|
||||||
|
profils = Normalien.objects.all()
|
||||||
|
addresses = EmailAddress.objects.all()
|
||||||
|
|
||||||
|
|
||||||
|
addr_dict = defaultdict(set)
|
||||||
|
for addr in addresses:
|
||||||
|
addr_dict[addr.user_id].add(addr.email)
|
||||||
|
|
||||||
|
|
||||||
|
profil_dict = {profil.user_id: profil for profil in profils}
|
||||||
|
|
||||||
|
addr_to_create = []
|
||||||
|
|
||||||
|
for acc in accounts:
|
||||||
|
u = acc.user
|
||||||
|
|
||||||
|
try:
|
||||||
|
profil = profil_dict[u.id]
|
||||||
|
except KeyError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
to_addr = set()
|
||||||
|
if profil.mail:
|
||||||
|
to_addr.add(profil.mail)
|
||||||
|
cp_ml = "%s@clipper.ens.fr" % acc.uid
|
||||||
|
try:
|
||||||
|
cp_ml = acc.extra_data["ldap"]["email"]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
to_addr.add(cp_ml)
|
||||||
|
|
||||||
|
addrs = addr_dict[u.id]
|
||||||
|
|
||||||
|
print(u.username, ";".join(list(to_addr)), ";".join(list(addrs)))
|
||||||
|
to_addr -= addrs
|
||||||
|
has_prim = len(addrs) > 0
|
||||||
|
|
||||||
|
for addr in to_addr:
|
||||||
|
ml = EmailAddress(email=addr, user=u, verified=True, primary=has_prim)
|
||||||
|
has_prim = False
|
||||||
|
addr_to_create.append(ml)
|
||||||
|
|
||||||
|
if "--fake" not in sys.argv:
|
||||||
|
EmailAddress.objects.bulk_create(addr_to_create)
|
Loading…
Add table
Reference in a new issue