Utilise nouvelle API. Presentation index. Logo.

This commit is contained in:
Ilona 2025-01-08 16:45:07 +01:00
parent 4f55017b6f
commit 694c21a254
8 changed files with 111 additions and 23 deletions

View File

@ -4,7 +4,6 @@ import time
from flask import current_app, g, render_template, request
from flask import Flask
from scodoc.api import APIError, ScoDocAuthError
from config import DevConfig
@ -48,6 +47,8 @@ def handle_sco_auth_error(exc):
def create_app(config_class=DevConfig):
from scodoc.api import APIError, ScoDocAuthError
app = Flask(__name__, static_url_path="/AutoSco/static", static_folder="static")
app.config.from_object(config_class)
app.wsgi_app = ReverseProxied(app.wsgi_app)

BIN
app/static/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View File

@ -13,9 +13,27 @@
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
font-size: 14pt;
margin: 8px;
padding: 0;
}
header {
display: grid;
justify-content: center;
margin-bottom: 16px;
}
div.titre1 {
font-size: 1.5em;
font-weight: bold;
margin-top: 12px;
}
.centered-description {
display: grid;
justify-content: center;
grid-template-columns: 1fr;
text-align: center;
}
</style>
{%- endblock styles %}
@ -23,6 +41,11 @@
</head>
<body{% block body_attribs %}{% endblock body_attribs %}>
{% block body -%}
{%- block app_header %}
<header>
<a href="/"><img src="/AutoSco/static/logo.png" alt="Espace Langues - USPN" height="80px"/></a>
</header>
{%- endblock app_header %}
{% block navbar %}
{%- endblock navbar %}
{% block content -%}

View File

@ -5,13 +5,6 @@
{{super()}}
<style>
.centered-description {
display: grid;
justify-content: center;
grid-template-columns: 1fr;
text-align: center;
}
div.titre {
font-size: 1.5em;
font-weight: bold;

View File

@ -1,16 +1,64 @@
{# Page accueil #}
{% extends 'base.j2' %}
{% block styles %}
{{super()}}
<style>
div.sem {
margin-top: 8px;
margin-bottom: 8px;
border-radius: 8px;
padding: 8px;
background-color: blanchedalmond;
}
div.sem.ouvert {
background-color: lightgreen;
}
.sem a, .sem a:visited {
text-decoration: none;
color: #025AA7;
}
.sem a:hover {
text-decoration: underline;
}
.dates, .date-limite {
color:darkolivegreen;
font-size: 80%;
}
.date-limite {
color: red;
}
</style>
{% endblock %}
{% block content %}
<h1>AutoSco - Accueil</h1>
<div class="titre1">Cours ouverts</div>
<div>
{% for sem in sems %}
<div class="sem">
{{sem.date_debut}} : <a href="{{
<div class="sem {% if sem.autosco.inscription_autorisee %}ouvert{% else %}ferme{% endif %}">
<a href="{{
url_for('autosco.formsemestre_description', formsemestre_id=sem.formsemestre_id )
}}">{{sem.titre}}</a>
<span class="dates">cours du {{sem.date_debut}} au {{sem.date_fin}}</span>
{% if sem.descr.date_fin_inscriptions is not none %}
<span class="date-limite">fermeture des inscriptions le {{sem.descr.date_fin_inscriptions|format_date}}</span>
{% endif %}
{% if sem.autosco.inscription_autorisee %}
<div class="inscription">
{% if sem.autosco.nb_dispo is not none %}
<span>{{ sem.autosco.nb_dispo }} places disponibles :</span>
{% endif %}
<a href="{{url_for('autosco.formsemestre_inscription', formsemestre_id=sem.formsemestre_id )}}">
s'inscrire
</a>
</div>
{% endif %}
</div>
{% endfor %}
</div>

View File

@ -11,17 +11,18 @@ from scodoc import api
@bp.route("/")
def index():
annee_scolaire = scu.annee_scolaire()
sems = api.get(f"/formsemestres/query?annee_scolaire={annee_scolaire}")
# nb: l'utilisaton de l'API départementale permet de n'avoir
sems = api.get(f"/formsemestres/with_description/query?annee_scolaire={annee_scolaire}")
# nb: l'utilisation de l'API départementale permet de n'avoir
# que les semestres du département configuré.
# Ne retient que les semestres ayant une description et étant visibles
sems = [ s for s in sems if s["autosco"] and s["autosco"]["visible"] ]
return render_template("index.j2", sems=sems)
@bp.route("/formdescription/<int:formsemestre_id>")
def formsemestre_description(formsemestre_id:int):
"""Page description d'un formsemestre (=d'un cours)"""
sem = api.get(f"/formsemestre/{formsemestre_id}")
sem["descr"] = api.get(f"/formsemestre/{formsemestre_id}/description")
sem = api.get(f"/formsemestre/{formsemestre_id}/with_description")
return render_template("formsemestre_description.j2", sem=sem)
@bp.route("/formsemestre/<int:formsemestre_id>/description/photo_ens")
@ -38,3 +39,8 @@ def formsemestre_get_photo_ens(formsemestre_id: int):
r = make_response(response.content)
r.headers["Content-Type"] = content_type
return r
@bp.route("/formsemestre/<int:formsemestre_id>/inscription")
def formsemestre_inscription(formsemestre_id: int):
"""Formulaire d'auto-inscription étudiant"""
return "Formulaire d'auto-inscription étudiant" # TODO

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""Application Flask: AutoSco"""
import os
import datetime
from pprint import pprint as pp
import click
@ -44,6 +44,15 @@ def make_shell_context():
"pp": pp,
}
@app.template_filter()
def format_date(value:str|datetime.datetime):
"""Format a date dd/mm/yyyy"""
if isinstance(value, str):
value = datetime.datetime.fromisoformat(value)
return value.strftime("%d/%m/%Y")
# Start using:
# flask run -p 5001 --host 0.0.0.0 --debug

View File

@ -3,7 +3,10 @@
import os
import requests
from flask import current_app
from app import log
import config
@ -22,12 +25,17 @@ class ScoDocAuthError(APIError):
def get_auth_headers(user: str, password: str, conf: config.Config) -> dict:
"Demande de jeton, dict à utiliser dans les en-têtes de requêtes http"
ans = requests.post(
conf["API_URL"] + "/tokens",
auth=(user, password),
timeout=conf["API_TIMEOUT"],
)
try:
ans = requests.post(
conf["API_URL"] + "/tokens",
auth=(user, password),
timeout=conf["API_TIMEOUT"],
)
except requests.exceptions.ConnectionError as exc:
log(f"get_auth_headers: error: user={user}, url='{conf['API_URL']}/tokens'")
raise ScoDocAuthError(f"Impossible de se connecter à ScoDoc: problème de configuration?", exc)
if ans.status_code != 200:
log(f"get_auth_headers: error: user={user}, answer status={ans.status_code}")
raise ScoDocAuthError(f"Echec demande jeton par {user}", status_code=ans.status_code)
token = ans.json()["token"]
return {"Authorization": f"Bearer {token}"}