mirror of
https://github.com/ae-utbm/sith.git
synced 2024-10-31 19:38:04 +00:00
Compare commits
No commits in common. "42055b9001ce6adb9b7b6313d14d7fc657f31e98" and "28077ef0b0b47aac939b99efaf9b02f3df970506" have entirely different histories.
42055b9001
...
28077ef0b0
@ -53,5 +53,4 @@ urlpatterns = [
|
|||||||
re_path(r"^login/", include("rest_framework.urls", namespace="rest_framework")),
|
re_path(r"^login/", include("rest_framework.urls", namespace="rest_framework")),
|
||||||
re_path(r"^markdown$", RenderMarkdown, name="api_markdown"),
|
re_path(r"^markdown$", RenderMarkdown, name="api_markdown"),
|
||||||
re_path(r"^mailings$", FetchMailingLists, name="mailings_fetch"),
|
re_path(r"^mailings$", FetchMailingLists, name="mailings_fetch"),
|
||||||
re_path(r"^uv$", uv_endpoint, name="uv_endpoint"),
|
|
||||||
]
|
]
|
||||||
|
@ -77,4 +77,3 @@ from .user import *
|
|||||||
from .club import *
|
from .club import *
|
||||||
from .group import *
|
from .group import *
|
||||||
from .launderette import *
|
from .launderette import *
|
||||||
from .uv import *
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.decorators import api_view, renderer_classes
|
from rest_framework.decorators import api_view, renderer_classes
|
||||||
from rest_framework.renderers import StaticHTMLRenderer
|
from rest_framework.renderers import StaticHTMLRenderer
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
from core.templatetags.renderer import markdown
|
from core.templatetags.renderer import markdown
|
||||||
|
|
||||||
|
127
api/views/uv.py
127
api/views/uv.py
@ -1,127 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
from pedagogy.views import CanCreateUVFunctionMixin
|
|
||||||
|
|
||||||
|
|
||||||
@api_view(["GET"])
|
|
||||||
@renderer_classes((JSONRenderer,))
|
|
||||||
def uv_endpoint(request):
|
|
||||||
if 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 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.
|
|
||||||
"""
|
|
||||||
# query the UV list
|
|
||||||
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:
|
|
||||||
# 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 = 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)
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
semester = full_uv.get("automne", None)
|
|
||||||
if not semester:
|
|
||||||
semester = full_uv.get("printemps", {})
|
|
||||||
res["manager"] = semester.get("responsable", "")
|
|
||||||
|
|
||||||
res["title"] = full_uv["libelle"]
|
|
||||||
|
|
||||||
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
|
|
@ -38,7 +38,7 @@ def get_cached_user(request):
|
|||||||
if not hasattr(request, "_cached_user"):
|
if not hasattr(request, "_cached_user"):
|
||||||
user = get_user(request)
|
user = get_user(request)
|
||||||
if user.is_anonymous:
|
if user.is_anonymous:
|
||||||
user = AnonymousUser()
|
user = AnonymousUser(request)
|
||||||
|
|
||||||
request._cached_user = user
|
request._cached_user = user
|
||||||
|
|
||||||
|
@ -659,7 +659,7 @@ class User(AbstractBaseUser):
|
|||||||
|
|
||||||
|
|
||||||
class AnonymousUser(AuthAnonymousUser):
|
class AnonymousUser(AuthAnonymousUser):
|
||||||
def __init__(self):
|
def __init__(self, request):
|
||||||
super(AnonymousUser, self).__init__()
|
super(AnonymousUser, self).__init__()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -40,20 +40,6 @@ $( function() {
|
|||||||
})
|
})
|
||||||
} );
|
} );
|
||||||
|
|
||||||
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 deleteQuickNotifs() {
|
|
||||||
const el = document.getElementById('quick_notif')
|
|
||||||
while (el.firstChild) {
|
|
||||||
el.removeChild(el.firstChild)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function display_notif() {
|
function display_notif() {
|
||||||
$('#header_notif').toggle().parent().toggleClass("white");
|
$('#header_notif').toggle().parent().toggleClass("white");
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,86 +0,0 @@
|
|||||||
{% extends "core/base.jinja" %}
|
|
||||||
|
|
||||||
{% block title %}
|
|
||||||
{% trans %}Edit UV{% endtrans %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<h2>{% trans %}Edit UV{% endtrans %}</h2>
|
|
||||||
<form action="" method="post" enctype="multipart/form-data" id="uv_edit">
|
|
||||||
{% csrf_token %}
|
|
||||||
{{ form.non_field_errors() }}
|
|
||||||
|
|
||||||
{% for field in form %}
|
|
||||||
|
|
||||||
{% if field.is_hidden %}
|
|
||||||
|
|
||||||
{{ field }}
|
|
||||||
|
|
||||||
{% else %}
|
|
||||||
<p>
|
|
||||||
{{ field.errors }}
|
|
||||||
<label for="{{ field.name }}">{{ field.label }}</label>
|
|
||||||
{{ field }}
|
|
||||||
|
|
||||||
|
|
||||||
{% if field.name == 'code' %}
|
|
||||||
<button type="button" id="autofill">{% trans %}Import from UTBM{% endtrans %}</button>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
|
|
||||||
<p><input type="submit" value="{% trans %}Update{% endtrans %}" /></p>
|
|
||||||
</form>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block script %}
|
|
||||||
{{ super() }}
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
const autofillBtn = document.getElementById('autofill')
|
|
||||||
const codeInput = document.querySelector('input[name="code"]')
|
|
||||||
|
|
||||||
autofillBtn.addEventListener('click', () => {
|
|
||||||
const today = new Date()
|
|
||||||
let year = today.getFullYear()
|
|
||||||
if (today.getMonth() < 7) { // student year starts in september
|
|
||||||
year--
|
|
||||||
}
|
|
||||||
const url = "{{ url('api:uv_endpoint') }}?year=" + year + "&code=" + codeInput.value
|
|
||||||
deleteQuickNotifs()
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
dataType: "json",
|
|
||||||
url: url,
|
|
||||||
success: function(data, _, xhr) {
|
|
||||||
if (xhr.status != 200) {
|
|
||||||
createQuickNotif("{% 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]
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
createQuickNotif('{% trans %}Successful autocomplete{% endtrans %}')
|
|
||||||
},
|
|
||||||
error: function(_, _, statusMessage) {
|
|
||||||
createQuickNotif('{% trans %}An error occured: {% endtrans %}' + statusMessage)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
@ -294,7 +294,7 @@ class UVCreateView(CanCreateMixin, CreateView):
|
|||||||
|
|
||||||
model = UV
|
model = UV
|
||||||
form_class = UVForm
|
form_class = UVForm
|
||||||
template_name = "pedagogy/uv_edit.jinja"
|
template_name = "core/edit.jinja"
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
kwargs = super(UVCreateView, self).get_form_kwargs()
|
kwargs = super(UVCreateView, self).get_form_kwargs()
|
||||||
@ -326,7 +326,7 @@ class UVUpdateView(CanEditPropMixin, UpdateView):
|
|||||||
model = UV
|
model = UV
|
||||||
form_class = UVForm
|
form_class = UVForm
|
||||||
pk_url_kwarg = "uv_id"
|
pk_url_kwarg = "uv_id"
|
||||||
template_name = "pedagogy/uv_edit.jinja"
|
template_name = "core/edit.jinja"
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
kwargs = super(UVUpdateView, self).get_form_kwargs()
|
kwargs = super(UVUpdateView, self).get_form_kwargs()
|
||||||
|
@ -196,8 +196,6 @@ SASS_PRECISION = 8
|
|||||||
|
|
||||||
WSGI_APPLICATION = "sith.wsgi.application"
|
WSGI_APPLICATION = "sith.wsgi.application"
|
||||||
|
|
||||||
REST_FRAMEWORK = {}
|
|
||||||
|
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
|
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
|
||||||
@ -254,7 +252,6 @@ LOGOUT_URL = "/logout"
|
|||||||
LOGIN_REDIRECT_URL = "/"
|
LOGIN_REDIRECT_URL = "/"
|
||||||
DEFAULT_FROM_EMAIL = "bibou@git.an"
|
DEFAULT_FROM_EMAIL = "bibou@git.an"
|
||||||
SITH_COM_EMAIL = "bibou_com@git.an"
|
SITH_COM_EMAIL = "bibou_com@git.an"
|
||||||
REST_FRAMEWORK["UNAUTHENTICATED_USER"] = "core.models.AnonymousUser"
|
|
||||||
|
|
||||||
# Email
|
# Email
|
||||||
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
|
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
|
||||||
@ -445,8 +442,6 @@ SITH_PEDAGOGY_UV_RESULT_GRADE = [
|
|||||||
("ABS", _("Abs")),
|
("ABS", _("Abs")),
|
||||||
]
|
]
|
||||||
|
|
||||||
SITH_PEDAGOGY_UTBM_API = "https://extranet1.utbm.fr/gpedago/api/guide"
|
|
||||||
|
|
||||||
SITH_ECOCUP_CONS = 1152
|
SITH_ECOCUP_CONS = 1152
|
||||||
|
|
||||||
SITH_ECOCUP_DECO = 1151
|
SITH_ECOCUP_DECO = 1151
|
||||||
|
Loading…
Reference in New Issue
Block a user