Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • mediatek/site-interludes
  • aeltheos/site-kwei
  • mediatek/site-kwei
3 results
Show changes
Showing
with 1348 additions and 150 deletions
{% extends "base.html" %}
{% block title %}404 Not Found{% endblock %}
{% block "content" %}
<h2>Page introuvable</h2>
<p>La page que vous avez demandée n'existe plus ou n'a jamais existé.</p>
......
{% extends "base.html" %}
{% block title %}500 Internal Error{% endblock %}
{% block "content" %}
<h2>Erreur interne</h2>
<p>Un incident technique est survenu pendant l'affichage de cette page.</p>
......
<div id="planning" style="margin-left: calc(-49vw + 50%); width: 97vw; background-color: white; padding: 10px;"></div>
<!--
In order to limit the planning's width, we cheat using the timeline's groups
I.E we set all dates to the first day (Friday) and set groups allowing vertical display:
-->
<script type="text/javascript">
// https://visjs.org/
// DOM element where the Timeline will be attached
const container = document.getElementById('planning');
const groups = new vis.DataSet([
{id: 0, content: "Ven.", order: 0},
{id: 1, content: "Sam.", order: 1},
{id: 2, content: "Dim.", order: 2},
]);
// Items in the timeline
const items = new vis.DataSet([
{% for slot in planning %}
{% if slot.start_day == slot.end_day %}
{
content: '<div style="background-color: yellow;"><a class="hidden" href="#{{ slot.activity.slug }}"><div><strong>{{ slot }}</strong><br>{{ slot.room|default:"" }}</div></a></div>',
title: '<strong>{{ slot }}</strong><br>{{ slot.room|default:"" }}',
start: '{{ slot.planning_start|date:"Y-m-d H:i:s"}}',
align: 'left',
group: {{ slot.start_day }},
end:'{{ slot.planning_end|date:"Y-m-d H:i:s"}}',
className: "color-{{ slot.color }}",
},
{% else %} // activity spans multiple days
{
content: '<a class="hidden" href="#{{ slot.activity.slug }}"><div><strong>{{ slot }}</strong><br>{{ slot.room|default:"" }}</div></a>',
title: '<strong>{{ slot }}</strong><br>{{ slot.room|default:"" }}',
start: '{{ slot.planning_start|date:"Y-m-d H:i:s"}}',
align: 'left',
group: {{ slot.start_day }},
end:'{{ settings.date_2|date:"Y-m-d"}} 04:00:00',
className: "color-{{ slot.color }}",
},
{
content: '<a class="hidden" href="#{{ slot.activity.slug }}"><div><strong>{{ slot }}</strong><br>{{ slot.room|default:"" }}</div></a>',
title: '<strong>{{ slot }}</strong><br>{{ slot.room|default:"" }}',
start: '{{ settings.date_start|date:"Y-m-d"}} 04:00:00',
align: 'left',
group: {{ slot.end_day }},
end:'{{ slot.planning_end|date:"Y-m-d H:i:s"}}',
className: "color-{{ slot.color }}",
},
{% endif %}
{% endfor %}
]);
// Configuration for the Timeline
const start = '{{ settings.date_start|date:"Y-m-d"}} 08:00:00';
const end = '{{ settings.date_start|date:"Y-m"}}-{{ saturday }} 04:00:00';
const options = {
showMajorLabels: false,
showCurrentTime: false,
locale: "fr",
groupOrder: "order",
start: start,
min: start,
end: end,
max: end,
selectable: false,
zoomable: false,
};
// Create a Timeline
const timeline = new vis.Timeline(container, items, options);
timeline.setGroups(groups);
// timeline.on('select', function (properties) {
// alert('selected items: ' + properties.items);
// });
</script>
<style>
.vis-item {
background-color: var(--color_bg_1);
color: white;
}
.vis-item-content {
width: 100%;
}
.vis-item a, .vis-item a:link, .vis-item a:visited {
text-decoration: none;
color: white;
width: 100%;
}
.vis-item a div {
width: 100%;
}
.vis-item:hover {
background-color: var(--color_bg_2);
}
.vis-time-axis .grid.vis-odd {
background: #444;
}
/* Color specific things */
:root {
/* red */
--color_1: #e84855;
--color_1_hover: #da1b2b;
--color_1_fg: white;
/* orange */
--color_2: #dd7230;
--color_2_hover: #c15d1f;
--color_2_fg: white;
/* yellow */
--color_3: #f9dc5c;
--color_3_hover: #f7d126;
--color_3_fg: black;
/* green */
--color_4: #7cae7a;
--color_4_hover: #5f8b55;
--color_4_fg: white;
/* blue */
--color_5: #3185fc;
--color_5_hover: #0467f1;
--color_5_fg: white;
/* dark blue */
--color_6: #4c4c7c;
--color_6_hover: #26263c;
--color_6_fg: white;
/* black */
--color_7: #483D3F;
--color_7_hover: #2c2627;
--color_7_fg: white;
}
.vis-item.color-a {
background-color: var(--color_1);
}
.vis-item.color-a a, .vis-item.color-a a:link, .vis-item.color-a a:visited {
color: var(--color_1_fg);
}
.vis-item.color-a:hover {
background-color: var(--color_1_hover)
}
.vis-item.color-b {
background-color: var(--color_2);
}
.vis-item.color-b a, .vis-item.color-b a:link, .vis-item.color-b a:visited {
color: var(--color_2_fg);
}
.vis-item.color-b:hover {
background-color: var(--color_2_hover)
}
.vis-item.color-c {
background-color: var(--color_2);
}
.vis-item.color-c a, .vis-item.color-c a:link, .vis-item.color-c a:visited {
color: var(--color_2_fg);
}
.vis-item.color-c:hover {
background-color: var(--color_2_hover)
}
.vis-item.color-c {
background-color: var(--color_3);
}
.vis-item.color-c a, .vis-item.color-c a:link, .vis-item.color-c a:visited {
color: var(--color_3_fg);
}
.vis-item.color-c:hover {
background-color: var(--color_3_hover)
}
.vis-item.color-d {
background-color: var(--color_4);
}
.vis-item.color-d a, .vis-item.color-d a:link, .vis-item.color-d a:visited {
color: var(--color_4_fg);
}
.vis-item.color-d:hover {
background-color: var(--color_4_hover)
}
.vis-item.color-e {
background-color: var(--color_5);
}
.vis-item.color-e a, .vis-item.color-e a:link, .vis-item.color-e a:visited {
color: var(--color_5_fg);
}
.vis-item.color-e:hover {
background-color: var(--color_5_hover)
}
.vis-item.color-f {
background-color: var(--color_6);
}
.vis-item.color-f a, .vis-item.color-f a:link, .vis-item.color-f a:visited {
color: var(--color_6_fg);
}
.vis-item.color-f:hover {
background-color: var(--color_6_hover)
}
.vis-item.color-g {
background-color: var(--color_7);
}
.vis-item.color-g a, .vis-item.color-g a:link, .vis-item.color-g a:visited {
color: var(--color_7_fg);
}
.vis-item.color-g:hover {
background-color: var(--color_7_hover)
}
</style>
{% if settings.has_caption %}
<div class="caption">
<p><strong>Légende :</strong></p>
<ul style="list-style-type: none; margin-left:-20px">
{% if settings.caption_red %}<li><span style="background-color: var(--color_1);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> {{ settings.caption_red }}</li>{% endif %}
{% if settings.caption_orange %}<li><span style="background-color: var(--color_2);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> {{ settings.caption_orange }}</li>{% endif %}
{% if settings.caption_yellow %}<li><span style="background-color: var(--color_3);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> {{ settings.caption_yellow }}</li>{% endif %}
{% if settings.caption_green %}<li><span style="background-color: var(--color_4);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> {{ settings.caption_green }}</li>{% endif %}
{% if settings.caption_blue %}<li><span style="background-color: var(--color_5);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> {{ settings.caption_blue }}</li>{% endif %}
{% if settings.caption_dark_blue %}<li><span style="background-color: var(--color_6);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> {{ settings.caption_dark_blue }}</li>{% endif %}
{% if settings.caption_black %}<li><span style="background-color: var(--color_7);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> {{ settings.caption_black }}</li>{% endif %}
</ul>
</div>
{% endif %}
{% if settings.planning_file %}
<div><p><a class="button" href="{{ settings.planning_file.url }}"><i class="fa fa-download"></i> Télécharger le planning</a></p></div>
{% endif %}
{% extends "base.html" %}
{% load static %}
{% block head %}
<script src="{% static 'js/vis-timeline.min.js' %}"></script>
{% endblock %}
{% block nav_activite %}current{% endblock %}
{% block "content" %}
{% if settings.activity_submission_open %}
<ul class="messagelist">
<li class="info">
Vous pouver proposer une activité en remplissant <a href="{% url 'activity_submission' %}">ce formulaire</a>.
</li>
</ul>{% endif %}
{% if settings.display_planning %}
<h2>Planning</h2>
{% include "_planning.html" %}
{% endif %}
<h2>Activités</h2>
<p>Durant tout l'événement, des jeux seront en libre-service et des tables disponibles pour jouer.
Certaines activités (JDRs, murders...) ne pourront se faire qu'avec inscription au vue d'un nombre de places limité.
</p>
<p>
TODO : planning et infos si vous voulez proposez une activité
Certaines activités ne pourront se faire qu'avec inscription au vue d'une préparation en amont ou d'un nombre de places limité.
</p>
{% if settings.activity_submission_form %}
<p>Vous pouver proposer une activité en remplissant <a href="{{ settings.activity_submission_form }}">ce formulaire</a>.</p>
{% endif %}
{% if activities %}
<p id="act-list"><strong>Liste des activités&nbsp;:</strong></p>
<ul>
{% for activity in activities %}
<li><a href="#{{ activity.slug }}">{{ activity.title }}</a></li>
{% endfor %}
</ul>
{% endif %}
{% for activity in activities %}
<h3>{{ activity.title }}</h3>
<h3 id="{{ activity.slug }}">{{ activity.title }}</h3>
<dl>
<dt>Durée :</dt><dd>{{ activity.duration }}</dd>
<dt>MJ :</dt><dd>{{ activity.host_name }}</dd>
<dt>Nombre de places :</dt><dd>{{ activity.nb_participants }}</dd>
<dt>Sur inscription :</dt><dd>{% if activity.must_subscribe %} Oui {% else %} Non {% endif %}</dd>
<dt>Description :</dt><dd>{{ activity.description|linebreaksbr }}</dd>
<dt>Durée :</dt><dd>{{ activity.pretty_duration }}</dd>
{% if activity.host_name %}
<dt>Orga :</dt><dd>{{ activity.host_name }}</dd>
{% endif %}
{% if settings.show_host_emails and activity.show_email %}
<dt>Contact :</dt><dd><a href="mailto:{{ activity.host_email }}">{{ activity.host_email }}</a></dd>
{% endif %}
<dt>Type :</dt><dd>{{ activity.pretty_type }}</dd>
<dt>Places :</dt><dd>{{ activity.nb_participants }}</dd>
{% if activity.slots and settings.display_planning %}
<dt>Heure/Lieu :</dt><dd>{% for slot in activity.slots %}
{{ slot.start|date:"l H:i" }}{% if slot.room %} {{ slot.room }}{% endif %}{% if not forloop.last %},<br> {% endif %}
{% endfor %}
</dd>
{% endif %}
<dt>Description :</dt>
</dl>
<div class="desc">
{% if activity.desc_as_html %}
{{ activity.description|safe }}
{% else %}
<p class="indent">{{ activity.description|linebreaksbr }}</p>
{% endif %}
</div>
<a style="text-decoration: none;" href="#act-list"><i class="fa fa-arrow-up"></i> Retour à la liste</a>
{% empty %}
<p>Il n'y a aucune activité pour l'instant, revenez dans quelques jours pour avoir une liste plus remplie.</p>
{% endfor %}
{% endblock %}
\ No newline at end of file
{% endblock %}
{% extends "base.html" %}
{% load static %}
{% block nav_activite %}current{% endblock %}
{% block "content" %}
<h2>Proposer une activité</h2>
{{ form.non_field_errors }}
<form method="post" action="{% url 'activity_submission' %}">
{% csrf_token %}
<ul class="messagelist">
<li class="info">
Les informations publiques (qui apparaîtrons sur la page <a href="{% url 'activites' %}">activites</a>) sont
celles <span class="underline">soulignées</span>.<br>
Les autres ne serons vues que par les orgas.
</li>
</ul>
<table>
<tr><td><strong class="underline">Titre&nbsp;:</strong></td><td> {{ form.title }}</td></tr>
<tr><td><strong class="underline">Type d'activité&nbsp;:</strong></td><td> {{ form.act_type }}</td></tr>
<tr><td><strong class="underline">Type de jeu&nbsp;:</strong></td><td> {{ form.game_type }}</td></tr>
</table>
<p><strong class="underline">Description&nbsp;:</strong> ce texte sera affiché sur la page
<a href="{% url 'activites' %}">activités</a> pour présenter votre activité.
</p>
{{ form.description }}
<h3>Organisateurs</h3>
<table>
<tr><td><strong class="underline">Nom&nbsp;:</strong></td><td> {{ form.host_name }}</td></tr>
<tr><td><strong class="underline">Email&nbsp;:</strong></td><td> {{ form.host_email }}</td></tr>
<tr><td><strong>Compte associé&nbsp;:&nbsp;</strong></td><td> {{ request.user.email }}</td></tr>
</table>
<p>
L'email de votre compte sera le principal moyen de contact.
Si vous ne souhaitez pas qu'il soit affiché, précisez le ci-dessous.
Vous pouvez également spécifier d'autres moyens de contact, ainsi que d'autres
organisateurs si vous êtes plusieurs.
</p>
{{ form.host_info }}
<h3>Participants et inscription</h3>
<table>
<tr><td><strong class="underline">Nécessite une inscription&nbsp;:</strong></td><td> {{ form.must_subscribe }}</td></tr>
<tr><td><strong>Me communiquer la liste des participants à l'avance&nbsp;:</strong></td><td> {{ form.communicate_participants }}</td></tr>
<tr><td><strong class="underline">Nombre max de participants&nbsp;:</strong></td><td> {{ form.max_participants }} (mettez 0 pour illimité)</td></tr>
{% if form.max_participants.errors %}<tr><td></td><td>{{ form.max_participants.errors }}</td></tr>{% endif %}
<tr><td><strong class="underline">Nombre min de participants&nbsp;:</strong></td><td> {{ form.min_participants }}</td></tr>
{% if form.min_participants.errors %}<tr><td></td><td>{{ form.min_participants.errors }}</td></tr>{% endif %}
</table>
<h3>Durée et crénaux</h3>
<table>
<tr><td><strong class="underline">Durée approximative&nbsp;:</strong></td><td> {{ form.duration }} (format hh:mm:ss)</td></tr>
{% if form.duration.errors %}<tr><td></td><td>{{ form.duration.errors }}</td></tr>{% endif %}
<tr><td><strong>Nombre de crénaux souhaités&nbsp;:</strong></td><td> {{ form.desired_slot_nb }}</td></tr>
{% if form.desired_slot_nb.errors %}<tr><td></td><td>{{ form.desired_slot_nb.errors }}</td></tr>{% endif %}
<tr><td><strong>Disponibilités&nbsp;:</strong></td></tr>
<tr><td>&nbsp;-&nbsp;Vendredi soir&nbsp;:</td><td>{{ form.available_friday_evening }}</td></tr>
<tr><td>&nbsp;-&nbsp;Vendredi nuit&nbsp;:</td><td>{{ form.available_friday_night }}</td></tr>
<tr><td>&nbsp;-&nbsp;Samedi matin&nbsp;:</td><td>{{ form.available_saturday_morning }}</td></tr>
<tr><td>&nbsp;-&nbsp;Samedi après-midi&nbsp;:</td><td>{{ form.available_saturday_afternoon }}</td></tr>
<tr><td>&nbsp;-&nbsp;Samedi soir&nbsp;:</td><td>{{ form.available_saturday_evening }}</td></tr>
<tr><td>&nbsp;-&nbsp;Samedi nuit&nbsp;:</td><td>{{ form.available_saturday_night }}</td></tr>
<tr><td>&nbsp;-&nbsp;Dimanche matin &nbsp;:</td><td>{{ form.available_sunday_morning }}</td></tr>
<tr><td>&nbsp;-&nbsp;Dimanche après-midi&nbsp;:</td><td>{{ form.available_sunday_afternoon }}</td></tr>
</table>
<p>Si vous avez des contraintes particulières, vous pouvez les préciser ici&nbsp;:</p>
{{ form.constraints }}
<h3>Modalités pratiques</h3>
{% comment "En présentiel" %}<p><strong>Présentiel/distanciel&nbsp;:</strong> &nbsp;{{ form.status }}</p>{% endcomment %}
<p><strong>Besoins spécifiques&nbsp;:</strong></p>
<ul>
<li>Vous faut-il une ou plusieurs salles&nbsp;?</li>
<li>Vous faut-il du matériel spécial&nbsp;?</li>
<li>Et tout autre besoin de ce type...</li>
</ul>
{{ form.needs }}
<h3>Commentaires</h3>
<p>D'autre choses à nous communiquer qui ne rentre pas dans les champs précédents&nbsp;?</p>
{{ form.comments }}
<h3>Soumettre</h3>
<p>L'activité n'est plus modifiable une fois soumise. Les administrateurs la reliront avant de l'afficher sur le site.</p>
<div class="flex">
<input type="submit" value="Soumettre mon activité">
<a class="button" href="{% url 'profile' %}">Annuler</a>
</div>
</form>
{% endblock %}
{% spaceless %}
{% load static %}
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interludes {% if settings.date_start %}{{ settings.date_start.year }}{% endif %}</title>
<head>
<!-- WEBSITE VERSION {{ constants.WEBSITE_FULL_VERSION }} -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Interludes{% if settings.date_start %} {{ settings.date_start.year }}{% endif %}{% endblock %}</title>
<meta name="description" content="Inscriptions et infos sur les interENS ludiques{% if settings.date_start %}, édition {{ settings.date_start.year }}{% endif %}">
<meta name="keywords" content="Interludes ENS événement COF {% if settings.date_start %}{{ settings.date_start.year }} {% endif %}InterENS">
<link rel="icon" type="image/png" href="{% static 'imgs/favicon.ico' %}">
<meta name="keywords" content="Interludes ENS {% if settings.date_start %}{{ settings.date_start.year }} {% endif %}InterENS">
<link rel="icon" type="image/png" href="{% static 'imgs/2023/favicon.ico' %}">
<link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}?v={{ constants.CSS_VERSION }}">
<link rel="stylesheet" type="text/css" href="{% static 'css/font-awesome-all.min.css' %}">
{% block head %}{% endblock %}
</head>
<body>
<header>
<div id="header_logo">
<h1><a href="/">Interludes {% if settings.date_start %}{{ settings.date_start.year }}{% endif %}</a></h1>
<div id="header_logo" class="easter_egg">
<h1><a href="/"><img src="{% static 'imgs/2023/logo.png' %}">&nbsp;Interludes{% if settings.date_start %} {{ settings.date_start.year }}{% endif %}&nbsp;</a></h1>
</div>
<div id="head_main_infos">
<div id="location">ENS Ulm</div>
<div id="date">{% if settings.date_start %}
<div id="location">{{ settings.hosting_school }}</div>
<div id="date">{% if settings.date_start %}
{% if settings.date_end %}
{{ settings.date_start.day }}-{{ settings.date_end }}
{% else %}
......@@ -33,7 +37,18 @@
</div>
</header>
<nav>
<script type="text/javascript">
function toggle_menu() {
var nav = document.getElementById("nav");
if (nav.className === "") {
nav.className += "responsive";
} else {
nav.className = "";
}
}
</script>
<nav id="nav">
<a href="{% url 'home' %}" rel="text/html"
class="{% block nav_home %}{% endblock %}">
Accueil
......@@ -47,54 +62,69 @@
Activités
</a>
<a href="{% url 'FAQ' %}" rel="text/html"
class="{% block nav_faq %}{% endblock %} ">
class="{% block nav_faq %}{% endblock %}">
FAQ
</a>
{% if request.user.is_authenticated %}
<a href="{% url 'accounts:profile' %}"
class="{% block nav_profile %}{% endblock %} ">
<a href="{% url 'profile' %}"
class="{% block nav_profile %}{% endblock %}">
Mon compte
</a>
{% else %}
<a href="{% url 'accounts:login' %}"
class="{% block nav_login %}{% endblock %} ">
class="{% block nav_login %}{% endblock %}">
Connexion
</a>
{% endif %}
{% if user.is_superuser %}
<a href="{% url 'admin_pages:index' %}"
class="{% block nav_admin %}{% endblock %}">
Administration
</a>
{% endif %}
<a href="javascript:void(0);" class="icon" onclick="toggle_menu()">
<i class="fa fa-bars"></i>
</a>
</nav>
<main>
{% if messages %}
<ul class="messagelist">
{% for message in messages %}
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
{% endfor %}
</ul>
{% endif %}
{% if settings.global_message %}
{% if settings.global_message_as_html %}
{{ settings.global_message|safe }}
{% else %}
<ul class="messagelist"><li class="info">{{ settings.global_message }}</li></ul>
{% endif %}
{% endif %}
{% block "content" %}
{% endblock %}
</main>
<footer>
<div id="sponsors">
<a class="external" href="https://www.ens.psl.eu/">
<img src="{% static "imgs/ens_psl.png" %}"
alt="École Normale Supérieure de Paris | Université Paris Sciences et Lettres"
title="École Normale Supérieure de Paris | Université Paris Sciences et Lettres"
/>
</a>
<a class="external" href="https://cof.ens.fr/">
<img src="{% static "imgs/cof.svg" %}"
alt="COF de l'ENS"
title="COF de l'ENS"
/>
</a>
</div>
{% if settings.contact_email %}
<p>Pour tout problème, contacter&nbsp;:<br>{{ settings.contact_email }}</p>
{% endif %}
</footer>
<footer>
<div id="sponsors">
<a class="external" href="https://www.ens-paris-saclay.fr/">
<img src="{% static "imgs/2023/ens_ps.png" %}" alt="École Normale Supérieure Paris-Saclay"
title="École Normale Supérieure Paris-Saclay" />
</a>
<a class="external" href="https://wiki.crans.org/VieBdl">
<img src="{% static "imgs/2023/bdl.png" %}" alt="Bureau des Loisirs de l'ENS de Paris-Saclay"
title="Bureau des Loisirs de l'ENS Paris-Saclay" />
</a>
</div>
{% if settings.contact_email %}
<p>Pour tout problème, contacter&nbsp;:<br><span class="antispam">{{ settings.contact_email_reversed }}</span>
</p>
{% endif %}
</footer>
</body>
</html>
{% endspaceless %}
{% extends "base.html" %}
{% load static %}
{% block nav_faq %}current{% endblock %}
{% block "content" %}
<h2>Dois-je être inscrit&middot;e pour participer&nbsp;?</h2>
<p>Les interludes ayant lieu à distance cette année, l'inscription est facultative.
Une inscription est seulement nécessaire pour certaines activités au nombre de places limité.
Sans inscription tu peux rejoindre notre
{% if settings.discord_link %}
<a href="{{ settings.discord_link }}">serveur discord</a>
{% else %}serveur discord{% endif %}
et y participer au jeux libres et à toutes les activités sans inscriptions.
</p>
<h2>Comment seront organisées les interludes à distance&nbsp;?</h2>
<p>Les interludes passeront principalement par un
{% if settings.discord_link %}<a href="{{ settings.discord_link }}">serveur discord</a>{% else %}serveur discord{% endif %}.
Nous y regrouperont
une liste de sites permettant de jouer en ligne et des canaux vocaux dédiés.
</p>
<p>Pour les <a href="{% url 'activites' %}">activités</a> proposées, leur description
vous indiquera s'il vous faudra autre chose qu'un ordinateur et une connexion internet pour participer.
</p>
<p>Le serveur contiendra des salons écrits et vocaux pour organiser des parties sur d'autres plateformes en lignes.</p>
<h2>Comment rejoindre le serveur discord&nbsp;?</h2>
{% if settings.discord_link %}
<p>Suivez <a href="{{ settings.discord_link }}">ce lien</a>.</p>
{% else %}
<p>Le lien vous sera communiqué par mail peu avant l'événement. Il apparaîtra également sur ce site.</p>
{% endif %}
<p>Vous pouvez utiliser Discord sur navigateur sans créer de compte (mais se connecter sans compte
pose parfois des problèmes). Sinon il existe une application mobile (Android et iOS) et un programme (Linux/Windows/Mac)
permettant d'y accèder via un compte.
</p>
<h2>Où jouer en ligne&nbsp;?</h2>
<p>Voici une liste (non-exhaustive) des plateformes de jeu en ligne&nbsp;:
<ul>
<li><a href="https://fr.boardgamearena.com/">Board Game Arena</a> (site gratuit nécessitant un compte)</li>
<li><a href="https://store.steampowered.com/app/286160/Tabletop_Simulator/">Tabletop Simulator</a> (jeu vendu 20€ sur steam)</li>
<li>Des sites spécialisés (gratuits)&nbsp;<ul>
<li>Pour Codenames : <a href="https://codenames.game/">codenames.game</a> ou <a href="https://www.horsepaste.com/">horsepaste.com</a>.</li>
<li>Pour Hanabi : <a href="https://hanab.live/">hanab.live</a> (nécessite un compte).</li>
<li>Pour Catan : <a href="https://colonist.io/">colonist.io</a>.</li>
<li>Pour Shadow-Hunter : <a href="http://shadowhunters.live/">shadowhunters.live</a>.</li>
<li>Pour Diplomacy : <a href="https://vdiplomacy.com/">vdiplomacy.com</a> (nécessite un compte).</li>
</ul></li>
<li>N'importe quel jeu vidéo multijoueur</li>
</ul>
Vous trouverez une liste plus fournie sur le discord interludes.
</p>
<h2>Comment proposer une activité&nbsp;?</h2>
{% if settings.activity_submission_open %}
<p>Vous pouver proposer une activité en remplissant <a href="{% url 'activity_submission' %}">ce formulaire</a>.</p>
<p>Il vous faudra être connecté et renseigner, le titre, une description, le nombre de places, la durée, les horaires possibles/idéaux, et tout autre besoin particulier...</p>
{% else %}
<p>L'appel a activités est fermé pour le moment.
Contactez nous en cas de besoin urgent ou d'idée trop géniale pour être délaissée.</p>
{% endif %}
<h2>Comment sont réparties les activités&nbsp;?</h2>
<p>
La répartition est faite par un algorithme puis vérifiée à la main.
Dans la mesure du possible, l'algorithme essaie d'attribue au moins une activité par personne. Par conséquent, si vous ne mettez qu'une seule activité, vous avez plus de chance de l'avoir.
</p>
<p>
Les activités qui n'ont pas de limite de place (et toutes les activités avec moins de demande que de places) ne comptent pas pour ce système, donc vous pouvez les mettre et vous ne serez pas pénalisés.
</p>
<p>
Vous ne pourrez pas avoir deux activités qui se déroulent en même temps. Si l'une vous est attribué l'autre souhait sera ignoré.
</p>
<p>On n'a pas trouvé le code des années précédentes, mais je suspecte fortement que ce soit un algo similaire en départageant les égalités aléatoirement plutôt qu'au shotgun.</p>
<p>Plus précisément : l'algorithme se base sur le problème hôpital-résident&nbsp;:</p>
<ol>
<li>Il commence par essayer d'attribuer une activité à chaque participant.es au mieux possible, en utilisant la librairie matching de python. Les égalités sont départagées aléatoirement. Plus un choix est haut dans votre liste de souhait, plus vous avez de chance de vous le voir attribuer. Si vous n'avez qu'un seul choix, vous avez plus de chance de vous le voir attribué. (les participant.es avec un seul choix sont automatique placé.es avant ceux qui en ont plusieurs)</li>
<li>Toutes les activités attribuées sont supprimées, ainsi que les voeux résolus des joueurs.</li>
<li>Tant qu'il reste des place dans des activités et des participant.es qui veulent y participer, on recommence à l'étape 1.</li>
</ol>
<p>Le code est sur <a href="https://github.com/Imakoala/InterludesMatchings">github</a>, il ne marche pas encore parfaitement, et on risque de devoir bidouiller à la main en plus pour résoudre tous les cas particuliers (conflits d'horaires, activité présente plusieurs fois...).
{% endblock %}
{% extends "base.html" %}
{% load static %}
{% block nav_faq %}current{% endblock %}
{% block "content" %}
<h2>Comment se rendre à l'ENS Ulm ?</h2>
<p>Plan transport + instructions</p>
<h2>Conditions sanitaires ?</h2>
<p>On ne sait pas trop...</p>
<h2>Comment s'incrire ?</h2>
{% if settings.inscriptions_open %}
<p> Les <a href="{% url 'inscription' %}">inscriptions</a> sont ouvertes. Vous pouvez vous inscrire aux repas et à l'hébergement.
{% if settings.activity_inscriptions_open %}
Vous pouvez aussi vous inscrire aux activités.
{% else %}
L'inscription aux activités aura lieu plupart.
{% endif %}
</p>
{% else %}
<p> Les inscriptions ne sont pas ouvertes. </p>
{% endif %}
<h2>Comment payer ?</h2>
De préférence par l'associations qui gèrent les Interludes dans votre ENS (Bureau des Loisirs, Bul...). Sinon par espèce, chèque, carte sur place.
<h2>Comment proposer une activité&nbsp;?</h2>
{% if settings.activity_submission_open %}
<p>Vous pouver proposer une activité en remplissant <a href="{% url 'activity_submission' %}">ce formulaire</a>.</p>
<p>Il vous faudra être connecté et renseigner, le titre, une description, le nombre de places, la durée, les horaires possibles/idéaux, et tout autre besoin particulier...</p>
{% else %}
<p>L'appel a activités est fermé pour le moment.
Contactez nous en cas de besoin urgent ou d'idée trop géniale pour être délaissée.</p>
{% endif %}
<h2>Quelles seront les conditions pour dormir/manger&nbsp;?</h2>
<p> Nous proposerons un logement indéterminé, pour celleux qui le souhaitent</p>
<p> Les repas seront préparés et servis sur place.</p>
<h2>Comment se rendre à l'événement&nbsp;?</h2>
<p>Les Interludes se déroule à l'ENS Paris-Saclay : 4 avenue des Sciences, 91190 Gif-sur-Yvette. L'accueil se fait par l'entrée principale.</p>
<div>
<p class="centered">
<iframe width="750" height="400"
frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="https://www.openstreetmap.org/export/embed.html?bbox=2.1628072857856755%2C48.71179934847555%2C2.1672758460044865%2C48.71333201299027&amp;layer=mapnik" style="border: 1px solid black"></iframe><br/>
<small><a href="https://www.openstreetmap.org/#map=19/48.71257/2.16504">View Larger Map</a></small>
</p>
</div>
<div id="public-transport-info">
<div id="transport-tcl-bus-1">
Bus 9
</div>
<div id="transport-tcl-bus-2">
Bus 91.06
</div>
<div id="transport-tcl-bus-3">
Bus 91.10
</div>
<span id="transport-tcl-stop">Arrêt : Moulon</span>
</div>
<h2>Conditions pour dormir/manger</h2>
<p>Une réponse</p>
<h2>Comment sont réparties les activités&nbsp;?</h2>
<p>
La répartition est faite par un algorithme puis vérifiée à la main.
Dans la mesure du possible, l'algorithme essaie d'attribue au moins une activité par personne. Par conséquent, si vous ne mettez qu'une seule activité, vous avez plus de chance de l'avoir.
</p>
<p>
Les activités qui n'ont pas de limite de place (et toutes les activités avec moins de demande que de places) ne comptent pas pour ce système, donc vous pouvez les mettre et vous ne serez pas pénalisés.
</p>
<p>
Vous ne pourrez pas avoir deux activités qui se déroulent en même temps. Si l'une vous est attribué l'autre souhait sera ignoré.
</p>
<p>On n'a pas trouvé le code des années précédentes, mais je suspecte fortement que ce soit un algo similaire en départageant les égalités aléatoirement plutôt qu'au shotgun.</p>
<p>Plus précisément : l'algorithme se base sur le problème hôpital-résident&nbsp;:</p>
<ol>
<li>Il commence par essayer d'attribuer une activité à chaque participant.es au mieux possible, en utilisant la librairie matching de python. Les égalités sont départagées aléatoirement. Plus un choix est haut dans votre liste de souhait, plus vous avez de chance de vous le voir attribuer. Si vous n'avez qu'un seul choix, vous avez plus de chance de vous le voir attribué. (les participant.es avec un seul choix sont automatique placé.es avant ceux qui en ont plusieurs)</li>
<li>Toutes les activités attribuées sont supprimées, ainsi que les voeux résolus des joueurs.</li>
<li>Tant qu'il reste des place dans des activités et des participant.es qui veulent y participer, on recommence à l'étape 1.</li>
</ol>
<p>Le code est sur <a href="https://github.com/Imakoala/InterludesMatchings">github</a>, il ne marche pas encore parfaitement, et on risque de devoir bidouiller à la main en plus pour résoudre tous les cas particuliers (conflits d'horaires, activité présente plusieurs fois...).
<h2>Proposer une activité ?</h2>
<p>Une réponse</p>
{% endblock %}
\ No newline at end of file
{% if settings.contact_email_reversed %}
<h2>J'ai encore une question, je fais quoi ?</h2>
<p> Hésite pas à nous passer un mail à <span class="antispam">{{ settings.contact_email_reversed }}</span> pour nous poser tes questions !</p>
{% endif %}
{% endblock %}
......@@ -3,17 +3,80 @@
{% block nav_home %}current{% endblock %}
{% block "content" %}
<h2>Présentation</h2>
{% if settings.discord_link %}
<ul class="messagelist"><li class="info">
Rejoins notre <a href="{{ settings.discord_link }}">serveur discord</a> pour participer à l'événement.
</li></ul>
{% endif %}
<p>
Les interludes, ou interENS ludiques, regroupent annuellement
les étudiants des quatres ENS de France autour d'activités ludiques.
les étudiants des quatre ENS de France autour d'activités ludiques.
Jeux de plateau, jeux de rôles, jeux vidéos, murders et autres sont
à l'honneur durant ce week-end de trois jours.
</p>
<p>
Cette année, c'est au tour de l'ENS Ulm d'organiser les interludes.
L'événement a habituellement lieu en février mais à cause du COVID,
il a été retardé et est prévu le week-end du vendredi 9 au dimanche 11
avril 2021.
Cette année, c'est au tour de l'{{ settings.hosting_school }} d'organiser les interludes.
Elles auront lieu
{% if settings.date_start %}{% if settings.date_end %}
le week-end du <strong>{{ settings.date_start.day }}-{{ settings.date_end }}</strong>.
{% else %}
le week-end du <strong>{{ settings.date_start }}</strong>.
{% endif %}
{% else %}
à une date non-fixée.
{% endif %}
</p>
<h2>Inscriptions</h2>
<h3>Inscription à l'événement</h3>
<p>
L'inscription à l'événement, aux repas, à l'hebergement et aux activités se fait dans <a href="{% url 'inscription'%}">l'onglet inscription</a>
</p>
</p>
{% if settings.inscriptions_start and settings.inscriptions_end %}
<p>Les inscriptions aux activités seront ouvertes
du <strong>{{ settings.inscriptions_start|date:"l d F Y à H:i" }}</strong>
au <strong>{{ settings.inscriptions_end|date:"l d F Y à H:i" }}</strong>.
</p>
{% elif settings.inscriptions_start %}
<p>Les inscriptions aux activités ouvrirons le <strong>{{ settings.inscriptions_start|date:"l d F Y à H:i" }}</strong>.</p>
{% elif settings.inscriptions_end %}
<p>Les inscriptions fermerons le <strong>{{ settings.inscriptions_end|date:"l d F Y à H:i" }}</strong>.</p>
{% endif %}
<h2>Tarifs</h2>
<p>
Les tarifs sont différenciés entre salarié·es et non-salarié·es.
<ul>
<li><strong>Participation à l'événement :</strong> 6€/4€</li>
<li><strong>Repas (du vendredi soir au dimanche midi) :</strong> 3€/2€ par repas</li>
<li><strong>Repas du dimanche soir (à emporter) :</strong> 2€</li>
<li><strong>Logement :</strong> gratuit (chez les Saclaysien⋅nes)</li>
</ul>
</p>
<h2>Menu des repas</h2>
<p>
Cette année, le menu sera entièrement végétarien. Il sera annoncé bientôt.
<ul>
<li><strong>Vendredi soir :</strong> Pâtes forestières & crumble aux pommes</li>
<li><strong>Samedi matin :</strong>Petit dej'</li>
<li><strong>Samedi midi :</strong>Chili sin carne (avec des pâtes) & crème dessert</li>
<li><strong>Samedi soir :</strong>Gratin patate poireau & charlotte</li>
<li><strong>Dimanche matin :</strong>Petit dej'</li>
<li><strong>Dimanche midi :</strong>Wraps & cookie</li>
<li><strong>Dimanche soir (à emporter):</strong>Wraps & fruit (ou cookie)</li>
</ul>
<h2>Liens divers</h2>
<ul>
<li>Le code source de ce site est sur <a href="https://gitlab.crans.org/mediatek/site-kwei">gitlab</a>.</li>
<li>Un historique des interludes avec leurs visuels, site webs et photos est sur le <a
href="https://wiki.crans.org/VieBdl/InterLudes">wiki Crans de Paris-Saclay</a>.</li>
</ul>
{% endblock %}
......@@ -3,9 +3,26 @@
{% block nav_inscription %}current{% endblock %}
{% block "content" %}
<h2>Inscriptions</h2>
<p>
Les inscriptions ne sont pas encores ouvertes.
Nous communiquerons pas mail via les BDE des différentes écoles pour leur ouverture.
</p>
<h2>Inscriptions à l'événement</h2>
<p> L'inscription est fermée </p>
<h2>Inscriptions aux activités</h2>
{% if settings.inscriptions_not_open_yet %}
<p>Les inscriptions aux activités ne sont pas encores ouvertes.</p>
<p>Leur ouverture est prévue le <strong>{{ settings.inscriptions_start|date:"l d F Y à H:i" }}</strong>.</p>
<p>Nous communiquerons par mail via les BDE des différentes écoles pour leur ouverture.</p>
{% elif settings.inscriptions_have_closed %}
<p>Les inscriptions aux activités sont fermées.</p>
<p>
Les inscriptions cette année sont facultatives,
tu peux quand même rejoindre le {% if settings.discord_link %}<a href="{{ settings.discord_link }}">serveur discord</a>{% else %}serveur discord{% endif %} et participer aux jeux libres et
aux activités qui ne nécessitent pas d'inscription.
</p>
{% if settings.contact_email %}
<p>Pour tout problème, contacter&nbsp;:<br><span class="antispam">{{ settings.contact_email_reversed }}</span></p>
{% endif %}
{% else %}
<p>Les inscriptions aux activités ne sont pas encores ouvertes ou ont été fermées.</p>
<p>Nous communiquerons par mail via les BDE des différentes écoles pour leur ouverture.</p>
{% endif %}
{% endblock %}
{% extends "base.html" %}
{% load static %}
{% block nav_inscription %}current{% endblock %}
{% block "content" %}
<h2>Inscriptions</h2>
{% if settings.discord_link %}
<ul class="messagelist">
<li class="info">Rejoignez aussi <a href="{{ settings.discord_link }}">le serveur discord</a>,
C'est là que s'organiseront la plupart des activités.</li>
</ul>
{% endif %}
<form id="main_form" method="post" action="{% url 'inscription' %}">
{% csrf_token %}
Cette année, l'événement étant en distanciel, il est gratuit.
<p>{{ form.school.label_tag }} {{ form.school }}</p>
<h3>Choix d'activités</h3>
<p>Saissisez les activités auquelles vous voulez vous inscrire, par ordre de préférence.
Vous trouverez une description des activités sur <a href="{% url 'activites' %}">cette page</a>.
</p>
<p>
Vous pouvez revenir modifier votre choix jusqu'à la fermeture des
inscriptions{% if settings.inscriptions_end %} (le {{ settings.inscriptions_end|date:"l d F Y à H:i" }}){% endif %}.
</p>
<p>Si vous vous inscrivez à une activité qui nécessite préparation, nous communiquerons
votre email aux orgas pour qu'iels puissent vous contacter.
</p>
{% if formset.non_form_errors %}
{{ formset.non_form_errors }}
{% endif %}
{{ formset.management_data }}
{{ formset.management_form }}
{% for form in formset %}
<div class="activity-form flex">
{{ form.as_p }}
<button class="button delete-activity" style="align-self: center; flex-grow: 0;">Supprimer</button>
</div>
{% endfor %}
<button class="button" id="add-activity">Ajouter une activité</button>
<div class="flex">
<input type="submit" value="Valider">
<a class="button" href="{% url 'profile' %}">Annuler</a>
</div>
</form>
<script>
const button_add_activity = document.querySelector("#add-activity");
const button_submit_form = document.querySelector('[type="submit"]');
const activity_form = document.getElementsByClassName("activity-form");
const main_form = document.querySelector("#main_form");
const total_forms = document.querySelector("#id_form-TOTAL_FORMS");
const form_regex = /form-(\d*)-/g;
var form_count = activity_form.length - 1;
function add_new_form(event) {
// adds a new activity form when clicking on the + button
event.preventDefault();
// clone the first form and replaces it's id
const new_form = activity_form[0].cloneNode(true);
form_count++;
new_form.innerHTML = new_form.innerHTML.replace(form_regex, `form-${form_count}-`);
// add it and increment form total
main_form.insertBefore(new_form, button_add_activity);
new_form.querySelector("select").value = "";
total_forms.setAttribute("value", `${form_count+1}`);
}
button_add_activity.addEventListener("click", add_new_form);
function delete_form(event) {
if (!event.target.classList.contains("delete-activity")) return;
event.preventDefault();
if (form_count == 0) {
// don't delete the first element
activity_form[0].querySelector("select").value = "";
return;
}
event.target.parentElement.remove();
form_count--;
total_forms.setAttribute("value", `${form_count+1}`);
// update form numbers
let count = 0;
for (const form of activity_form) {
// the replace changes the field value
// so we save and restore it
const select = form.querySelector("select");
const value = select.value;
form.innerHTML = form.innerHTML.replace(form_regex, `form-${count++}-`);
form.querySelector("select").value = value;
}
}
main_form.addEventListener("click", delete_form);
</script>
{% endblock %}
......@@ -3,19 +3,60 @@
{% block nav_inscription %}current{% endblock %}
{% block "head" %}
<!--<script src="{% static 'js/formset.js' %}"></script>-->
{% endblock %}
{% block "content" %}
<h2>Inscriptions</h2>
<form id="main_form" method="post" action="{% url 'inscription' %}">
{% csrf_token %}
{{ form.as_p }}
{% csrf_token %}
<h2>Inscription à l'événement</h2>
<p>L'inscription à l'événement,à l'hébergement
et aux repas se fait sur cette page.</p>
<h3>École</h3>
<p>{{ form.school.label_tag }} {{ form.school }}</p>
<h3>Repas</h3>
<p>Vous pouvez vous inscrire aux repas ci-dessous :</p>
<ul>
<li>Vendredi soir {{ form.meal_friday_evening }}</li>
<li>Petit dej' du samedi {{ form.meal_saturday_morning }}</li>
<li>Samedi midi {{ form.meal_saturday_midday }}</li>
<li>Samedi soir {{ form.meal_saturday_evening }}</li>
<li>Dimanche matin {{ form.meal_sunday_morning }}</li>
<li>Dimanche midi {{ form.meal_sunday_midday }}</li>
<li>Dimanche soir (à emporter) {{ form.meal_sunday_evening }}</li>
</ul>
<p>Les menus sont disponibles sur la <a href="{% url 'home' %}">page d'accueil</a>
<h3>Hébergement</h3>
<p>Pour l'hébergement, nous proposons le logement chez les Saclaysien⋅nes (comme aux InterQ). Si vous souhaitez un hébergement, cochez la case suivante : {{ form.sleeps }} </p>
<p>L'idée est de proposer aux normalien⋅nes de Saclay de loger celleux des autres écoles. Si vous avez besoin d'un hébergement vous pouvez compléter <a href="https://framaforms.org/logement-interludes-2023-extes-1668450149">ce questionnaire</a>. Si vous voulez loger quelqu'un <a href="https://framaforms.org/logement-interludes-2023-cote-hebergement-1668438253">c'est ici</a>. Merci à ceux qui veulent bien accueillir !</p>
<h3>Tarif</h3>
<p>Le tarif est différent selon si vous percevez un salaire ou non. Êtes-vous payé⋅e : {{ form.paid }}</p>
<h2>Inscription aux activités</h2>
{% if formset.non_form_errors %}
{{ formset.non_form_errors }}
{% endif %}
<h3>Choix d'activités</h3>
{{ formset.management_data }}
{{ formset.management_form }}
{% if settings.activity_inscriptions_open %}
<p>Vous pouvez vous inscrire à certaines activités sur cette page. La
plupart des activités ne demandent pas d'inscription et seront en libre
accès durant tout l'événement, mais certaines demandent une inscription
à l'avance.</p>
<h3>Choix d'activités</h3>
<p>Saissisez les activités auquelles vous voulez vous inscrire, <strong>par ordre de préférence</strong>.
Vous trouverez une description des activités sur <a href="{% url 'activites' %}">cette page</a>.</p>
<p>Si vous vous inscrivez à une activité qui nécessite préparation, nous communiquerons
votre email aux orgas pour qu'iels puissent vous contacter.</p>
{% for form in formset %}
<div class="activity-form flex">
{{ form.as_p }}
......@@ -23,10 +64,33 @@
</div>
{% endfor %}
<button class="button" id="add-activity">Ajouter une activité</button>
{% else %}
<p>Vous pourrez vous inscrire à certaines activités sur cette page. La
plupart des activités ne demandent pas d'inscription et seront en libre
accès durant tout l'événement, mais certaines demandent une inscription
à l'avance.{% if settings.inscriptions_end %} Les inscriptions aux activités ouvrent le {{ settings.inscriptions_start|date:"l d F Y à H:i" }}){% endif %}. </p>
{% endif %}
<h3>Expérience</h3>
<p>Pour vous attribuer au mieux les activités, nous aimerions connaître votre exprérieurnce en murder (jeux de rôles grandeurs nature). Si vous avez perdu le compte, 42 conviendra très bien ;) </p>
Nombre de murder déjà jouées : {{ form.nb_murder }}
<h2>Commentaire</h2>
<p>Pour préciser toutes les informations qui vous semblent utiles comme les allergies alimentaires.</p>
{{ form.comment }}
<p>
Vous pouvez revenir modifier vos choix jusqu'à la fermeture des
inscriptions{% if settings.inscriptions_end %} (le {{ settings.inscriptions_end|date:"l d F Y à H:i" }}){% endif %}.
</p>
<div class="flex">
<input type="submit" value="Valider">
<a class="button" href="{% url 'accounts:profile' %}">Annuler</a>
<a class="button" href="{% url 'profile' %}">Annuler</a>
</div>
</form>
......@@ -50,6 +114,7 @@ function add_new_form(event) {
new_form.innerHTML = new_form.innerHTML.replace(form_regex, `form-${form_count}-`);
// add it and increment form total
main_form.insertBefore(new_form, button_add_activity);
new_form.querySelector("select").value = "";
total_forms.setAttribute("value", `${form_count+1}`);
}
......@@ -58,24 +123,26 @@ button_add_activity.addEventListener("click", add_new_form);
function delete_form(event) {
if (!event.target.classList.contains("delete-activity")) return;
event.preventDefault();
if (form_count == 0) return;
if (form_count == 0) {
// don't delete the first element
activity_form[0].querySelector("select").value = "";
return;
}
event.target.parentElement.remove();
form_count--;
total_forms.setAttribute("value", `${form_count+1}`);
// update form numbers
let count = 0;
for (const form of activity_form) {
console.log(form.children.item(0).find("option:selected").val())
// the replace changes the field value
// so we save and restore it
const select = form.querySelector("select");
const value = select.value;
form.innerHTML = form.innerHTML.replace(form_regex, `form-${count++}-`);
form.querySelector("select").value = value;
}
}
function change(event) {
console.log(event.target.value)
}
main_form.addEventListener("click", delete_form);
main_form.addEventListener("change", change)
</script>
{% endblock %}
......@@ -4,7 +4,10 @@
{% block "content" %}
<h2>Inscriptions</h2>
<p>Vous devez être connecté pour pouvoir vous inscrire à l'événement.</p>
<p>Aller à la page de <a href="{% url 'accounts:login' %}">connexion</a> pour vous connectez
<p>Vous devez être connecté pour pouvoir vous inscrire</p>
<p>Aller à la page de <a href="{% url 'accounts:login' %}">connexion</a> pour vous connecter
ou à celle de <a href="{% url 'accounts:create' %}">création de compte</a> si vous n'avez pas de compte.</p>
{% if settings.inscriptions_end %}
<p>Les inscriptions seront ouvertes jusqu'au {{ settings.inscriptions_end|date:"l d F Y à H:i" }})</p>
{% endif %}
{% endblock %}
{% extends "base.html" %}
{% block nav_profile %}current{% endblock %}
{% block "content" %}
<h2>Mon compte</h2>
<p>Connecté en tant que {{ user.first_name }} {{ user.last_name }} ({{ user.email }})</p>
{% if user.is_superuser %}
<ul class="messagelist">
<li class="info">
Vous avez les droits d'administrateurs.
<br>Aller à la <a href="{% url 'admin_pages:index' %}">page d'administration du site</a>
{% if user.is_staff %}
<br>Aller à la <a href="{% url 'admin:index' %}">page d'administration de django</a>
(N'y modifier rien sy vous n'êtes pas sûrs de vous)
{% endif %}
</li>
</ul>{% endif %}
{% if user.profile.is_registered %}
<strong>Mon inscription&nbsp;:</strong>
{% if settings.inscriptions_open and settings.inscriptions_end %}
modifiable jusqu'au {{ settings.inscriptions_end|date:"l d F Y à H:i" }}
{% endif %}
<ul>
<li>Tarif personnalisé : {{ user.profile.cost }}€</li>
<li>{% if user.profile.sleeps %}Inscrit pour dormir sur place{% else %}Non inscrit pour dormir sur place{% endif %}</li>
{% comment "pas de tasse" %}<li>{% if user.profile.mug %}Commandse une tasse{% else %}Ne commande pas de tasse{% endif %}</li>{% endcomment%}
{% if user.profile.nb_meals != 0 %}
<li>Inscrit à {{ user.profile.nb_meals }} repas :</li>
<ul>
{% if user.profile.meal_friday_evening == True %}<li>Vendredi soir</li>{% endif %}
{% if user.profile.meal_saturday_morning == True %}<li>Petit dej' du samedi</li>{% endif %}
{% if user.profile.meal_saturday_midday == True %}<li>Samedi midi</li>{% endif %}
{% if user.profile.meal_saturday_evening == True %}<li>Samedi soir</li>{% endif %}
{% if user.profile.meal_sunday_morning == True %}<li>Petit dej' du dimanche</li>{% endif %}
{% if user.profile.meal_sunday_midday == True %}<li>Dimanche midi</li>{% endif %}
{% if user.profile.meal_sunday_evening == True %}<li>Dimanche soir (à emporter)</li>{% endif %}
</ul>
{% else %}
<li>Inscrit à aucun repas</li>
{% endif %}
{% if settings.activities_allocated %}
{% if my_choices %}
<li>Inscrit à {{ my_choices|length }} activités&nbsp;:
<ul>
{% for choice in my_choices %}
<li><a href="{% url 'activites' %}#{{ choice.slot.activity.slug }}">{{ choice.slot }}</a>
{% if choice.slot.on_planning %}
(le {{ choice.slot.start|date:"l à H:i" }}<!-- en {{ choice.slot.room }} -->)
{% endif %}
</li>
{% endfor %}
</ul>
</li>
{% else %}
<li>Inscrit à aucune activité</li>
{% endif %}
{% else %}
{% if my_choices %}
<li>{{ my_choices|length }} activités souhaitées&nbsp;:
<ol>
{% for choice in my_choices %}
<li><a href="{% url 'activites' %}#{{ choice.slot.activity.slug }}">{{ choice.slot }}</a>
{% if choice.slot.on_planning %}
(le {{ choice.slot.start|date:"l à H:i" }}<!-- en {{ choice.slot.room }} -->)
{% endif %}
</li>
{% endfor %}
</ol>
</li>
{% else %}
<li>Aucune activité souhaitée</li>
{% endif %}
{% endif %}
</ul>
{% else %}
<strong>Vous n'avez pas encore renseigné vos choix d'activités.</strong>
{% if not settings.inscriptions_open %}
{% if settings.inscriptions_not_open_yet %}
<p>Les inscriptions aux activités ne sont pas encores ouvertes. Elles ouvrirons le <strong>{{ settings.inscriptions_start|date:"l d F Y à H:i" }}</strong>.</p>
{% elif settings.inscriptions_have_closed %}
<p>Les inscriptions aux activités sont fermées.</p>
{% else %}
<p>Les inscriptions aux activités ne sont pas encores ouvertes ou ont été fermées.</p>
{% endif %}
{% elif settings.inscriptions_end %}
<p>les inscriptions aux activités sont ouvertes jusqu'au {{ settings.inscriptions_end|date:"l d F Y à H:i" }}).</p>
{% endif %}
<br><br>
{% endif %}
<div class="flex wrap">
{% if user.profile.is_registered %}
{% if settings.inscriptions_open %}
<a class="button" href="{% url 'desinscription' %}">Me désinscrire</a>
<a class="button" href="{% url 'inscription' %}">Modifier mon inscription</a>
{% else %}
<script type="text/javascript">
function clicked() {
if (confirm(
'Les inscriptions étant fermées, vous ne pourrez pas vous réinscrire.\nVoulez vous vraiment vous désinscrire?'
))
window.location = "{% url 'desinscription' %}";
}
</script>
<button class="button" onclick="clicked();">Me désinscrire</button>
{% endif %}
{% elif settings.inscriptions_open %}
<a class="button" href="{% url 'inscription' %}">S'inscrire</a>
{% endif %}
<a class="button" href="{% url 'accounts:update' %}">Modifier mes informations</a>
<a class="button" href="{% url 'accounts:logout' %}">Déconnexion</a>
</div>
{% endblock %}
from django.conf import settings
from django.conf.urls.static import static
from django.contrib.sitemaps.views import sitemap
from django.views.generic import RedirectView
from django.urls import path, include
......@@ -7,14 +9,21 @@ from home import views
sitemaps = {"static_pages": views.StaticViewSitemap}
urlpatterns = [
path('', views.HomeView.as_view(), {"template": "home.html"}, name = 'home'),
path('', views.HomeView.as_view(), name = 'home'),
path('inscription/', views.RegisterView.as_view(), name = 'inscription'),
path('activites/', views.ActivityView.as_view(), {"template":"activites.html"}, name = 'activites'),
path('faq/', views.FAQView.as_view(), {"template":"faq.html"}, name = 'FAQ'),
path('desinscription/', views.UnregisterView.as_view(), name="desinscription"),
path('activites/', views.ActivityView.as_view(), name = 'activites'),
path('activites/nouvelle/', views.ActivitySubmissionView.as_view(), name = 'activity_submission'),
path('faq/', views.FAQView.as_view(), name = 'FAQ'),
path("profil/", views.ProfileView.as_view(), name="profile"),
path('favicon.ico', RedirectView.as_view(url='/static/imgs/favicon.ico')),
path(
'sitemap.xml', sitemap, {'sitemaps': sitemaps},
name='django.contrib.sitemaps.views.sitemap'
),
path('accounts/', include("accounts.urls")),
path('admin_pages/', include(('admin_pages.urls', 'admin_pages'), namespace="admin_pages")),
path('comptes/', include("accounts.urls")),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
from datetime import timedelta
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.sitemaps import Sitemap
from django.forms import modelformset_factory
from django.forms import formset_factory
from django.shortcuts import redirect, render
from django.urls import reverse
from django.views.generic import UpdateView, TemplateView, View
from django.urls import reverse, reverse_lazy
from django.views.generic import FormView, RedirectView, TemplateView, View
from home.models import ActivityList, InterludesActivity
from home.forms import ActivityForm, InscriptionForm
from home import models
from home.forms import ActivityForm, ActivitySubmissionForm, BaseActivityFormSet, InscriptionForm
from site_settings.models import SiteSettings
# ==============================
# Site static pages
# ==============================
class HomeView(TemplateView):
"""Vue pour la page d'acceuil"""
template_name = "home.html"
def get_planning_context():
"""Returns the context dict needed to display the planning"""
settings = SiteSettings.load()
context = dict()
context['planning'] = models.SlotModel.objects.filter(on_planning=True).order_by("title")
if settings.date_start is not None:
context['friday'] = settings.date_start.day
context['saturday'] = (settings.date_start + timedelta(days=1)).day
context['sunday'] = (settings.date_start + timedelta(days=2)).day
else:
context['friday'] = 1
context['saturday'] = 2
context['sunday'] = 3
return context
class ActivityView(TemplateView):
"""Vue pour la liste des activités"""
......@@ -23,7 +44,8 @@ class ActivityView(TemplateView):
def get_context_data(self, **kwargs):
"""ajoute la liste des activités au contexte"""
context = super(ActivityView, self).get_context_data(**kwargs)
context['activities'] = InterludesActivity.objects.filter(display=True).order_by("title")
context['activities'] = models.ActivityModel.objects.filter(display=True).order_by("title")
context.update(get_planning_context())
return context
......@@ -32,6 +54,33 @@ class FAQView(TemplateView):
template_name = "faq.html"
# ==============================
# Profile and registration
# ==============================
class ProfileView(LoginRequiredMixin, TemplateView):
"""Vue des actions de gestion de son profil"""
template_name = "profile.html"
redirect_field_name = "next"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
settings = SiteSettings.load()
if settings.activities_allocated:
my_choices = models.ActivityChoicesModel.objects.filter(
participant=self.request.user.profile,
accepted=True
)
else:
my_choices = models.ActivityChoicesModel.objects.filter(
participant=self.request.user.profile
)
context["my_choices"] = my_choices
return context
class RegisterClosed(TemplateView):
"""Vue pour quand les inscriptions ne sont pas ouvertes"""
template_name = "inscription/closed.html"
......@@ -41,35 +90,63 @@ class RegisterSignIn(TemplateView):
l'utilisateur n'est pas connecté"""
template_name = "inscription/signin.html"
class RegisterUpdateView(LoginRequiredMixin, UpdateView):
class RegisterUpdateView(LoginRequiredMixin, TemplateView):
"""Vue pour s'inscrire et modifier son inscription"""
template_name = "inscription/form.html"
form_class = InscriptionForm
formset = modelformset_factory(ActivityList, form=ActivityForm, extra=3)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["formset"] = self.formset(queryset=ActivityList.objects.none())
return context
def get_object(self):
return self.request.user.profile
def get_success_url(self):
return reverse("accounts:profile")
def form_valid(self, form):
messages.success(self.request, "Votre inscription a été enregistrée")
return super().form_valid(form)
formset_class = formset_factory(form=ActivityForm, extra=3, formset=BaseActivityFormSet)
success_url = reverse_lazy("profile")
@staticmethod
def get_slots(participant):
activities = models.ActivityChoicesModel.objects.filter(participant=participant).order_by("priority")
return [{"slot": act.slot} for act in activities]
@staticmethod
def set_activities(participant, formset):
# delete old activites
models.ActivityChoicesModel.objects.filter(participant=participant).delete()
priority = 0
for form in formset:
data = form.cleaned_data
if data:
slot = data["slot"]
models.ActivityChoicesModel(
priority=priority, participant=participant, slot=slot
).save()
priority += 1
def get(self, request, *args, **kwargs):
participant = request.user.profile
slots = self.get_slots(participant)
form = self.form_class(instance=participant)
formset = self.formset_class(initial=slots)
context = {"form": form, "formset": formset}
return render(request, self.template_name, context)
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
formset = self.formset(request.POST)
if formset.is_valid():
print("\n\n{} {}\n\n".format(len(formset), formset))
else:
print("\n\nInvalid\n\n")
return super().post(request, *args, **kwargs)
settings = SiteSettings.load()
form = self.form_class(request.POST, instance=request.user.profile)
if settings.activity_inscriptions_open : # meal + sleep + activities open
formset = self.formset_class(request.POST)
if not (form.is_valid() and formset.is_valid()):
context = {"form": form, "formset": formset}
return render(request, self.template_name, context)
self.set_activities(request.user.profile, formset)
else: # only meal and sleep open
if not form.is_valid():
participant = request.user.profile
slots = self.get_slots(participant)
formset = self.formset_class(initial=slots)
context = {"form": form, "formset": formset}
return render(request, self.template_name, context)
form.save()
messages.success(request, "Votre inscription a bien été enregistrée")
return redirect(self.success_url, permanent=False)
class RegisterView(View):
"""Vue pour l'inscription
......@@ -83,6 +160,73 @@ class RegisterView(View):
return RegisterUpdateView.as_view()(request)
class UnregisterView(LoginRequiredMixin, RedirectView):
pattern_name = "profile"
def get_redirect_url(self, *args, **kwargs):
participant = self.request.user.profile
participant.is_registered = False
participant.save()
messages.success(self.request, "Vous avez été désinscrit")
return reverse(self.pattern_name)
# ==============================
# Activity Submission Form
# ==============================
class ActivitySubmissionView(LoginRequiredMixin, FormView):
"""Vue pour proposer une activité"""
template_name = "activity_submission.html"
form_class = ActivitySubmissionForm
success_url = reverse_lazy("profile")
@staticmethod
def submission_check():
"""Vérifie si le formulaire est ouvert ou non"""
settings = SiteSettings.load()
return settings.activity_submission_open
def get_initial(self):
init = super().get_initial()
user = self.request.user
init.update({
"host_name": "{} {}".format(user.first_name, user.last_name),
"host_email": user.email,
})
return init
def not_open(self, request):
"""Appelé quand le formulaire est désactivé"""
messages.error(request, "La soumission d'activité est desactivée")
return redirect(self.success_url, permanent=False)
def get(self, request, *args, **kwargs):
if not self.submission_check():
return self.not_open(request)
return super().get(self, request, *args, **kwargs)
def post(self, request, *args, **kwargs):
if not self.submission_check():
return self.not_open(request)
form = self.form_class(request.POST)
if not form.is_valid():
context = self.get_context_data()
context["form"] = form
return render(request, self.template_name, context)
form.save()
messages.success(request, "Votre activité a bien été enregistrée. Elle sera affichée sur le site après relecture par les admins.")
return redirect(self.success_url, permanent=False)
# ==============================
# Sitemap
# ==============================
class StaticViewSitemap(Sitemap):
"""Vue générant la sitemap.xml du site"""
changefreq = 'monthly'
......
from django.contrib.auth import get_user_model
from cas_server.auth import AuthUser, DjangoAuthUser
class InterLudesAuthUser(DjangoAuthUser): # pragma: no cover
"""
Overrides DjangoAuthUser constructor
"""
def __init__(self, username):
User = get_user_model()
try:
self.user = User.objects.get(email=username)
except User.DoesNotExist:
pass
super(DjangoAuthUser, self).__init__(username)
\ No newline at end of file
# Secrets that must be changed in production
SECRET_KEY = "i*4$=*fa(644(*!9m2)0-*&sows2uz$b^brb(=)elfn3+y6#1n"
ADMINS = [("superuser", "superuser@admin.fr"),]
DB_NAME = "db.sqlite3"
SERVER_EMAIL = "root@localhost"
DEFAULT_FROM_EMAIL = "webmaster@localhost"
EMAIL_HOST = "localhost"
EMAIL_PORT = 587
EMAIL_HOST_USER = None
EMAIL_HOST_PASSWORD = None
This diff is collapsed.
This diff is collapsed.