From eeb791c46003665a1feb8612f3e3380cccc7f9c5 Mon Sep 17 00:00:00 2001 From: tleb Date: Fri, 18 Oct 2019 01:28:59 +0200 Subject: [PATCH 01/14] Initial autofill on UV --- api/urls.py | 1 + api/views/api.py | 98 ++++++++++++++++++++- pedagogy/templates/pedagogy/uv_create.jinja | 68 ++++++++++++++ pedagogy/views.py | 2 +- 4 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 pedagogy/templates/pedagogy/uv_create.jinja diff --git a/api/urls.py b/api/urls.py index 9f8884bd..c8bdc2b2 100644 --- a/api/urls.py +++ b/api/urls.py @@ -53,4 +53,5 @@ urlpatterns = [ re_path(r"^login/", include("rest_framework.urls", namespace="rest_framework")), re_path(r"^markdown$", RenderMarkdown, name="api_markdown"), re_path(r"^mailings$", FetchMailingLists, name="mailings_fetch"), + re_path(r"^uv$", uv_endpoint, name="uv_endpoint"), ] diff --git a/api/views/api.py b/api/views/api.py index efd9ec42..47967f2b 100644 --- a/api/views/api.py +++ b/api/views/api.py @@ -24,10 +24,15 @@ from rest_framework.response import Response from rest_framework.decorators import api_view, renderer_classes -from rest_framework.renderers import StaticHTMLRenderer +from rest_framework.renderers import StaticHTMLRenderer, JSONRenderer from rest_framework.views import APIView +from django.core.exceptions import PermissionDenied +from rest_framework import serializers +import urllib.request +import json from core.templatetags.renderer import markdown +from pedagogy.views import CanCreateUVFunctionMixin @api_view(["POST"]) @@ -41,3 +46,94 @@ def RenderMarkdown(request): except: data = "Error" return Response(data) + + +@api_view(["GET"]) +@renderer_classes((JSONRenderer,)) +def uv_endpoint(request): + if not request.user.is_authenticated or not CanCreateUVFunctionMixin.can_create_uv( + request.user + ): + raise PermissionDenied + + lang = "fr" + + params = request.query_params + if "year" not in params or "code" not in params: + raise serializers.ValidationError("Missing query parameter") + + uvs_url = "https://extranet1.utbm.fr/gpedago/api/guide/uvs/{lang}/{year}" + response = urllib.request.urlopen(uvs_url.format(lang=lang, year=params["year"])) + + uvs = json.loads(response.read().decode("utf-8")) + + try: + found = next(uv for uv in uvs if uv["code"] == params["code"]) + except StopIteration: + # shouldn't be 404, rather something like 204 + return Response(status=404) + + uv_url = "https://extranet1.utbm.fr/gpedago/api/guide/uv/{lang}/{year}/{code}/{formation}" + response = urllib.request.urlopen( + uv_url.format( + lang=lang, + year=params["year"], + code=params["code"], + formation=found["codeFormation"], + ) + ) + + uv = json.loads(response.read().decode("utf-8")) + + res = {} + + res["credit_type"] = found["codeCategorie"] + + semesters = { + (True, True): "AUTUMN_AND_SPRING", + (True, False): "AUTOMN", + (False, True): "SPRING", + } + res["semester"] = semesters.get( + (found["ouvertAutomne"], found["ouvertPrintemps"]), "CLOSED" + ) + + langs = {"es": "SP", "en": "EN", "de": "DE"} + res["language"] = langs.get(uv["codeLangue"], "FR") + + if uv["departement"] == "Pôle Humanités": + res["department"] = "HUMA" + else: + departments = { + "AL": "IMSI", + "AE": "EE", + "GI": "GI", + "GC": "EE", + "GM": "MC", + "TC": "TC", + "GP": "IMSI", + "ED": "EDIM", + "AI": "GI", + "AM": "MC", + } + res["department"] = departments.get(uv["codeFormation"], "NA") + + res["credits"] = uv["creditsEcts"] + + activities = ("CM", "TD", "TP", "THE", "TE") + for activity in activities: + res["hours_{}".format(activity)] = 0 + for activity in uv["activites"]: + if activity["code"] in activities: + res["hours_{}".format(activity["code"])] += activity["nbh"] + + res["manager"] = uv["automne"]["responsable"] + + res["title"] = uv["libelle"] + + res["objectives"] = uv["objectifs"] + res["program"] = uv["programme"] + res["skills"] = uv["acquisitionCompetences"] + res["key_concepts"] = uv["acquisitionNotions"] + + return Response(res) diff --git a/pedagogy/templates/pedagogy/uv_create.jinja b/pedagogy/templates/pedagogy/uv_create.jinja new file mode 100644 index 00000000..a14d43bc --- /dev/null +++ b/pedagogy/templates/pedagogy/uv_create.jinja @@ -0,0 +1,68 @@ +{% extends "core/base.jinja" %} + +{% block title %} +{% trans %}Edit UV{% endtrans %} +{% endblock %} + +{% block content %} +

{% trans %}Edit UV{% endtrans %}

+
+ {% csrf_token %} + {{ form.non_field_errors() }} + + {% for field in form %} + + {% if not field.is_hidden %} +

+ {{ field.errors }} + + {{ field }} + + + {% if field.name == 'code' %} + Fill + {% endif %} +

+ {% endif %} + + + {% endfor %} + + +

+
+{% endblock %} + +{% block script %} +{{ super() }} + + +{% endblock %} diff --git a/pedagogy/views.py b/pedagogy/views.py index fae5b8f0..f3b02d9b 100644 --- a/pedagogy/views.py +++ b/pedagogy/views.py @@ -294,7 +294,7 @@ class UVCreateView(CanCreateMixin, CreateView): model = UV form_class = UVForm - template_name = "core/edit.jinja" + template_name = "pedagogy/uv_create.jinja" def get_form_kwargs(self): kwargs = super(UVCreateView, self).get_form_kwargs() From dbe44a9c1cf8759212c4b43d632d41253b94ee09 Mon Sep 17 00:00:00 2001 From: tleb Date: Fri, 18 Oct 2019 01:45:49 +0200 Subject: [PATCH 02/14] Fix hour count and submit button --- api/views/api.py | 2 +- pedagogy/templates/pedagogy/uv_create.jinja | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/api/views/api.py b/api/views/api.py index 47967f2b..f70517ce 100644 --- a/api/views/api.py +++ b/api/views/api.py @@ -125,7 +125,7 @@ def uv_endpoint(request): res["hours_{}".format(activity)] = 0 for activity in uv["activites"]: if activity["code"] in activities: - res["hours_{}".format(activity["code"])] += activity["nbh"] + res["hours_{}".format(activity["code"])] += activity["nbh"] // 60 res["manager"] = uv["automne"]["responsable"] diff --git a/pedagogy/templates/pedagogy/uv_create.jinja b/pedagogy/templates/pedagogy/uv_create.jinja index a14d43bc..a648799b 100644 --- a/pedagogy/templates/pedagogy/uv_create.jinja +++ b/pedagogy/templates/pedagogy/uv_create.jinja @@ -12,7 +12,11 @@ {% for field in form %} - {% if not field.is_hidden %} + {% if field.is_hidden %} + + {{ field }} + + {% else %}

{{ field.errors }} From bddb88d97fe689134df7bd7ca37e95d8c01631d0 Mon Sep 17 00:00:00 2001 From: tleb Date: Fri, 18 Oct 2019 18:13:53 +0200 Subject: [PATCH 03/14] Comment UV API and fix little bugs --- api/views/__init__.py | 1 + api/views/api.py | 99 +-------- api/views/uv.py | 120 +++++++++++ locale/fr/LC_MESSAGES/django.po | 226 +++++++++++--------- pedagogy/templates/pedagogy/uv_create.jinja | 6 +- 5 files changed, 247 insertions(+), 205 deletions(-) create mode 100644 api/views/uv.py diff --git a/api/views/__init__.py b/api/views/__init__.py index 3d731738..21aacd98 100644 --- a/api/views/__init__.py +++ b/api/views/__init__.py @@ -77,3 +77,4 @@ from .user import * from .club import * from .group import * from .launderette import * +from .uv import * diff --git a/api/views/api.py b/api/views/api.py index f70517ce..82d9942b 100644 --- a/api/views/api.py +++ b/api/views/api.py @@ -24,15 +24,9 @@ from rest_framework.response import Response from rest_framework.decorators import api_view, renderer_classes -from rest_framework.renderers import StaticHTMLRenderer, JSONRenderer -from rest_framework.views import APIView -from django.core.exceptions import PermissionDenied -from rest_framework import serializers -import urllib.request -import json +from rest_framework.renderers import StaticHTMLRenderer from core.templatetags.renderer import markdown -from pedagogy.views import CanCreateUVFunctionMixin @api_view(["POST"]) @@ -46,94 +40,3 @@ def RenderMarkdown(request): except: data = "Error" return Response(data) - - -@api_view(["GET"]) -@renderer_classes((JSONRenderer,)) -def uv_endpoint(request): - if not request.user.is_authenticated or not CanCreateUVFunctionMixin.can_create_uv( - request.user - ): - raise PermissionDenied - - lang = "fr" - - params = request.query_params - if "year" not in params or "code" not in params: - raise serializers.ValidationError("Missing query parameter") - - uvs_url = "https://extranet1.utbm.fr/gpedago/api/guide/uvs/{lang}/{year}" - response = urllib.request.urlopen(uvs_url.format(lang=lang, year=params["year"])) - - uvs = json.loads(response.read().decode("utf-8")) - - try: - found = next(uv for uv in uvs if uv["code"] == params["code"]) - except StopIteration: - # shouldn't be 404, rather something like 204 - return Response(status=404) - - uv_url = "https://extranet1.utbm.fr/gpedago/api/guide/uv/{lang}/{year}/{code}/{formation}" - response = urllib.request.urlopen( - uv_url.format( - lang=lang, - year=params["year"], - code=params["code"], - formation=found["codeFormation"], - ) - ) - - uv = json.loads(response.read().decode("utf-8")) - - res = {} - - res["credit_type"] = found["codeCategorie"] - - semesters = { - (True, True): "AUTUMN_AND_SPRING", - (True, False): "AUTOMN", - (False, True): "SPRING", - } - res["semester"] = semesters.get( - (found["ouvertAutomne"], found["ouvertPrintemps"]), "CLOSED" - ) - - langs = {"es": "SP", "en": "EN", "de": "DE"} - res["language"] = langs.get(uv["codeLangue"], "FR") - - if uv["departement"] == "Pôle Humanités": - res["department"] = "HUMA" - else: - departments = { - "AL": "IMSI", - "AE": "EE", - "GI": "GI", - "GC": "EE", - "GM": "MC", - "TC": "TC", - "GP": "IMSI", - "ED": "EDIM", - "AI": "GI", - "AM": "MC", - } - res["department"] = departments.get(uv["codeFormation"], "NA") - - res["credits"] = uv["creditsEcts"] - - activities = ("CM", "TD", "TP", "THE", "TE") - for activity in activities: - res["hours_{}".format(activity)] = 0 - for activity in uv["activites"]: - if activity["code"] in activities: - res["hours_{}".format(activity["code"])] += activity["nbh"] // 60 - - res["manager"] = uv["automne"]["responsable"] - - res["title"] = uv["libelle"] - - res["objectives"] = uv["objectifs"] - res["program"] = uv["programme"] - res["skills"] = uv["acquisitionCompetences"] - res["key_concepts"] = uv["acquisitionNotions"] - - return Response(res) diff --git a/api/views/uv.py b/api/views/uv.py new file mode 100644 index 00000000..940aa3a7 --- /dev/null +++ b/api/views/uv.py @@ -0,0 +1,120 @@ +from rest_framework.response import Response +from rest_framework.decorators import api_view, renderer_classes +from rest_framework.renderers import JSONRenderer +from django.core.exceptions import PermissionDenied +from rest_framework import serializers +import urllib.request +import json + +from pedagogy.views import CanCreateUVFunctionMixin + + +@api_view(["GET"]) +@renderer_classes((JSONRenderer,)) +def uv_endpoint(request): + # is authenticated and has the right to create an UV + if not request.user.is_authenticated or not CanCreateUVFunctionMixin.can_create_uv( + request.user + ): + raise PermissionDenied + + params = request.query_params + if "year" not in params or "code" not in params: + raise serializers.ValidationError("Missing query parameter") + + short_uv, full_uv = find_uv("fr", params["year"], params["code"]) + if short_uv is None or full_uv is None: + return Response(status=204) + + return Response(make_clean_uv(short_uv, full_uv)) + + +def find_uv(lang, year, code): + """ + Uses the UTBM API to find a UV. + short_uv is the UV entry in the UV list. It is returned as it contains + information which are not in full_uv. + full_uv is the detailed representation of an UV. + """ + # query the UV list + uvs_url = "https://extranet1.utbm.fr/gpedago/api/guide/uvs/{lang}/{year}" + response = urllib.request.urlopen(uvs_url.format(lang=lang, year=year)) + uvs = json.loads(response.read().decode("utf-8")) + + try: + # find the first UV which matches the code + short_uv = next(uv for uv in uvs if uv["code"] == code) + except StopIteration: + return (None, None) + + # get detailed information about the UV + uv_url = "https://extranet1.utbm.fr/gpedago/api/guide/uv/{lang}/{year}/{code}/{formation}" + response = urllib.request.urlopen( + uv_url.format( + lang=lang, year=year, code=code, formation=short_uv["codeFormation"] + ) + ) + full_uv = json.loads(response.read().decode("utf-8")) + + return (short_uv, full_uv) + + +def make_clean_uv(short_uv, full_uv): + """ + Cleans the data up so that it corresponds to our data representation. + """ + res = {} + + res["credit_type"] = short_uv["codeCategorie"] + + # probably wrong on a few UVs as we pick the first UV we find but + # availability depends on the formation + semesters = { + (True, True): "AUTUMN_AND_SPRING", + (True, False): "AUTUMN", + (False, True): "SPRING", + } + res["semester"] = semesters.get( + (short_uv["ouvertAutomne"], short_uv["ouvertPrintemps"]), "CLOSED" + ) + + langs = {"es": "SP", "en": "EN", "de": "DE"} + res["language"] = langs.get(full_uv["codeLangue"], "FR") + + if full_uv["departement"] == "Pôle Humanités": + res["department"] = "HUMA" + else: + departments = { + "AL": "IMSI", + "AE": "EE", + "GI": "GI", + "GC": "EE", + "GM": "MC", + "TC": "TC", + "GP": "IMSI", + "ED": "EDIM", + "AI": "GI", + "AM": "MC", + } + res["department"] = departments.get(full_uv["codeFormation"], "NA") + + res["credits"] = full_uv["creditsEcts"] + + activities = ("CM", "TD", "TP", "THE", "TE") + for activity in activities: + res["hours_{}".format(activity)] = 0 + for activity in full_uv["activites"]: + if activity["code"] in activities: + res["hours_{}".format(activity["code"])] += activity["nbh"] // 60 + + # wrong if the manager changes depending on the semester + res["manager"] = full_uv["automne"]["responsable"] + + res["title"] = full_uv["libelle"] + + res["objectives"] = full_uv["objectifs"] + res["program"] = full_uv["programme"] + res["skills"] = full_uv["acquisitionCompetences"] + res["key_concepts"] = full_uv["acquisitionNotions"] + + return res diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index bb935af5..473bbcc9 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-10-13 17:21+0200\n" +"POT-Creation-Date: 2019-10-18 18:04+0200\n" "PO-Revision-Date: 2016-07-18\n" "Last-Translator: Skia \n" "Language-Team: AE info \n" @@ -88,12 +88,12 @@ msgstr "Compte club" msgid "%(club_account)s on %(bank_account)s" msgstr "%(club_account)s sur %(bank_account)s" -#: accounting/models.py:214 club/models.py:281 counter/models.py:616 +#: accounting/models.py:214 club/models.py:281 counter/models.py:632 #: election/models.py:18 launderette/models.py:194 msgid "start date" msgstr "date de début" -#: accounting/models.py:215 club/models.py:282 counter/models.py:617 +#: accounting/models.py:215 club/models.py:282 counter/models.py:633 #: election/models.py:19 msgid "end date" msgstr "date de fin" @@ -129,13 +129,13 @@ msgstr "classeur" #: accounting/models.py:290 core/models.py:825 core/models.py:1363 #: core/models.py:1411 core/models.py:1440 counter/models.py:364 -#: counter/models.py:457 counter/models.py:646 eboutic/models.py:46 +#: counter/models.py:457 counter/models.py:662 eboutic/models.py:46 #: eboutic/models.py:93 forum/models.py:311 forum/models.py:408 #: stock/models.py:104 msgid "date" msgstr "date" -#: accounting/models.py:291 counter/models.py:123 counter/models.py:647 +#: accounting/models.py:291 counter/models.py:123 counter/models.py:663 #: pedagogy/models.py:219 stock/models.py:107 msgid "comment" msgstr "commentaire" @@ -654,7 +654,7 @@ msgid "Target" msgstr "Cible" #: accounting/templates/accounting/journal_details.jinja:38 -#: core/views/forms.py:112 +#: core/views/forms.py:94 msgid "Code" msgstr "Code" @@ -1046,7 +1046,7 @@ msgstr "Vous ne pouvez pas faire de boucles dans les clubs" msgid "A club with that unix_name already exists" msgstr "Un club avec ce nom UNIX existe déjà." -#: club/models.py:267 counter/models.py:607 counter/models.py:637 +#: club/models.py:267 counter/models.py:623 counter/models.py:653 #: eboutic/models.py:42 eboutic/models.py:89 election/models.py:192 #: launderette/models.py:145 launderette/models.py:213 sas/models.py:244 #: trombi/models.py:213 @@ -1155,7 +1155,7 @@ msgid "There are no members in this club." msgstr "Il n'y a pas de membres dans ce club." #: club/templates/club/club_members.jinja:78 -#: core/templates/core/file_detail.jinja:19 core/views/forms.py:355 +#: core/templates/core/file_detail.jinja:19 core/views/forms.py:337 #: launderette/views.py:226 trombi/templates/trombi/detail.jinja:19 msgid "Add" msgstr "Ajouter" @@ -1363,7 +1363,7 @@ msgstr "Anciens membres" msgid "History" msgstr "Historique" -#: club/views.py:115 core/templates/core/base.jinja:119 core/views/user.py:219 +#: club/views.py:115 core/templates/core/base.jinja:118 core/views/user.py:219 #: sas/templates/sas/picture.jinja:95 trombi/views.py:61 msgid "Tools" msgstr "Outils" @@ -1651,7 +1651,7 @@ msgid "Calls to moderate" msgstr "Appels à modérer" #: com/templates/com/news_admin_list.jinja:242 -#: core/templates/core/base.jinja:171 +#: core/templates/core/base.jinja:170 msgid "Events" msgstr "Événements" @@ -1930,23 +1930,23 @@ msgstr "Jusqu'à" msgid "Automoderation" msgstr "Automodération" -#: com/views.py:227 com/views.py:231 com/views.py:241 +#: com/views.py:227 com/views.py:231 com/views.py:245 msgid "This field is required." msgstr "Ce champ est obligatoire." -#: com/views.py:237 +#: com/views.py:241 msgid "You crazy? You can not finish an event before starting it." msgstr "T'es fou? Un événement ne peut pas finir avant même de commencer." -#: com/views.py:466 +#: com/views.py:470 msgid "Delete and save to regenerate" msgstr "Supprimer et sauver pour regénérer" -#: com/views.py:481 +#: com/views.py:485 msgid "Weekmail of the " msgstr "Weekmail du " -#: com/views.py:591 +#: com/views.py:595 msgid "" "You must be a board member of the selected club to post in the Weekmail." msgstr "" @@ -2372,24 +2372,24 @@ msgstr "500, Erreur Serveur" msgid "Welcome!" msgstr "Bienvenue !" -#: core/templates/core/base.jinja:49 +#: core/templates/core/base.jinja:48 msgid "Username" msgstr "Nom d'utilisateur" -#: core/templates/core/base.jinja:51 +#: core/templates/core/base.jinja:50 msgid "Password" msgstr "Mot de passe" -#: core/templates/core/base.jinja:53 core/templates/core/login.jinja:4 +#: core/templates/core/base.jinja:52 core/templates/core/login.jinja:4 #: core/templates/core/password_reset_complete.jinja:5 msgid "Login" msgstr "Connexion" -#: core/templates/core/base.jinja:55 core/templates/core/register.jinja:18 +#: core/templates/core/base.jinja:54 core/templates/core/register.jinja:18 msgid "Register" msgstr "S'enregister" -#: core/templates/core/base.jinja:81 core/templates/core/base.jinja:82 +#: core/templates/core/base.jinja:80 core/templates/core/base.jinja:81 #: forum/templates/forum/macros.jinja:171 #: forum/templates/forum/macros.jinja:175 #: matmat/templates/matmat/search_form.jinja:37 @@ -2399,64 +2399,64 @@ msgstr "S'enregister" msgid "Search" msgstr "Recherche" -#: core/templates/core/base.jinja:108 +#: core/templates/core/base.jinja:107 msgid "View more" msgstr "Voir plus" -#: core/templates/core/base.jinja:112 +#: core/templates/core/base.jinja:111 #: forum/templates/forum/last_unread.jinja:17 msgid "Mark all as read" msgstr "Marquer tout commme lu" -#: core/templates/core/base.jinja:122 +#: core/templates/core/base.jinja:121 msgid "Logout" msgstr "Déconnexion" -#: core/templates/core/base.jinja:155 +#: core/templates/core/base.jinja:154 msgid "Main" msgstr "Accueil" -#: core/templates/core/base.jinja:157 +#: core/templates/core/base.jinja:156 msgid "Associations & Clubs" msgstr "Associations & Clubs" -#: core/templates/core/base.jinja:161 +#: core/templates/core/base.jinja:160 msgid "AE" msgstr "L'AE" -#: core/templates/core/base.jinja:162 +#: core/templates/core/base.jinja:161 msgid "AE's clubs" msgstr "Les clubs de L'AE" -#: core/templates/core/base.jinja:163 +#: core/templates/core/base.jinja:162 msgid "BdF" msgstr "Le BdF" -#: core/templates/core/base.jinja:164 +#: core/templates/core/base.jinja:163 msgid "BDS" msgstr "Le BDS" -#: core/templates/core/base.jinja:165 +#: core/templates/core/base.jinja:164 msgid "CETU" msgstr "Le CETU" -#: core/templates/core/base.jinja:166 +#: core/templates/core/base.jinja:165 msgid "Doceo" msgstr "Doceo" -#: core/templates/core/base.jinja:167 +#: core/templates/core/base.jinja:166 msgid "Positions" msgstr "Postes à pourvoir" -#: core/templates/core/base.jinja:175 +#: core/templates/core/base.jinja:174 msgid "Calendar" msgstr "Calendrier" -#: core/templates/core/base.jinja:176 +#: core/templates/core/base.jinja:175 msgid "Big event" msgstr "Grandes Activités" -#: core/templates/core/base.jinja:179 +#: core/templates/core/base.jinja:178 #: forum/templates/forum/favorite_topics.jinja:14 #: forum/templates/forum/last_unread.jinja:14 #: forum/templates/forum/macros.jinja:90 forum/templates/forum/main.jinja:6 @@ -2465,11 +2465,11 @@ msgstr "Grandes Activités" msgid "Forum" msgstr "Forum" -#: core/templates/core/base.jinja:180 +#: core/templates/core/base.jinja:179 msgid "Gallery" msgstr "Photos" -#: core/templates/core/base.jinja:181 counter/models.py:223 +#: core/templates/core/base.jinja:180 counter/models.py:223 #: counter/templates/counter/counter_list.jinja:11 #: eboutic/templates/eboutic/eboutic_main.jinja:4 #: eboutic/templates/eboutic/eboutic_main.jinja:24 @@ -2479,75 +2479,75 @@ msgstr "Photos" msgid "Eboutic" msgstr "Eboutic" -#: core/templates/core/base.jinja:183 +#: core/templates/core/base.jinja:182 msgid "Services" msgstr "Services" -#: core/templates/core/base.jinja:187 +#: core/templates/core/base.jinja:186 msgid "Matmatronch" msgstr "Matmatronch" -#: core/templates/core/base.jinja:188 launderette/models.py:47 +#: core/templates/core/base.jinja:187 launderette/models.py:47 #: launderette/templates/launderette/launderette_book.jinja:5 #: launderette/templates/launderette/launderette_book_choose.jinja:4 #: launderette/templates/launderette/launderette_main.jinja:4 msgid "Launderette" msgstr "Laverie" -#: core/templates/core/base.jinja:189 core/templates/core/file.jinja:20 +#: core/templates/core/base.jinja:188 core/templates/core/file.jinja:20 #: core/views/files.py:84 msgid "Files" msgstr "Fichiers" -#: core/templates/core/base.jinja:190 core/templates/core/user_tools.jinja:108 +#: core/templates/core/base.jinja:189 core/templates/core/user_tools.jinja:108 msgid "Pedagogy" msgstr "Pédagogie" -#: core/templates/core/base.jinja:194 +#: core/templates/core/base.jinja:193 msgid "My Benefits" msgstr "Mes Avantages" -#: core/templates/core/base.jinja:198 +#: core/templates/core/base.jinja:197 msgid "Sponsors" msgstr "Partenaires" -#: core/templates/core/base.jinja:199 +#: core/templates/core/base.jinja:198 msgid "Subscriber benefits" msgstr "Les avantages cotisants" -#: core/templates/core/base.jinja:203 +#: core/templates/core/base.jinja:202 msgid "Help" msgstr "Aide" -#: core/templates/core/base.jinja:207 +#: core/templates/core/base.jinja:206 msgid "FAQ" msgstr "FAQ" -#: core/templates/core/base.jinja:208 core/templates/core/base.jinja:250 +#: core/templates/core/base.jinja:207 core/templates/core/base.jinja:249 msgid "Contacts" msgstr "Contacts" -#: core/templates/core/base.jinja:209 +#: core/templates/core/base.jinja:208 msgid "Wiki" msgstr "Wiki" -#: core/templates/core/base.jinja:251 +#: core/templates/core/base.jinja:250 msgid "Legal notices" msgstr "Mentions légales" -#: core/templates/core/base.jinja:252 +#: core/templates/core/base.jinja:251 msgid "Intellectual property" msgstr "Propriété intellectuelle" -#: core/templates/core/base.jinja:253 +#: core/templates/core/base.jinja:252 msgid "Help & Documentation" msgstr "Aide & Documentation" -#: core/templates/core/base.jinja:254 +#: core/templates/core/base.jinja:253 msgid "R&D" msgstr "R&D" -#: core/templates/core/base.jinja:256 +#: core/templates/core/base.jinja:255 msgid "Site made by good people" msgstr "Site réalisé par des gens bons" @@ -2688,6 +2688,7 @@ msgstr "Éditer le groupe" #: core/templates/core/group_edit.jinja:9 #: core/templates/core/user_edit.jinja:37 #: core/templates/core/user_group.jinja:8 +#: pedagogy/templates/pedagogy/uv_create.jinja:36 msgid "Update" msgstr "Mettre à jour" @@ -3520,7 +3521,7 @@ msgstr "Ajouter un nouveau dossier" msgid "Error creating folder %(folder_name)s: %(msg)s" msgstr "Erreur de création du dossier %(folder_name)s : %(msg)s" -#: core/views/files.py:121 core/views/forms.py:323 core/views/forms.py:330 +#: core/views/files.py:121 core/views/forms.py:305 core/views/forms.py:312 #: sas/views.py:94 #, python-format msgid "Error uploading file %(file_name)s: %(msg)s" @@ -3530,91 +3531,91 @@ msgstr "Erreur d'envoi du fichier %(file_name)s : %(msg)s" msgid "Apply rights recursively" msgstr "Appliquer les droits récursivement" -#: core/views/forms.py:105 +#: core/views/forms.py:87 msgid "Heading" msgstr "Titre" -#: core/views/forms.py:106 +#: core/views/forms.py:88 msgid "Italic" msgstr "Italique" -#: core/views/forms.py:107 +#: core/views/forms.py:89 msgid "Bold" msgstr "Gras" -#: core/views/forms.py:108 +#: core/views/forms.py:90 msgid "Strikethrough" msgstr "Barré" -#: core/views/forms.py:109 +#: core/views/forms.py:91 msgid "Underline" msgstr "Souligné" -#: core/views/forms.py:110 +#: core/views/forms.py:92 msgid "Superscript" msgstr "Exposant" -#: core/views/forms.py:111 +#: core/views/forms.py:93 msgid "Subscript" msgstr "Indice" -#: core/views/forms.py:113 +#: core/views/forms.py:95 msgid "Quote" msgstr "Citation" -#: core/views/forms.py:114 +#: core/views/forms.py:96 msgid "Unordered list" msgstr "Liste non ordonnée" -#: core/views/forms.py:115 +#: core/views/forms.py:97 msgid "Ordered list" msgstr "Liste ordonnée" -#: core/views/forms.py:116 +#: core/views/forms.py:98 msgid "Insert image" msgstr "Insérer image" -#: core/views/forms.py:117 +#: core/views/forms.py:99 msgid "Insert link" msgstr "Insérer lien" -#: core/views/forms.py:118 +#: core/views/forms.py:100 msgid "Insert table" msgstr "Insérer tableau" -#: core/views/forms.py:119 +#: core/views/forms.py:101 msgid "Clean block" msgstr "Nettoyer bloc" -#: core/views/forms.py:120 +#: core/views/forms.py:102 msgid "Toggle preview" msgstr "Activer la prévisualisation" -#: core/views/forms.py:121 +#: core/views/forms.py:103 msgid "Toggle side by side" msgstr "Activer la vue côte à côte" -#: core/views/forms.py:122 +#: core/views/forms.py:104 msgid "Toggle fullscreen" msgstr "Activer le plein écran" -#: core/views/forms.py:123 +#: core/views/forms.py:105 msgid "Markdown guide" msgstr "Guide markdown" -#: core/views/forms.py:139 core/views/forms.py:147 +#: core/views/forms.py:121 core/views/forms.py:129 msgid "Choose file" msgstr "Choisir un fichier" -#: core/views/forms.py:163 core/views/forms.py:171 +#: core/views/forms.py:145 core/views/forms.py:153 msgid "Choose user" msgstr "Choisir un utilisateur" -#: core/views/forms.py:203 +#: core/views/forms.py:185 msgid "Username, email, or account number" msgstr "Nom d'utilisateur, email, ou numéro de compte AE" -#: core/views/forms.py:269 +#: core/views/forms.py:251 msgid "" "Profile: you need to be visible on the picture, in order to be recognized (e." "g. by the barmen)" @@ -3622,36 +3623,36 @@ msgstr "" "Photo de profil: vous devez être visible sur la photo afin d'être reconnu " "(par exemple par les barmen)" -#: core/views/forms.py:271 +#: core/views/forms.py:253 msgid "Avatar: used on the forum" msgstr "Avatar : utilisé sur le forum" -#: core/views/forms.py:272 +#: core/views/forms.py:254 msgid "Scrub: let other know how your scrub looks like!" msgstr "Blouse : montrez aux autres à quoi ressemble votre blouse !" -#: core/views/forms.py:334 +#: core/views/forms.py:316 msgid "Bad image format, only jpeg, png, and gif are accepted" msgstr "Mauvais format d'image, seuls les jpeg, png, et gif sont acceptés" -#: core/views/forms.py:354 +#: core/views/forms.py:336 msgid "Godfather" msgstr "Parrain" -#: core/views/forms.py:354 +#: core/views/forms.py:336 msgid "Godchild" msgstr "Fillot" -#: core/views/forms.py:358 counter/views.py:154 trombi/views.py:156 +#: core/views/forms.py:340 counter/views.py:154 trombi/views.py:156 msgid "Select user" msgstr "Choisir un utilisateur" -#: core/views/forms.py:371 core/views/forms.py:389 election/models.py:24 +#: core/views/forms.py:353 core/views/forms.py:371 election/models.py:24 #: election/views.py:154 msgid "edit groups" msgstr "groupe d'édition" -#: core/views/forms.py:374 core/views/forms.py:392 election/models.py:31 +#: core/views/forms.py:356 core/views/forms.py:374 election/models.py:31 #: election/views.py:157 msgid "view groups" msgstr "groupe de vue" @@ -3742,7 +3743,7 @@ msgstr "groupe d'achat" msgid "archived" msgstr "archivé" -#: counter/models.py:185 counter/models.py:738 +#: counter/models.py:185 counter/models.py:754 msgid "product" msgstr "produit" @@ -3770,7 +3771,7 @@ msgstr "vendeurs" msgid "token" msgstr "jeton" -#: counter/models.py:237 counter/models.py:613 counter/models.py:643 +#: counter/models.py:237 counter/models.py:629 counter/models.py:659 #: launderette/models.py:41 stock/models.py:43 msgid "counter" msgstr "comptoir" @@ -3791,7 +3792,7 @@ msgstr "rechargement" msgid "unit price" msgstr "prix unitaire" -#: counter/models.py:442 counter/models.py:723 eboutic/models.py:155 +#: counter/models.py:442 counter/models.py:739 eboutic/models.py:155 msgid "quantity" msgstr "quantité" @@ -3808,16 +3809,16 @@ msgstr "Carte bancaire" msgid "selling" msgstr "vente" -#: counter/models.py:490 +#: counter/models.py:494 msgid "Unknown event" msgstr "Événement inconnu" -#: counter/models.py:491 +#: counter/models.py:495 #, python-format msgid "Eticket bought for the event %(event)s" msgstr "Eticket acheté pour l'événement %(event)s" -#: counter/models.py:493 counter/models.py:508 +#: counter/models.py:497 counter/models.py:520 #, python-format msgid "" "You bought an eticket for the event %(event)s.\n" @@ -3829,59 +3830,59 @@ msgstr "" "Vous pouvez également retrouver tous vos e-tickets sur votre page de compte " "%(url)s." -#: counter/models.py:618 +#: counter/models.py:634 msgid "last activity date" msgstr "dernière activité" -#: counter/models.py:621 +#: counter/models.py:637 msgid "permanency" msgstr "permanence" -#: counter/models.py:648 +#: counter/models.py:664 msgid "emptied" msgstr "coffre vidée" -#: counter/models.py:651 +#: counter/models.py:667 msgid "cash register summary" msgstr "relevé de caisse" -#: counter/models.py:719 +#: counter/models.py:735 msgid "cash summary" msgstr "relevé" -#: counter/models.py:722 +#: counter/models.py:738 msgid "value" msgstr "valeur" -#: counter/models.py:724 +#: counter/models.py:740 msgid "check" msgstr "chèque" -#: counter/models.py:727 +#: counter/models.py:743 msgid "cash register summary item" msgstr "élément de relevé de caisse" -#: counter/models.py:742 +#: counter/models.py:758 msgid "banner" msgstr "bannière" -#: counter/models.py:744 +#: counter/models.py:760 msgid "event date" msgstr "date de l'événement" -#: counter/models.py:746 +#: counter/models.py:762 msgid "event title" msgstr "titre de l'événement" -#: counter/models.py:748 +#: counter/models.py:764 msgid "secret" msgstr "secret" -#: counter/models.py:804 +#: counter/models.py:820 msgid "uid" msgstr "uid" -#: counter/models.py:809 +#: counter/models.py:825 msgid "student cards" msgstr "cartes étudiante" @@ -4291,7 +4292,7 @@ msgstr "Montant du chèque" msgid "Check quantity" msgstr "Nombre de chèque" -#: counter/views.py:1802 +#: counter/views.py:1806 msgid "people(s)" msgstr "personne(s)" @@ -4987,6 +4988,19 @@ msgstr "Supprimer commentaire" msgid "Delete report" msgstr "Supprimer signalement" +#: pedagogy/templates/pedagogy/uv_create.jinja:4 +#: pedagogy/templates/pedagogy/uv_create.jinja:8 +#, fuzzy +#| msgid "Edit" +msgid "Edit UV" +msgstr "Éditer" + +#: pedagogy/templates/pedagogy/uv_create.jinja:57 +#, fuzzy +#| msgid "Unknown event" +msgid "Unknown UV code" +msgstr "Code d'UV inconnu" + #: pedagogy/templates/pedagogy/uv_detail.jinja:6 msgid "UV Details" msgstr "Détails d'UV" diff --git a/pedagogy/templates/pedagogy/uv_create.jinja b/pedagogy/templates/pedagogy/uv_create.jinja index a648799b..7f00598c 100644 --- a/pedagogy/templates/pedagogy/uv_create.jinja +++ b/pedagogy/templates/pedagogy/uv_create.jinja @@ -52,7 +52,11 @@ year-- } const url = "{{ url('api:uv_endpoint') }}?year=" + year + "&code=" + codeInput.value - $.getJSON(url, function(data) { + $.getJSON(url, function(data, _, xhr) { + if (xhr.status != 200) { + alert('{% trans %}Unknown UV code{% endtrans %}') + return + } for (let key in data) { if (data.hasOwnProperty(key)) { const el = document.querySelector('[name="' + key + '"]') From 4759551c16917b7f7a2951b08c9cfe878aeb7c13 Mon Sep 17 00:00:00 2001 From: tleb Date: Sun, 20 Oct 2019 17:09:36 +0200 Subject: [PATCH 04/14] Autofull UV small changes --- locale/fr/LC_MESSAGES/django.po | 14 +++++++++----- pedagogy/templates/pedagogy/uv_create.jinja | 9 +++++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 473bbcc9..04483f41 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-10-18 18:04+0200\n" +"POT-Creation-Date: 2019-10-20 16:50+0200\n" "PO-Revision-Date: 2016-07-18\n" "Last-Translator: Skia \n" "Language-Team: AE info \n" @@ -4990,17 +4990,21 @@ msgstr "Supprimer signalement" #: pedagogy/templates/pedagogy/uv_create.jinja:4 #: pedagogy/templates/pedagogy/uv_create.jinja:8 -#, fuzzy -#| msgid "Edit" msgid "Edit UV" msgstr "Éditer" +#: pedagogy/templates/pedagogy/uv_create.jinja:27 +msgid "Import from UTBM" +msgstr "Importer depuis l'UTBM" + #: pedagogy/templates/pedagogy/uv_create.jinja:57 -#, fuzzy -#| msgid "Unknown event" msgid "Unknown UV code" msgstr "Code d'UV inconnu" +#: pedagogy/templates/pedagogy/uv_create.jinja:72 +msgid "Successful autocomplete" +msgstr "Autocomplétion réussite" + #: pedagogy/templates/pedagogy/uv_detail.jinja:6 msgid "UV Details" msgstr "Détails d'UV" diff --git a/pedagogy/templates/pedagogy/uv_create.jinja b/pedagogy/templates/pedagogy/uv_create.jinja index 7f00598c..9940390c 100644 --- a/pedagogy/templates/pedagogy/uv_create.jinja +++ b/pedagogy/templates/pedagogy/uv_create.jinja @@ -24,7 +24,7 @@ {% if field.name == 'code' %} - Fill + {% endif %}

{% endif %} @@ -48,13 +48,13 @@ autofillBtn.addEventListener('click', () => { const today = new Date() let year = today.getFullYear() - if (today.getMonth() < 7) { // student year, starts in september + if (today.getMonth() < 7) { // student year starts in september year-- } const url = "{{ url('api:uv_endpoint') }}?year=" + year + "&code=" + codeInput.value $.getJSON(url, function(data, _, xhr) { if (xhr.status != 200) { - alert('{% trans %}Unknown UV code{% endtrans %}') + alert("{% trans %}Unknown UV code{% endtrans %}") return } for (let key in data) { @@ -68,9 +68,10 @@ } } + + alert('{% trans %}Successful autocomplete{% endtrans %}') }) }) - }) {% endblock %} From 86bc491df4f0f54f92911f809b056640dfae5b57 Mon Sep 17 00:00:00 2001 From: tleb Date: Sun, 20 Oct 2019 18:26:11 +0200 Subject: [PATCH 05/14] Fix UV_endpoint auth --- api/views/uv.py | 5 +---- core/middleware.py | 2 +- core/models.py | 2 +- sith/settings.py | 3 +++ 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/api/views/uv.py b/api/views/uv.py index 940aa3a7..2b7b33e9 100644 --- a/api/views/uv.py +++ b/api/views/uv.py @@ -12,10 +12,7 @@ from pedagogy.views import CanCreateUVFunctionMixin @api_view(["GET"]) @renderer_classes((JSONRenderer,)) def uv_endpoint(request): - # is authenticated and has the right to create an UV - if not request.user.is_authenticated or not CanCreateUVFunctionMixin.can_create_uv( - request.user - ): + if not CanCreateUVFunctionMixin.can_create_uv(request.user): raise PermissionDenied params = request.query_params diff --git a/core/middleware.py b/core/middleware.py index 54d7dd2e..2567dc91 100644 --- a/core/middleware.py +++ b/core/middleware.py @@ -38,7 +38,7 @@ def get_cached_user(request): if not hasattr(request, "_cached_user"): user = get_user(request) if user.is_anonymous: - user = AnonymousUser(request) + user = AnonymousUser() request._cached_user = user diff --git a/core/models.py b/core/models.py index 17bc5003..1afc9858 100644 --- a/core/models.py +++ b/core/models.py @@ -659,7 +659,7 @@ class User(AbstractBaseUser): class AnonymousUser(AuthAnonymousUser): - def __init__(self, request): + def __init__(self): super(AnonymousUser, self).__init__() @property diff --git a/sith/settings.py b/sith/settings.py index 75c864d3..3fe4e826 100644 --- a/sith/settings.py +++ b/sith/settings.py @@ -196,6 +196,8 @@ SASS_PRECISION = 8 WSGI_APPLICATION = "sith.wsgi.application" +REST_FRAMEWORK = {} + # Database # https://docs.djangoproject.com/en/1.8/ref/settings/#databases @@ -252,6 +254,7 @@ LOGOUT_URL = "/logout" LOGIN_REDIRECT_URL = "/" DEFAULT_FROM_EMAIL = "bibou@git.an" SITH_COM_EMAIL = "bibou_com@git.an" +REST_FRAMEWORK["UNAUTHENTICATED_USER"] = "core.models.AnonymousUser" # Email EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" From f533c39e67bf79c39958131658acc0b260f926ed Mon Sep 17 00:00:00 2001 From: Bartuccio Antoine Date: Mon, 21 Oct 2019 02:10:09 +0200 Subject: [PATCH 06/14] api: fix uv manager acquisition if uv is only available in spring --- api/views/uv.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/api/views/uv.py b/api/views/uv.py index 2b7b33e9..5a0f2929 100644 --- a/api/views/uv.py +++ b/api/views/uv.py @@ -105,7 +105,10 @@ def make_clean_uv(short_uv, full_uv): res["hours_{}".format(activity["code"])] += activity["nbh"] // 60 # wrong if the manager changes depending on the semester - res["manager"] = full_uv["automne"]["responsable"] + semester = full_uv.get("automne", None) + if not semester: + semester = full_uv.get("printemps", {}) + res["manager"] = semester.get("responsable", "") res["title"] = full_uv["libelle"] From 4094394cef5c6cd03643c838085d3629664f7ffb Mon Sep 17 00:00:00 2001 From: tleb Date: Mon, 21 Oct 2019 08:13:36 +0200 Subject: [PATCH 07/14] api: typo in doc comment --- api/views/uv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/views/uv.py b/api/views/uv.py index 5a0f2929..24e72dd2 100644 --- a/api/views/uv.py +++ b/api/views/uv.py @@ -28,7 +28,7 @@ def uv_endpoint(request): def find_uv(lang, year, code): """ - Uses the UTBM API to find a UV. + Uses the UTBM API to find an UV. short_uv is the UV entry in the UV list. It is returned as it contains information which are not in full_uv. full_uv is the detailed representation of an UV. From 53a76337003879ec1defb52c7ab8331524d1c1e6 Mon Sep 17 00:00:00 2001 From: tleb Date: Mon, 21 Oct 2019 10:34:46 +0200 Subject: [PATCH 08/14] uv: Add error handler to uv autofill --- locale/fr/LC_MESSAGES/django.po | 202 ++++++++++---------- pedagogy/templates/pedagogy/uv_create.jinja | 38 ++-- 2 files changed, 127 insertions(+), 113 deletions(-) diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 04483f41..a826a20a 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-10-20 16:50+0200\n" +"POT-Creation-Date: 2019-10-21 10:28+0200\n" "PO-Revision-Date: 2016-07-18\n" "Last-Translator: Skia \n" "Language-Team: AE info \n" @@ -218,7 +218,7 @@ msgstr "Compte" msgid "Company" msgstr "Entreprise" -#: accounting/models.py:341 sith/settings.py:377 +#: accounting/models.py:341 sith/settings.py:380 #: stock/templates/stock/shopping_list_items.jinja:37 msgid "Other" msgstr "Autre" @@ -531,7 +531,7 @@ msgid "Effective amount" msgstr "Montant effectif" #: accounting/templates/accounting/club_account_details.jinja:36 -#: sith/settings.py:421 +#: sith/settings.py:424 msgid "Closed" msgstr "Fermé" @@ -2475,7 +2475,7 @@ msgstr "Photos" #: eboutic/templates/eboutic/eboutic_main.jinja:24 #: eboutic/templates/eboutic/eboutic_makecommand.jinja:8 #: eboutic/templates/eboutic/eboutic_payment_result.jinja:4 -#: sith/settings.py:376 sith/settings.py:384 +#: sith/settings.py:379 sith/settings.py:387 msgid "Eboutic" msgstr "Eboutic" @@ -3800,8 +3800,8 @@ msgstr "quantité" msgid "Sith account" msgstr "Compte utilisateur" -#: counter/models.py:461 sith/settings.py:369 sith/settings.py:374 -#: sith/settings.py:392 +#: counter/models.py:461 sith/settings.py:372 sith/settings.py:377 +#: sith/settings.py:395 msgid "Credit card" msgstr "Carte bancaire" @@ -4726,12 +4726,12 @@ msgid "Washing and drying" msgstr "Lavage et séchage" #: launderette/templates/launderette/launderette_book.jinja:27 -#: sith/settings.py:583 +#: sith/settings.py:586 msgid "Washing" msgstr "Lavage" #: launderette/templates/launderette/launderette_book.jinja:31 -#: sith/settings.py:583 +#: sith/settings.py:586 msgid "Drying" msgstr "Séchage" @@ -4997,14 +4997,20 @@ msgstr "Éditer" msgid "Import from UTBM" msgstr "Importer depuis l'UTBM" -#: pedagogy/templates/pedagogy/uv_create.jinja:57 +#: pedagogy/templates/pedagogy/uv_create.jinja:61 +#: pedagogy/templates/pedagogy/uv_create.jinja:84 msgid "Unknown UV code" msgstr "Code d'UV inconnu" -#: pedagogy/templates/pedagogy/uv_create.jinja:72 +#: pedagogy/templates/pedagogy/uv_create.jinja:76 +#: pedagogy/templates/pedagogy/uv_create.jinja:99 msgid "Successful autocomplete" msgstr "Autocomplétion réussite" +#: pedagogy/templates/pedagogy/uv_create.jinja:79 +msgid "An error occured: " +msgstr "Une erreur est survenue : " + #: pedagogy/templates/pedagogy/uv_detail.jinja:6 msgid "UV Details" msgstr "Détails d'UV" @@ -5217,360 +5223,360 @@ msgstr "Erreur de création de l'album %(album)s : %(msg)s" msgid "Add user" msgstr "Ajouter une personne" -#: sith/settings.py:216 sith/settings.py:429 +#: sith/settings.py:218 sith/settings.py:432 msgid "English" msgstr "Anglais" -#: sith/settings.py:216 sith/settings.py:428 +#: sith/settings.py:218 sith/settings.py:431 msgid "French" msgstr "Français" -#: sith/settings.py:350 +#: sith/settings.py:353 msgid "TC" msgstr "TC" -#: sith/settings.py:351 +#: sith/settings.py:354 msgid "IMSI" msgstr "IMSI" -#: sith/settings.py:352 +#: sith/settings.py:355 msgid "IMAP" msgstr "IMAP" -#: sith/settings.py:353 +#: sith/settings.py:356 msgid "INFO" msgstr "INFO" -#: sith/settings.py:354 +#: sith/settings.py:357 msgid "GI" msgstr "GI" -#: sith/settings.py:355 sith/settings.py:439 +#: sith/settings.py:358 sith/settings.py:442 msgid "E" msgstr "E" -#: sith/settings.py:356 +#: sith/settings.py:359 msgid "EE" msgstr "EE" -#: sith/settings.py:357 +#: sith/settings.py:360 msgid "GESC" msgstr "GESC" -#: sith/settings.py:358 +#: sith/settings.py:361 msgid "GMC" msgstr "GMC" -#: sith/settings.py:359 +#: sith/settings.py:362 msgid "MC" msgstr "MC" -#: sith/settings.py:360 +#: sith/settings.py:363 msgid "EDIM" msgstr "EDIM" -#: sith/settings.py:361 +#: sith/settings.py:364 msgid "Humanities" msgstr "Humanités" -#: sith/settings.py:362 +#: sith/settings.py:365 msgid "N/A" msgstr "N/A" -#: sith/settings.py:366 sith/settings.py:373 sith/settings.py:390 +#: sith/settings.py:369 sith/settings.py:376 sith/settings.py:393 msgid "Check" msgstr "Chèque" -#: sith/settings.py:367 sith/settings.py:375 sith/settings.py:391 +#: sith/settings.py:370 sith/settings.py:378 sith/settings.py:394 msgid "Cash" msgstr "Espèces" -#: sith/settings.py:368 +#: sith/settings.py:371 msgid "Transfert" msgstr "Virement" -#: sith/settings.py:381 +#: sith/settings.py:384 msgid "Belfort" msgstr "Belfort" -#: sith/settings.py:382 +#: sith/settings.py:385 msgid "Sevenans" msgstr "Sevenans" -#: sith/settings.py:383 +#: sith/settings.py:386 msgid "Montbéliard" msgstr "Montbéliard" -#: sith/settings.py:409 +#: sith/settings.py:412 msgid "Free" msgstr "Libre" -#: sith/settings.py:410 +#: sith/settings.py:413 msgid "CS" msgstr "CS" -#: sith/settings.py:411 +#: sith/settings.py:414 msgid "TM" msgstr "TM" -#: sith/settings.py:412 +#: sith/settings.py:415 msgid "OM" msgstr "OM" -#: sith/settings.py:413 +#: sith/settings.py:416 msgid "QC" msgstr "QC" -#: sith/settings.py:414 +#: sith/settings.py:417 msgid "EC" msgstr "EC" -#: sith/settings.py:415 +#: sith/settings.py:418 msgid "RN" msgstr "RN" -#: sith/settings.py:416 +#: sith/settings.py:419 msgid "ST" msgstr "ST" -#: sith/settings.py:417 +#: sith/settings.py:420 msgid "EXT" msgstr "EXT" -#: sith/settings.py:422 +#: sith/settings.py:425 msgid "Autumn" msgstr "Automne" -#: sith/settings.py:423 +#: sith/settings.py:426 msgid "Spring" msgstr "Printemps" -#: sith/settings.py:424 +#: sith/settings.py:427 msgid "Autumn and spring" msgstr "Automne et printemps" -#: sith/settings.py:430 +#: sith/settings.py:433 msgid "German" msgstr "Allemant" -#: sith/settings.py:431 +#: sith/settings.py:434 msgid "Spanich" msgstr "Espagnol" -#: sith/settings.py:435 +#: sith/settings.py:438 msgid "A" msgstr "A" -#: sith/settings.py:436 +#: sith/settings.py:439 msgid "B" msgstr "B" -#: sith/settings.py:437 +#: sith/settings.py:440 msgid "C" msgstr "C" -#: sith/settings.py:438 +#: sith/settings.py:441 msgid "D" msgstr "D" -#: sith/settings.py:440 +#: sith/settings.py:443 msgid "FX" msgstr "FX" -#: sith/settings.py:441 +#: sith/settings.py:444 msgid "F" msgstr "F" -#: sith/settings.py:442 +#: sith/settings.py:445 msgid "Abs" msgstr "Abs" -#: sith/settings.py:471 +#: sith/settings.py:474 msgid "One semester" msgstr "Un semestre, 15 €" -#: sith/settings.py:472 +#: sith/settings.py:475 msgid "Two semesters" msgstr "Deux semestres, 28 €" -#: sith/settings.py:474 +#: sith/settings.py:477 msgid "Common core cursus" msgstr "Cursus tronc commun, 45 €" -#: sith/settings.py:478 +#: sith/settings.py:481 msgid "Branch cursus" msgstr "Cursus branche, 45 €" -#: sith/settings.py:479 +#: sith/settings.py:482 msgid "Alternating cursus" msgstr "Cursus alternant, 30 €" -#: sith/settings.py:480 +#: sith/settings.py:483 msgid "Honorary member" msgstr "Membre honoraire, 0 €" -#: sith/settings.py:481 +#: sith/settings.py:484 msgid "Assidu member" msgstr "Membre d'Assidu, 0 €" -#: sith/settings.py:482 +#: sith/settings.py:485 msgid "Amicale/DOCEO member" msgstr "Membre de l'Amicale/DOCEO, 0 €" -#: sith/settings.py:483 +#: sith/settings.py:486 msgid "UT network member" msgstr "Cotisant du réseau UT, 0 €" -#: sith/settings.py:484 +#: sith/settings.py:487 msgid "CROUS member" msgstr "Membres du CROUS, 0 €" -#: sith/settings.py:485 +#: sith/settings.py:488 msgid "Sbarro/ESTA member" msgstr "Membre de Sbarro ou de l'ESTA, 15 €" -#: sith/settings.py:487 +#: sith/settings.py:490 msgid "One semester Welcome Week" msgstr "Un semestre Welcome Week" -#: sith/settings.py:491 +#: sith/settings.py:494 msgid "Two months for free" msgstr "Deux mois gratuits" -#: sith/settings.py:492 +#: sith/settings.py:495 msgid "Eurok's volunteer" msgstr "Bénévole Eurockéennes" -#: sith/settings.py:494 +#: sith/settings.py:497 msgid "Six weeks for free" msgstr "6 semaines gratuites" -#: sith/settings.py:498 +#: sith/settings.py:501 msgid "One day" msgstr "Un jour" -#: sith/settings.py:501 +#: sith/settings.py:504 msgid "One semester (-20%)" msgstr "Un semestre (-20%), 12 €" -#: sith/settings.py:506 +#: sith/settings.py:509 msgid "Two semesters (-20%)" msgstr "Deux semestres (-20%), 22 €" -#: sith/settings.py:511 +#: sith/settings.py:514 msgid "Common core cursus (-20%)" msgstr "Cursus tronc commun (-20%), 36 €" -#: sith/settings.py:516 +#: sith/settings.py:519 msgid "Branch cursus (-20%)" msgstr "Cursus branche (-20%), 36 €" -#: sith/settings.py:521 +#: sith/settings.py:524 msgid "Alternating cursus (-20%)" msgstr "Cursus alternant (-20%), 24 €" -#: sith/settings.py:543 +#: sith/settings.py:546 msgid "President" msgstr "Président" -#: sith/settings.py:544 +#: sith/settings.py:547 msgid "Vice-President" msgstr "Vice-Président" -#: sith/settings.py:545 +#: sith/settings.py:548 msgid "Treasurer" msgstr "Trésorier" -#: sith/settings.py:546 +#: sith/settings.py:549 msgid "Communication supervisor" msgstr "Responsable communication" -#: sith/settings.py:547 +#: sith/settings.py:550 msgid "Secretary" msgstr "Secrétaire" -#: sith/settings.py:548 +#: sith/settings.py:551 msgid "IT supervisor" msgstr "Responsable info" -#: sith/settings.py:549 +#: sith/settings.py:552 msgid "Board member" msgstr "Membre du bureau" -#: sith/settings.py:550 +#: sith/settings.py:553 msgid "Active member" msgstr "Membre actif" -#: sith/settings.py:551 +#: sith/settings.py:554 msgid "Curious" msgstr "Curieux" -#: sith/settings.py:587 +#: sith/settings.py:590 msgid "A new poster needs to be moderated" msgstr "Une nouvelle affiche a besoin d'être modérée" -#: sith/settings.py:588 +#: sith/settings.py:591 msgid "A new mailing list needs to be moderated" msgstr "Une nouvelle mailing list a besoin d'être modérée" -#: sith/settings.py:591 +#: sith/settings.py:594 msgid "A new pedagogy comment has been signaled for moderation" msgstr "" "Un nouveau commentaire de la pédagogie a été signalé pour la modération" -#: sith/settings.py:593 +#: sith/settings.py:596 #, python-format msgid "There are %s fresh news to be moderated" msgstr "Il y a %s nouvelles toutes fraîches à modérer" -#: sith/settings.py:594 +#: sith/settings.py:597 msgid "New files to be moderated" msgstr "Nouveaux fichiers à modérer" -#: sith/settings.py:595 +#: sith/settings.py:598 #, python-format msgid "There are %s pictures to be moderated in the SAS" msgstr "Il y a %s photos à modérer dans le SAS" -#: sith/settings.py:596 +#: sith/settings.py:599 msgid "You've been identified on some pictures" msgstr "Vous avez été identifié sur des photos" -#: sith/settings.py:597 +#: sith/settings.py:600 #, python-format msgid "You just refilled of %s €" msgstr "Vous avez rechargé votre compte de %s€" -#: sith/settings.py:598 +#: sith/settings.py:601 #, python-format msgid "You just bought %s" msgstr "Vous avez acheté %s" -#: sith/settings.py:599 +#: sith/settings.py:602 msgid "You have a notification" msgstr "Vous avez une notification" -#: sith/settings.py:611 +#: sith/settings.py:614 msgid "Success!" msgstr "Succès !" -#: sith/settings.py:612 +#: sith/settings.py:615 msgid "Fail!" msgstr "Échec !" -#: sith/settings.py:613 +#: sith/settings.py:616 msgid "You successfully posted an article in the Weekmail" msgstr "Article posté avec succès dans le Weekmail" -#: sith/settings.py:614 +#: sith/settings.py:617 msgid "You successfully edited an article in the Weekmail" msgstr "Article édité avec succès dans le Weekmail" -#: sith/settings.py:615 +#: sith/settings.py:618 msgid "You successfully sent the Weekmail" msgstr "Weekmail envoyé avec succès" -#: sith/settings.py:623 +#: sith/settings.py:626 msgid "AE tee-shirt" msgstr "Tee-shirt AE" diff --git a/pedagogy/templates/pedagogy/uv_create.jinja b/pedagogy/templates/pedagogy/uv_create.jinja index 9940390c..daeef735 100644 --- a/pedagogy/templates/pedagogy/uv_create.jinja +++ b/pedagogy/templates/pedagogy/uv_create.jinja @@ -52,24 +52,32 @@ year-- } const url = "{{ url('api:uv_endpoint') }}?year=" + year + "&code=" + codeInput.value - $.getJSON(url, function(data, _, xhr) { - if (xhr.status != 200) { - alert("{% trans %}Unknown UV code{% endtrans %}") - return - } - for (let key in data) { - if (data.hasOwnProperty(key)) { - const el = document.querySelector('[name="' + key + '"]') - if (el.tagName == 'TEXTAREA') { - el.parentNode.querySelector('.CodeMirror').CodeMirror.setValue(data[key]) - } else { - el.value = data[key] - } + $.ajax({ + dataType: "json", + url: url, + success: function(data, _, xhr) { + if (xhr.status != 200) { + alert("{% trans %}Unknown UV code{% endtrans %}") + return } - } + for (let key in data) { + if (data.hasOwnProperty(key)) { + const el = document.querySelector('[name="' + key + '"]') + if (el.tagName == 'TEXTAREA') { + el.parentNode.querySelector('.CodeMirror').CodeMirror.setValue(data[key]) + } else { + el.value = data[key] + } - alert('{% trans %}Successful autocomplete{% endtrans %}') + } + } + + alert('{% trans %}Successful autocomplete{% endtrans %}') + }, + error: function(_, _, statusMessage) { + alert('{% trans %}An error occured: {% endtrans %}' + statusMessage) + }, }) }) }) From 6fce27113ae1d7c93f8aed93c3f4708266e58658 Mon Sep 17 00:00:00 2001 From: tleb Date: Mon, 21 Oct 2019 16:52:51 +0200 Subject: [PATCH 09/14] /pedagogy/uv/create use quick notif --- core/static/core/js/script.js | 11 +++++++++-- pedagogy/templates/pedagogy/uv_create.jinja | 6 +++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/core/static/core/js/script.js b/core/static/core/js/script.js index f152525f..a8f41b31 100644 --- a/core/static/core/js/script.js +++ b/core/static/core/js/script.js @@ -38,7 +38,14 @@ $( function() { $("#quick_notif li").click(function () { $(this).hide(); }) -} ); +}); + +function createQuickNotif(msg) { + const el = document.createElement('li') + el.textContent = msg + el.addEventListener('click', () => el.parentNode.removeChild(el)) + document.getElementById('quick_notif').appendChild(el) +} function display_notif() { $('#header_notif').toggle().parent().toggleClass("white"); @@ -52,4 +59,4 @@ function display_notif() { // https://docs.djangoproject.com/en/2.0/ref/csrf/#acquiring-the-token-if-csrf-use-sessions-is-true function getCSRFToken() { return $("[name=csrfmiddlewaretoken]").val(); -} \ No newline at end of file +} diff --git a/pedagogy/templates/pedagogy/uv_create.jinja b/pedagogy/templates/pedagogy/uv_create.jinja index daeef735..533f6454 100644 --- a/pedagogy/templates/pedagogy/uv_create.jinja +++ b/pedagogy/templates/pedagogy/uv_create.jinja @@ -58,7 +58,7 @@ url: url, success: function(data, _, xhr) { if (xhr.status != 200) { - alert("{% trans %}Unknown UV code{% endtrans %}") + createQuickNotif("{% trans %}Unknown UV code{% endtrans %}") return } for (let key in data) { @@ -73,10 +73,10 @@ } } - alert('{% trans %}Successful autocomplete{% endtrans %}') + createQuickNotif('{% trans %}Successful autocomplete{% endtrans %}') }, error: function(_, _, statusMessage) { - alert('{% trans %}An error occured: {% endtrans %}' + statusMessage) + createQuickNotif('{% trans %}An error occured: {% endtrans %}' + statusMessage) }, }) }) From 419a48ac3a788255530847f5f9adc517cb09ba67 Mon Sep 17 00:00:00 2001 From: tleb Date: Mon, 21 Oct 2019 17:01:21 +0200 Subject: [PATCH 10/14] /pedagogy/uv/create put urls in settings --- api/views/uv.py | 6 +++--- sith/settings.py | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/api/views/uv.py b/api/views/uv.py index 24e72dd2..9cf46a2b 100644 --- a/api/views/uv.py +++ b/api/views/uv.py @@ -2,6 +2,7 @@ from rest_framework.response import Response from rest_framework.decorators import api_view, renderer_classes from rest_framework.renderers import JSONRenderer from django.core.exceptions import PermissionDenied +from django.conf import settings from rest_framework import serializers import urllib.request import json @@ -34,7 +35,7 @@ def find_uv(lang, year, code): full_uv is the detailed representation of an UV. """ # query the UV list - uvs_url = "https://extranet1.utbm.fr/gpedago/api/guide/uvs/{lang}/{year}" + uvs_url = settings.SITH_PEDAGOGY_UTBM_API_UVS_URL response = urllib.request.urlopen(uvs_url.format(lang=lang, year=year)) uvs = json.loads(response.read().decode("utf-8")) @@ -45,9 +46,8 @@ def find_uv(lang, year, code): return (None, None) # get detailed information about the UV - uv_url = "https://extranet1.utbm.fr/gpedago/api/guide/uv/{lang}/{year}/{code}/{formation}" response = urllib.request.urlopen( - uv_url.format( + settings.SITH_PEDAGOGY_UTBM_API_UV_URL.format( lang=lang, year=year, code=code, formation=short_uv["codeFormation"] ) ) diff --git a/sith/settings.py b/sith/settings.py index 3fe4e826..68250b47 100644 --- a/sith/settings.py +++ b/sith/settings.py @@ -445,6 +445,9 @@ SITH_PEDAGOGY_UV_RESULT_GRADE = [ ("ABS", _("Abs")), ] +SITH_PEDAGOGY_UTBM_API_UVS_URL = "https://extranet1.utbm.fr/gpedago/api/guide/uvs/{lang}/{year}" +SITH_PEDAGOGY_UTBM_API_UV_URL = "https://extranet1.utbm.fr/gpedago/api/guide/uv/{lang}/{year}/{code}/{formation}" + SITH_ECOCUP_CONS = 1152 SITH_ECOCUP_DECO = 1151 From 28bd6b8708152c20b495027012a5b4291e017b40 Mon Sep 17 00:00:00 2001 From: tleb Date: Mon, 21 Oct 2019 17:10:16 +0200 Subject: [PATCH 11/14] uv: make autofill available on edit page --- .../templates/pedagogy/{uv_create.jinja => uv_edit.jinja} | 0 pedagogy/views.py | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename pedagogy/templates/pedagogy/{uv_create.jinja => uv_edit.jinja} (100%) diff --git a/pedagogy/templates/pedagogy/uv_create.jinja b/pedagogy/templates/pedagogy/uv_edit.jinja similarity index 100% rename from pedagogy/templates/pedagogy/uv_create.jinja rename to pedagogy/templates/pedagogy/uv_edit.jinja diff --git a/pedagogy/views.py b/pedagogy/views.py index f3b02d9b..f486aa14 100644 --- a/pedagogy/views.py +++ b/pedagogy/views.py @@ -294,7 +294,7 @@ class UVCreateView(CanCreateMixin, CreateView): model = UV form_class = UVForm - template_name = "pedagogy/uv_create.jinja" + template_name = "pedagogy/uv_edit.jinja" def get_form_kwargs(self): kwargs = super(UVCreateView, self).get_form_kwargs() @@ -326,7 +326,7 @@ class UVUpdateView(CanEditPropMixin, UpdateView): model = UV form_class = UVForm pk_url_kwarg = "uv_id" - template_name = "core/edit.jinja" + template_name = "pedagogy/uv_edit.jinja" def get_form_kwargs(self): kwargs = super(UVUpdateView, self).get_form_kwargs() From 1c0d15ba2aff965a38096d540920cfff04181fcb Mon Sep 17 00:00:00 2001 From: tleb Date: Mon, 21 Oct 2019 21:17:11 +0200 Subject: [PATCH 12/14] settings: fix black report --- sith/settings.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sith/settings.py b/sith/settings.py index 68250b47..6bc270c8 100644 --- a/sith/settings.py +++ b/sith/settings.py @@ -445,8 +445,10 @@ SITH_PEDAGOGY_UV_RESULT_GRADE = [ ("ABS", _("Abs")), ] -SITH_PEDAGOGY_UTBM_API_UVS_URL = "https://extranet1.utbm.fr/gpedago/api/guide/uvs/{lang}/{year}" -SITH_PEDAGOGY_UTBM_API_UV_URL = "https://extranet1.utbm.fr/gpedago/api/guide/uv/{lang}/{year}/{code}/{formation}" +base_url = "https://extranet1.utbm.fr/gpedago/api/guide" +SITH_PEDAGOGY_UTBM_API_UVS_URL = base_url + "/uvs/{lang}/{year}" +SITH_PEDAGOGY_UTBM_API_UV_URL = base_url + "/uv/{lang}/{year}/{code}/{formation}" +del base_url SITH_ECOCUP_CONS = 1152 From 143b1288919309c55d6a04256714d70fdfbb9700 Mon Sep 17 00:00:00 2001 From: tleb Date: Mon, 21 Oct 2019 22:56:24 +0200 Subject: [PATCH 13/14] club: fix 500 on club_new --- club/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/club/views.py b/club/views.py index a5b3aef8..1f26b76e 100644 --- a/club/views.py +++ b/club/views.py @@ -451,7 +451,7 @@ class ClubEditPropView(ClubTabsMixin, CanEditPropMixin, UpdateView): current_tab = "props" -class ClubCreateView(CanEditPropMixin, CreateView): +class ClubCreateView(CanCreateMixin, CreateView): """ Create a club (for the Sith admin) """ From 5cc7eff94f4e878f74e9a8824e518349a999a228 Mon Sep 17 00:00:00 2001 From: tleb Date: Thu, 24 Oct 2019 14:18:29 +0200 Subject: [PATCH 14/14] pedagogy: uv autofill finishing touches --- api/views/uv.py | 27 ++++++++++++++--------- core/static/core/js/script.js | 7 ++++++ pedagogy/templates/pedagogy/uv_edit.jinja | 1 + sith/settings.py | 5 +---- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/api/views/uv.py b/api/views/uv.py index 9cf46a2b..d1099475 100644 --- a/api/views/uv.py +++ b/api/views/uv.py @@ -35,8 +35,8 @@ def find_uv(lang, year, code): full_uv is the detailed representation of an UV. """ # query the UV list - uvs_url = settings.SITH_PEDAGOGY_UTBM_API_UVS_URL - response = urllib.request.urlopen(uvs_url.format(lang=lang, year=year)) + uvs_url = settings.SITH_PEDAGOGY_UTBM_API + "/uvs/{}/{}".format(lang, year) + response = urllib.request.urlopen(uvs_url) uvs = json.loads(response.read().decode("utf-8")) try: @@ -46,11 +46,10 @@ def find_uv(lang, year, code): return (None, None) # get detailed information about the UV - response = urllib.request.urlopen( - settings.SITH_PEDAGOGY_UTBM_API_UV_URL.format( - lang=lang, year=year, code=code, formation=short_uv["codeFormation"] - ) + uv_url = settings.SITH_PEDAGOGY_UTBM_API + "/uv/{}/{}/{}/{}".format( + lang, year, code, short_uv["codeFormation"] ) + response = urllib.request.urlopen(uv_url) full_uv = json.loads(response.read().decode("utf-8")) return (short_uv, full_uv) @@ -112,9 +111,17 @@ def make_clean_uv(short_uv, full_uv): res["title"] = full_uv["libelle"] - res["objectives"] = full_uv["objectifs"] - res["program"] = full_uv["programme"] - res["skills"] = full_uv["acquisitionCompetences"] - res["key_concepts"] = full_uv["acquisitionNotions"] + descriptions = { + "objectives": "objectifs", + "program": "programme", + "skills": "acquisitionCompetences", + "key_concepts": "acquisitionNotions", + } + + for res_key, full_uv_key in descriptions.items(): + res[res_key] = full_uv[full_uv_key] + # if not found or the API did not return a string + if type(res[res_key]) != str: + res[res_key] = "" return res diff --git a/core/static/core/js/script.js b/core/static/core/js/script.js index a8f41b31..671785fe 100644 --- a/core/static/core/js/script.js +++ b/core/static/core/js/script.js @@ -47,6 +47,13 @@ function createQuickNotif(msg) { document.getElementById('quick_notif').appendChild(el) } +function deleteQuickNotifs() { + const el = document.getElementById('quick_notif') + while (el.firstChild) { + el.removeChild(el.firstChild) + } +} + function display_notif() { $('#header_notif').toggle().parent().toggleClass("white"); } diff --git a/pedagogy/templates/pedagogy/uv_edit.jinja b/pedagogy/templates/pedagogy/uv_edit.jinja index 533f6454..a47e10e6 100644 --- a/pedagogy/templates/pedagogy/uv_edit.jinja +++ b/pedagogy/templates/pedagogy/uv_edit.jinja @@ -52,6 +52,7 @@ year-- } const url = "{{ url('api:uv_endpoint') }}?year=" + year + "&code=" + codeInput.value + deleteQuickNotifs() $.ajax({ dataType: "json", diff --git a/sith/settings.py b/sith/settings.py index 6bc270c8..75fd63e8 100644 --- a/sith/settings.py +++ b/sith/settings.py @@ -445,10 +445,7 @@ SITH_PEDAGOGY_UV_RESULT_GRADE = [ ("ABS", _("Abs")), ] -base_url = "https://extranet1.utbm.fr/gpedago/api/guide" -SITH_PEDAGOGY_UTBM_API_UVS_URL = base_url + "/uvs/{lang}/{year}" -SITH_PEDAGOGY_UTBM_API_UV_URL = base_url + "/uv/{lang}/{year}/{code}/{formation}" -del base_url +SITH_PEDAGOGY_UTBM_API = "https://extranet1.utbm.fr/gpedago/api/guide" SITH_ECOCUP_CONS = 1152