Gros progrès, statistiques 80%, reste à faire le school-info

This commit is contained in:
The17thDoctor 2023-03-31 00:49:11 +02:00
parent 71e3c478dc
commit 0fc09ae416
21 changed files with 4427 additions and 1180 deletions

View File

@ -9,32 +9,127 @@
<p>Moyenne des admis<span class="is-pulled-right">{state.average}</span></p>
<p>Nombre de formations<span class="is-pulled-right">{state.courseNumber}</span></p>
<p>Capacité<span class="is-pulled-right">{state.capacity}</span></p>
<p>Sélectivité</p>
<title-progress title={"Sélectivité"} value={state.selectivity} max="100"></title-progress>
</div>
<div class="m-4">
<line-graph title="Répartition par genre" style="height: 6rem;"></line-graph>
<line-graph title="Répartition par genre" data={state.genreStats} style="height: 6rem;"></line-graph>
</div>
<div class="m-4">
<line-graph title="Répartition par bac" style="height: 6rem;"></line-graph>
<line-graph title="Répartition par bac" data={state.bacStats} style="height: 6rem;"></line-graph>
</div>
<div class="m-4">
<line-graph title="Répartition par mention au bac" style="height: 6rem;"></line-graph>
<line-graph title="Répartition par mention au bac" data={state.mentionStats} style="height: 6rem;"></line-graph>
</div>
</div>
<script>
export default {
onBeforeMount(props, state) {
this.state = {
state = {
average: 0,
capacity: 0,
selectivity: 0,
courseNumber: 0
courseNumber: 0,
bacStats: [],
genreStats: [],
mentionStats: []
}
},
onUpdated(props, state) {
onBeforeUpdate(props, state) {
if (!props.schoolList || !props.schoolList.length) return
let list = props.schoolList
let avg = list.reduce((s, e) => s + e.fields.moyenne, 0) / list.length
let avgCap = list.reduce((s, e) => s + e.fields.capa_fin, 0) / list.length
let avgSlc = list.reduce((s, e) => s + (e.fields.taux_acces_ens || 0), 0) / list.filter((e) => e.fields.taux_acces_ens).length
state.courseNumber = list.length
state.average = Math.round(avg * 100) / 100
state.capacity = Math.floor(avgCap)
state.selectivity = Math.floor(avgSlc)
let pctFemmes = Math.round(list.reduce((s, e) => s + (e.fields.pct_f || 0), 0) / list.filter((e) => e.fields.pct_f).length)
console.log(pctFemmes)
state.genreStats = [
{
name: "Hommes",
short: "H",
value: (100 - pctFemmes)
},
{
name: "Femmes",
short: "F",
value: pctFemmes
},
]
let pctBG = Math.round(list.reduce((s, e) => s + (e.fields.part_acces_gen || 0), 0) / list.filter((e) => e.fields.part_acces_gen).length)
let pctBT = Math.round(list.reduce((s, e) => s + (e.fields.part_acces_tec || 0), 0) / list.filter((e) => e.fields.part_acces_tec).length)
let pctBP = Math.round(list.reduce((s, e) => s + (e.fields.part_acces_pro || 0), 0) / list.filter((e) => e.fields.part_acces_pro).length)
state.bacStats = [
{
name: "Général",
short: "Gen.",
value: pctBG
},
{
name: "Technologique",
short: "Tech.",
value: pctBT
},
{
name: "Professionnel",
short: "Pro.",
value: pctBP
},
{
name: "Autre",
short: "Au.",
value: 100 - (pctBG + pctBT + pctBP)
}
]
let pctSM = Math.round(list.reduce((s, e) => s + e.fields.pct_sansmention, 0) / list.length)
let pctAB = Math.round(list.reduce((s, e) => s + e.fields.pct_ab, 0) / list.length)
let pctB = Math.round(list.reduce((s, e) => s + e.fields.pct_b, 0) / list.length)
let pctTB = Math.round(list.reduce((s, e) => s + e.fields.pct_tb, 0) / list.length)
let pctTBF = Math.round(list.reduce((s, e) => s + e.fields.pct_tbf, 0) / list.length)
state.mentionStats = [
{
name: "Sans Mention",
short: "SM",
value: pctSM
},
{
name: "Assez Bien",
short: "AB",
value: pctAB
},
{
name: "Bien",
short: "B",
value: pctB
},
{
name: "Très Bien",
short: "TB",
value: pctTB
},
{
name: "Très Bien + Félicitations",
short: "TBF",
value: pctTBF
},
{
name: "Non Spécifié",
short: "NS",
value: 100 - (pctSM + pctAB + pctB + pctTB + pctTBF)
}
]
}
}
</script>

View File

@ -10,7 +10,7 @@
updateCanvas() {
let canvas = this.$("canvas")
if (!canvas) return
if (!canvas || !this.props.data || !this.props.title) return
canvas.width = canvas.clientWidth
canvas.height = canvas.clientHeight
@ -23,13 +23,14 @@
let height = canvas.height
let spacing = 1
let data = this.state.data
let data = this.props.data
let colors = [
"#003F5C",
"#2F4B7C",
"#665191",
"#A05195",
"#D45087"
"#D45087",
"#D47150"
]
cx.clearRect(0, 0, width, height)
@ -48,9 +49,10 @@
let counter = 0
let legendWidth = 0
for (let field of data) {
if (field.value == 0) continue
let start = curr + spacing
let barWidth = field.value / total * width - spacing * 2
let text = `${Math.round(field.value / total * 1000) / 10}% (${field.name})`
let text = `${Math.round(field.value / total * 1000) / 10}% (${field.short || field.name})`
cx.fillStyle = colors[counter]
cx.fillRect(start, 0, barWidth, height / 3)
@ -58,14 +60,15 @@
cx.fillStyle = "#FFFFFF"
if (cx.measureText(text).width < barWidth) {
cx.fillText(text, start + barWidth / 2, height / 6)
} else if (cx.measureText("...").width < barWidth) {
cx.fillText("...", start + barWidth / 2, height / 6)
} else if (cx.measureText(`${Math.round(field.value / total * 1000) / 10}%`).width < barWidth) {
cx.fillText(`${Math.round(field.value / total * 1000) / 10}%`, start + barWidth / 2, height / 6)
}
curr += field.value / total * width
counter++
legendWidth += cx.measureText(field.name).width + 25 + 15 // += textWidth + squareWidth + margin
let legendText = field.name + (field.short ? ` (${field.short})` : "")
legendWidth += cx.measureText(legendText).width + 25 + 15
}
cx.textAlign = "left"
@ -74,20 +77,18 @@
counter = 0
for (let field of data) {
if (field.value == 0) continue
cx.fillStyle = colors[counter]
cx.fillRect(0, 0, 25, 25)
cx.fillStyle = "#707070"
cx.fillText(field.name, 30, 12.5)
cx.translate(cx.measureText(field.name).width + 25 + 15, 0)
let legendText = field.name + (field.short ? ` (${field.short})` : "")
cx.fillText(legendText, 30, 12.5)
cx.translate(cx.measureText(legendText).width + 25 + 15, 0)
counter++
}
},
state: {
data: [],
title: "Example"
},
onMounted() {
let canvas = this.$("canvas")
this.updateCanvas()

View File

@ -8,28 +8,96 @@
</div>
<div class="column">
<fili-info course={state.course} shouldShowInfos={state.shouldShowInfos}></fili-info>
<school parentUpdate={state.updating} course={state.course} shouldShowInfos={state.shouldShowInfos}></school>
<fili-info schoolList={state.schoolList} course={state.course} shouldShowInfos={state.shouldShowInfos}></fili-info>
<school sortList={sortList} schoolList={state.schoolList} sortFields={state.sortFields} course={state.course} shouldShowInfos={state.shouldShowInfos}></school>
</div>
</div>
<school-info></school-info>
<script>
export default {
onBeforeMount(props, state) {
//Initial state
this.state = {
course: null,
updating: false,
shouldShowInfos: false
import PAPI from '../javascript/parcoursup-link.js'
const SORT_TABLE = [
{name: "Nom", id: "g_ea_lib_vx"},
{name: "Ville", id: "ville_etab"},
{name: "Département", id: "dep"},
{name: "Moyenne", id: "moyenne"},
{name: "Sélectivité", id: "taux_acces_ens"}
]
export default {
sortList(sortBy) {
//Si la liste est déjà triée par la bonne catégorie, on l'inverse
if (sortBy == this.state.sortBy) {
this.state.schoolList.reverse()
}
//Sinon on l'ordonne par la nouvelle catégorie (ascendant par défaut)
else {
this.state.sortBy = sortBy
switch (sortBy) {
case SORT_TABLE[3].id:
case SORT_TABLE[4].id: {
this.state.schoolList.sort((a, b) => {
if (a.fields[sortBy] > b.fields[sortBy]) return 1
else return -1
})
break
}
default: {
this.state.schoolList.sort((a, b) => {
return (a.fields[sortBy]).localeCompare(b.fields[sortBy])
})
break
}
}
}
this.update({
schoolList: this.state.schoolList
})
},
updateList(course) {
course = course || this.state.course
PAPI.fetchEtablissement(course.fili, course.sousfili, course.soussousfili).then((response) => {
response.forEach(etablissement => {
// calcul la moyenne
let pct_sansmention = etablissement.fields.pct_sansmention
let pct_AB = etablissement.fields.pct_ab
let pct_B = etablissement.fields.pct_b
let pct_TB = etablissement.fields.pct_tb
let pct_TBF = etablissement.fields.pct_tbf
// On prend la moyenne des moyennes comprises dans la mention
// Exemple : Assez bien est entre 12 et 14 donc 13.
etablissement.fields.moyenne = ((pct_TBF*19)+(pct_TB*17)+(pct_B*15)+(pct_AB*13)+(pct_sansmention*11))/100
})
this.update({
schoolList: response
})
})
},
updateCourse(course){
this.updateList(course)
this.update({
course: course,
sortFields: SORT_TABLE,
shouldShowInfos: course != null,
updating: !this.state.updating
})
},
onMounted(props, state) {
this.update({
course: null,
sortBy: null,
schoolList: null,
sortFields: SORT_TABLE,
shouldShowInfos: false
})
}
}

View File

@ -1,6 +1,6 @@
<school>
<div if={props.shouldShowInfos} class="box p-2 m-2">
<iframe width="100%" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0"
<div if={props.shouldShowInfos} class="box p-2 m-2" disabled="true">
<iframe if={false} width="100%" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0"
src="https://www.openstreetmap.org/export/embed.html?bbox=-14.655761718750002%2C40.56389453066509%2C13.601074218750002%2C51.754240074033525&amp;layer=mapnik"
style="border-radius: 5px;"></iframe>
<br>
@ -13,115 +13,23 @@
<table class="table is-fullwidth is-hoverable">
<thead>
<tr>
<th each={sortField in state.sortFields}>
<th each={sortField in props.sortFields}>
{sortField.name}
<a id={sortField.id} onclick={() => sortList(sortField.id)}>
<a id={sortField.id} onclick={() => props.sortList(sortField.id)}>
<span class="icon"><i class="fas fa-sort"></i></span>
</a>
</th>
</tr>
</thead>
<tbody>
<tr each={etablissement in state.items}>
<td>{etablissement.fields.g_ea_lib_vx}</td>
<td>{etablissement.fields.ville_etab}</td>
<td>{etablissement.fields.dep}</td>
<td>{etablissement.fields.moyenne}</td>
<td>{etablissement.fields.taux_acces_ens}</td>
<tr each={school in props.schoolList}>
<td>{school.fields.g_ea_lib_vx}</td>
<td>{school.fields.ville_etab}</td>
<td>{school.fields.dep}</td>
<td>{school.fields.moyenne}</td>
<td><title-progress value={school.fields.taux_acces_ens} max="100" style="margin: auto"></title-progress></td>
</tr>
</tbody>
</table>
</div>
<script>
import PAPI from '../javascript/parcoursup-link.js'
async function fetchEtablissement(course) {
return PAPI.fetchEtablissement(course.fili, course.sousfili, course.soussousfili);
}
const SORT_TABLE = [
{name: "Nom", id: "g_ea_lib_vx"},
{name: "Ville", id: "ville_etab"},
{name: "Département", id: "dep"},
{name: "Moyenne", id: "moyenne"},
{name: "Sélectivité", id: "taux_acces_ens"}
]
export default function search() {
return {
updateList() {
fetchEtablissement(this.props.course).then((response) => {
response.forEach(etablissement => {
// calcul la moyenne
let pct_sansmention = etablissement.fields.pct_sansmention
let pct_AB = etablissement.fields.pct_ab
let pct_B = etablissement.fields.pct_b
let pct_TB = etablissement.fields.pct_tb
let pct_TBF = etablissement.fields.pct_tbf
// On prend la moyenne des moyennes comprises dans la mention
// Exemple : Assez bien est entre 12 et 14 donc 13.
etablissement.fields.moyenne = ((pct_TBF*19)+(pct_TB*17)+(pct_B*15)+(pct_AB*13)+(pct_sansmention*11))/100
})
this.update({
items: response,
parentUpdate: this.props.parentUpdate
})
})
},
sortList(sortBy) {
//Si la liste est déjà triée par la bonne catégorie, on l'inverse
if (sortBy == this.state.sortBy) {
this.state.items.reverse()
}
//Sinon on l'ordonne par la nouvelle catégorie (ascendant par défaut)
else {
this.state.sortBy = sortBy
switch (sortBy) {
case SORT_TABLE[3].id:
case SORT_TABLE[4].id: {
this.state.items.sort((a, b) => {
if (a.fields[sortBy] > b.fields[sortBy]) return 1
else return -1
})
break
}
default: {
this.state.items.sort((a, b) => {
return (a.fields[sortBy]).localeCompare(b.fields[sortBy])
})
break
}
}
}
this.update({
items: this.state.items
})
},
onBeforeMount(props, state) {
state = {
items: null,
breakCycle: false,
sortBy: null,
parentUpdate: null,
sortFields: null
}
},
onMounted(props, state) {
this.update({
sortFields: SORT_TABLE
})
},
onUpdated(props, state) {
if (!props.shouldShowInfos || state.parentUpdate == props.parentUpdate) return
this.updateList()
}
}
}
</script>
</school>

View File

@ -38,7 +38,7 @@
promise = PAPI.fetchFiliere(this.state.course.fili)
break
case 2:
promise = PAPI.fetchSpecialites(this.state.course.sousfili)
promise = PAPI.fetchSpecialites(this.state.course.fili, this.state.course.sousfili)
break
default:

View File

@ -0,0 +1,49 @@
<title-progress>
<div style="display: flex;">
<span if={props.title}>{props.title}</span>
<span class="ml-1">{calcPct()}</span>
<progress value={props.value} max={props.max} class={state.class} style="box-shadow: 0 0.5em 1em -0.125em rgb(10 10 10 / 10%), 0 0 0 1px rgb(10 10 10 / 2%);"></progress>
</div>
<script>
const DEFAULT_CLASSES = "progress is-small m-2 mt-auto mb-auto"
const COLOR_CLASSES = [
"is-link",
"is-info",
"is-success",
"is-warning",
"is-danger"
]
export default {
computeClasses() {
if (!this.props.value) return DEFAULT_CLASSES
let n = Math.floor(this.props.value / 20)
if (n == 5) n = 4
return DEFAULT_CLASSES + " " + COLOR_CLASSES[n]
},
calcPct() {
if (!this.props.value) {
return "???"
} else {
return Math.round(this.props.value / this.props.max * 100) + "%"
}
},
onMounted(props, state) {
this.update({
class: this.computeClasses()
})
},
onBeforeUpdate(props, state) {
state.class = this.computeClasses()
}
}
</script>
</title-progress>

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

View File

@ -1,11 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title>Parcoursup</title>
<title>Parcourplus | Accueil</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" href="style/parcoursup.css">
<script src="riot.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.9.3/css/bulma.min.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" integrity="sha512-q3eWabyZPc1XTCmF+8/LuE1ozpg5xxn7iO89yfSOd5/oKvyqLngoNGsx8jq92Y8eXJ/IRxQbEC+FGSYxtk2oiw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="loader.js" type="module"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/riot/7.1.0/riot+compiler.min.js" integrity="sha512-sSGKGR9MvL0bUx3CScaBb56crXwspwDkL/JnB0IrLFQfw3uvSUlITQtsTtDZctshhv5wdwIt+qZeN8zThRF4Dw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

File diff suppressed because one or more lines are too long

View File

@ -3,7 +3,7 @@ var lineGraph = {
exports: {
updateCanvas() {
let canvas = this.$("canvas");
if (!canvas) return;
if (!canvas || !this.props.data || !this.props.title) return;
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
let cx = canvas.getContext("2d");
@ -12,8 +12,8 @@ var lineGraph = {
let width = canvas.width;
let height = canvas.height;
let spacing = 1;
let data = this.state.data;
let colors = ["#003F5C", "#2F4B7C", "#665191", "#A05195", "#D45087"];
let data = this.props.data;
let colors = ["#003F5C", "#2F4B7C", "#665191", "#A05195", "#D45087", "#D47150"];
cx.clearRect(0, 0, width, height);
cx.resetTransform();
if (!data) return;
@ -27,39 +27,38 @@ var lineGraph = {
let counter = 0;
let legendWidth = 0;
for (let field of data) {
if (field.value == 0) continue;
let start = curr + spacing;
let barWidth = field.value / total * width - spacing * 2;
let text = `${Math.round(field.value / total * 1000) / 10}% (${field.name})`;
let text = `${Math.round(field.value / total * 1000) / 10}% (${field.short || field.name})`;
cx.fillStyle = colors[counter];
cx.fillRect(start, 0, barWidth, height / 3);
cx.fillStyle = "#FFFFFF";
if (cx.measureText(text).width < barWidth) {
cx.fillText(text, start + barWidth / 2, height / 6);
} else if (cx.measureText("...").width < barWidth) {
cx.fillText("...", start + barWidth / 2, height / 6);
} else if (cx.measureText(`${Math.round(field.value / total * 1000) / 10}%`).width < barWidth) {
cx.fillText(`${Math.round(field.value / total * 1000) / 10}%`, start + barWidth / 2, height / 6);
}
curr += field.value / total * width;
counter++;
legendWidth += cx.measureText(field.name).width + 25 + 15; // += textWidth + squareWidth + margin
let legendText = field.name + (field.short ? ` (${field.short})` : "");
legendWidth += cx.measureText(legendText).width + 25 + 15;
}
cx.textAlign = "left";
legendWidth -= 15; //On enlève la dernière marge
cx.translate(width / 2 - legendWidth / 2, height / 4 + 20);
counter = 0;
for (let field of data) {
if (field.value == 0) continue;
cx.fillStyle = colors[counter];
cx.fillRect(0, 0, 25, 25);
cx.fillStyle = "#707070";
cx.fillText(field.name, 30, 12.5);
cx.translate(cx.measureText(field.name).width + 25 + 15, 0);
let legendText = field.name + (field.short ? ` (${field.short})` : "");
cx.fillText(legendText, 30, 12.5);
cx.translate(cx.measureText(legendText).width + 25 + 15, 0);
counter++;
}
},
state: {
data: [],
title: "Example"
},
onMounted() {
let canvas = this.$("canvas");
this.updateCanvas();

View File

@ -1,23 +1,134 @@
/*
Parcoursup API (PAPI)
Comprend un set de wrapper afin d'accéder plus aisément aux informations de l'API parcoursup
*/
class PAPI {
static dataset = "fr-esr-parcoursup";
static timezone = "Europe%2FBerlin";
static searchURL = `https://data.enseignementsup-recherche.gouv.fr/api/records/1.0/search/?dataset=${PAPI.dataset}&timezone=${PAPI.timezone}`;
static async fetchFilieres() {
if (localStorage.getItem("filis")) return JSON.parse(localStorage.getItem("filis"));
let request = await fetch(`${PAPI.searchURL}&rows=0&sort=tri&facet=fili`);
let result = await request.json();
let response = result["facet_groups"][0]["facets"];
localStorage.setItem("filis", JSON.stringify(response));
return response;
}
static async fetchFiliere(filiere) {
if (localStorage.getItem("fili." + filiere)) return JSON.parse(localStorage.getItem("fili." + filiere));
let request = await fetch(`${PAPI.searchURL}&rows=0&sort=tri&facet=form_lib_voe_acc&refine.fili=${filiere}`);
let result = await request.json();
let response = result["facet_groups"][0]["facets"];
localStorage.setItem("fili." + filiere, JSON.stringify(response));
return response;
}
static async fetchSpecialites(filiere, specialite) {
if (localStorage.getItem(`spe.${filiere}.${specialite}`)) return JSON.parse(localStorage.getItem(`spe.${filiere}.${specialite}`));
let request = await fetch(`${PAPI.searchURL}&rows=0&sort=tri&facet=fil_lib_voe_acc&refine.form_lib_voe_acc=${specialite}&refine.fili=${filiere}`);
let result = await request.json();
let response = result["facet_groups"][0]["facets"];
localStorage.setItem(`spe.${filiere}.${specialite}`, JSON.stringify(response));
return response;
}
static async fetchEtablissement(filiere, sousfiliere, soussousfiliere) {
if (localStorage.getItem(`eta.${filiere}.${sousfiliere}.${soussousfiliere}`)) return JSON.parse(localStorage.getItem(`eta.${filiere}.${sousfiliere}.${soussousfiliere}`));
let request = await fetch(`${PAPI.searchURL}&rows=10000&refine.fil_lib_voe_acc=${soussousfiliere}&refine.form_lib_voe_acc=${sousfiliere}&refine.fili=${filiere}`);
let result = await request.json();
let response = result["records"];
localStorage.setItem(`eta.${filiere}.${sousfiliere}.${soussousfiliere}`, JSON.stringify(response));
return response;
}
}
const SORT_TABLE = [{
name: "Nom",
id: "g_ea_lib_vx"
}, {
name: "Ville",
id: "ville_etab"
}, {
name: "Département",
id: "dep"
}, {
name: "Moyenne",
id: "moyenne"
}, {
name: "Sélectivité",
id: "taux_acces_ens"
}];
var mainController = {
css: null,
exports: {
onBeforeMount(props, state) {
//Initial state
this.state = {
course: null,
updating: false,
shouldShowInfos: false
};
sortList(sortBy) {
//Si la liste est déjà triée par la bonne catégorie, on l'inverse
if (sortBy == this.state.sortBy) {
this.state.schoolList.reverse();
}
//Sinon on l'ordonne par la nouvelle catégorie (ascendant par défaut)
else {
this.state.sortBy = sortBy;
switch (sortBy) {
case SORT_TABLE[3].id:
case SORT_TABLE[4].id:
{
this.state.schoolList.sort((a, b) => {
if (a.fields[sortBy] > b.fields[sortBy]) return 1;else return -1;
});
break;
}
default:
{
this.state.schoolList.sort((a, b) => {
return a.fields[sortBy].localeCompare(b.fields[sortBy]);
});
break;
}
}
}
this.update({
schoolList: this.state.schoolList
});
},
updateList(course) {
course = course || this.state.course;
PAPI.fetchEtablissement(course.fili, course.sousfili, course.soussousfili).then(response => {
response.forEach(etablissement => {
// calcul la moyenne
let pct_sansmention = etablissement.fields.pct_sansmention;
let pct_AB = etablissement.fields.pct_ab;
let pct_B = etablissement.fields.pct_b;
let pct_TB = etablissement.fields.pct_tb;
let pct_TBF = etablissement.fields.pct_tbf;
// On prend la moyenne des moyennes comprises dans la mention
// Exemple : Assez bien est entre 12 et 14 donc 13.
etablissement.fields.moyenne = (pct_TBF * 19 + pct_TB * 17 + pct_B * 15 + pct_AB * 13 + pct_sansmention * 11) / 100;
});
this.update({
schoolList: response
});
});
},
updateCourse(course) {
this.updateList(course);
this.update({
course: course,
shouldShowInfos: course != null,
updating: !this.state.updating
sortFields: SORT_TABLE,
shouldShowInfos: course != null
});
},
onMounted(props, state) {
this.update({
course: null,
sortBy: null,
schoolList: null,
sortFields: SORT_TABLE,
shouldShowInfos: false
});
}
},
template: (template, expressionTypes, bindingTypes, getComponent) => template('<div class="columns"><div class="column is-one-third"><div class="box p-3 m-2"><img class="mt-1 ml-5 mr-auto" style="margin: auto;" src="../resources/logo-parcoursup.svg"/></div><search expr125="expr125"></search></div><div class="column"><fili-info expr126="expr126"></fili-info><school expr127="expr127"></school></div></div><school-info expr128="expr128"></school-info>', [{
template: (template, expressionTypes, bindingTypes, getComponent) => template('<div class="columns"><div class="column is-one-third"><div class="box p-3 m-2"><img class="mt-1 ml-5 mr-auto" style="margin: auto;" src="../resources/logo-parcoursup.svg"/></div><search expr0="expr0"></search></div><div class="column"><fili-info expr1="expr1"></fili-info><school expr2="expr2"></school></div></div><school-info expr3="expr3"></school-info>', [{
type: bindingTypes.TAG,
getComponent: getComponent,
evaluate: _scope => 'search',
@ -27,14 +138,18 @@ var mainController = {
name: 'updateCourse',
evaluate: _scope => _scope.updateCourse
}],
redundantAttribute: 'expr125',
selector: '[expr125]'
redundantAttribute: 'expr0',
selector: '[expr0]'
}, {
type: bindingTypes.TAG,
getComponent: getComponent,
evaluate: _scope => 'fili-info',
slots: [],
attributes: [{
type: expressionTypes.ATTRIBUTE,
name: 'schoolList',
evaluate: _scope => _scope.state.schoolList
}, {
type: expressionTypes.ATTRIBUTE,
name: 'course',
evaluate: _scope => _scope.state.course
@ -43,8 +158,8 @@ var mainController = {
name: 'shouldShowInfos',
evaluate: _scope => _scope.state.shouldShowInfos
}],
redundantAttribute: 'expr126',
selector: '[expr126]'
redundantAttribute: 'expr1',
selector: '[expr1]'
}, {
type: bindingTypes.TAG,
getComponent: getComponent,
@ -52,8 +167,16 @@ var mainController = {
slots: [],
attributes: [{
type: expressionTypes.ATTRIBUTE,
name: 'parentUpdate',
evaluate: _scope => _scope.state.updating
name: 'sortList',
evaluate: _scope => _scope.sortList
}, {
type: expressionTypes.ATTRIBUTE,
name: 'schoolList',
evaluate: _scope => _scope.state.schoolList
}, {
type: expressionTypes.ATTRIBUTE,
name: 'sortFields',
evaluate: _scope => _scope.state.sortFields
}, {
type: expressionTypes.ATTRIBUTE,
name: 'course',
@ -63,16 +186,16 @@ var mainController = {
name: 'shouldShowInfos',
evaluate: _scope => _scope.state.shouldShowInfos
}],
redundantAttribute: 'expr127',
selector: '[expr127]'
redundantAttribute: 'expr2',
selector: '[expr2]'
}, {
type: bindingTypes.TAG,
getComponent: getComponent,
evaluate: _scope => 'school-info',
slots: [],
attributes: [],
redundantAttribute: 'expr128',
selector: '[expr128]'
redundantAttribute: 'expr3',
selector: '[expr3]'
}]),
name: 'main-controller'
};

View File

@ -35,15 +35,15 @@ class PAPI {
return response
}
static async fetchSpecialites(specialite) {
static async fetchSpecialites(filiere, specialite) {
if (localStorage.getItem("spe." + specialite)) return JSON.parse(localStorage.getItem("spe." + specialite))
if (localStorage.getItem(`spe.${filiere}.${specialite}`)) return JSON.parse(localStorage.getItem(`spe.${filiere}.${specialite}`))
let request = await fetch(`${PAPI.searchURL}&rows=0&sort=tri&facet=fil_lib_voe_acc&refine.form_lib_voe_acc=${specialite}`)
let request = await fetch(`${PAPI.searchURL}&rows=0&sort=tri&facet=fil_lib_voe_acc&refine.form_lib_voe_acc=${specialite}&refine.fili=${filiere}`)
let result = await request.json()
let response = result["facet_groups"][0]["facets"]
localStorage.setItem("spe." + specialite, JSON.stringify(response))
localStorage.setItem(`spe.${filiere}.${specialite}`, JSON.stringify(response))
return response
}
@ -52,7 +52,7 @@ class PAPI {
if (localStorage.getItem(`eta.${filiere}.${sousfiliere}.${soussousfiliere}`)) return JSON.parse(localStorage.getItem(`eta.${filiere}.${sousfiliere}.${soussousfiliere}`))
let request = await fetch(`${PAPI.searchURL}&refine.fil_lib_voe_acc=${soussousfiliere}&refine.form_lib_voe_acc=${sousfiliere}&refine.fili=${filiere}`)
let request = await fetch(`${PAPI.searchURL}&rows=10000&refine.fil_lib_voe_acc=${soussousfiliere}&refine.form_lib_voe_acc=${sousfiliere}&refine.fili=${filiere}`)
let result = await request.json()
let response = result["records"]

View File

@ -10,14 +10,14 @@ var schoolInfo = {
this.update();
}
},
template: (template, expressionTypes, bindingTypes, getComponent) => template('<div expr10="expr10" style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; background: #000000DD;"></div>', [{
template: (template, expressionTypes, bindingTypes, getComponent) => template('<div expr29="expr29" style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; background: #000000DD;"></div>', [{
type: bindingTypes.IF,
evaluate: _scope => _scope.state.enabled,
redundantAttribute: 'expr10',
selector: '[expr10]',
template: template('<div style="position: absolute; top: 10%; left: 10%; width: 80%; height: 80%; background: #FFFFFF"><button expr11="expr11" class="delete is-medium">X</button><p><h2></h2></p><line-graph expr12="expr12" style="height: 90px; margin: 10px;"></line-graph></div>', [{
redundantAttribute: 'expr11',
selector: '[expr11]',
redundantAttribute: 'expr29',
selector: '[expr29]',
template: template('<div style="position: absolute; top: 10%; left: 10%; width: 80%; height: 80%; background: #FFFFFF"><button expr30="expr30" class="delete is-medium">X</button><p><h2></h2></p><line-graph expr31="expr31" style="height: 90px; margin: 10px;"></line-graph></div>', [{
redundantAttribute: 'expr30',
selector: '[expr30]',
expressions: [{
type: expressionTypes.EVENT,
name: 'onclick',
@ -29,8 +29,8 @@ var schoolInfo = {
evaluate: _scope => 'line-graph',
slots: [],
attributes: [],
redundantAttribute: 'expr12',
selector: '[expr12]'
redundantAttribute: 'expr31',
selector: '[expr31]'
}])
}]),
name: 'school-info'

View File

@ -1,150 +1,30 @@
/*
Parcoursup API (PAPI)
Comprend un set de wrapper afin d'accéder plus aisément aux informations de l'API parcoursup
*/
class PAPI {
static dataset = "fr-esr-parcoursup";
static timezone = "Europe%2FBerlin";
static searchURL = `https://data.enseignementsup-recherche.gouv.fr/api/records/1.0/search/?dataset=${PAPI.dataset}&timezone=${PAPI.timezone}`;
static async fetchFilieres() {
if (localStorage.getItem("filis")) return JSON.parse(localStorage.getItem("filis"));
let request = await fetch(`${PAPI.searchURL}&rows=0&sort=tri&facet=fili`);
let result = await request.json();
let response = result["facet_groups"][0]["facets"];
localStorage.setItem("filis", JSON.stringify(response));
return response;
}
static async fetchFiliere(filiere) {
if (localStorage.getItem("fili." + filiere)) return JSON.parse(localStorage.getItem("fili." + filiere));
let request = await fetch(`${PAPI.searchURL}&rows=0&sort=tri&facet=form_lib_voe_acc&refine.fili=${filiere}`);
let result = await request.json();
let response = result["facet_groups"][0]["facets"];
localStorage.setItem("fili." + filiere, JSON.stringify(response));
return response;
}
static async fetchSpecialites(specialite) {
if (localStorage.getItem("spe." + specialite)) return JSON.parse(localStorage.getItem("spe." + specialite));
let request = await fetch(`${PAPI.searchURL}&rows=0&sort=tri&facet=fil_lib_voe_acc&refine.form_lib_voe_acc=${specialite}`);
let result = await request.json();
let response = result["facet_groups"][0]["facets"];
localStorage.setItem("spe." + specialite, JSON.stringify(response));
return response;
}
static async fetchEtablissement(filiere, sousfiliere, soussousfiliere) {
if (localStorage.getItem(`eta.${filiere}.${sousfiliere}.${soussousfiliere}`)) return JSON.parse(localStorage.getItem(`eta.${filiere}.${sousfiliere}.${soussousfiliere}`));
let request = await fetch(`${PAPI.searchURL}&refine.fil_lib_voe_acc=${soussousfiliere}&refine.form_lib_voe_acc=${sousfiliere}&refine.fili=${filiere}`);
let result = await request.json();
let response = result["records"];
localStorage.setItem(`eta.${filiere}.${sousfiliere}.${soussousfiliere}`, JSON.stringify(response));
return response;
}
}
async function fetchEtablissement(course) {
return PAPI.fetchEtablissement(course.fili, course.sousfili, course.soussousfili);
}
const SORT_TABLE = [{
name: "Nom",
id: "g_ea_lib_vx"
}, {
name: "Ville",
id: "ville_etab"
}, {
name: "Département",
id: "dep"
}, {
name: "Moyenne",
id: "moyenne"
}, {
name: "Sélectivité",
id: "taux_acces_ens"
}];
var school = {
css: null,
exports: function search() {
return {
updateList() {
fetchEtablissement(this.props.course).then(response => {
response.forEach(etablissement => {
// calcul la moyenne
let pct_sansmention = etablissement.fields.pct_sansmention;
let pct_AB = etablissement.fields.pct_ab;
let pct_B = etablissement.fields.pct_b;
let pct_TB = etablissement.fields.pct_tb;
let pct_TBF = etablissement.fields.pct_tbf;
// On prend la moyenne des moyennes comprises dans la mention
// Exemple : Assez bien est entre 12 et 14 donc 13.
etablissement.fields.moyenne = (pct_TBF * 19 + pct_TB * 17 + pct_B * 15 + pct_AB * 13 + pct_sansmention * 11) / 100;
});
this.update({
items: response,
parentUpdate: this.props.parentUpdate
});
});
},
sortList(sortBy) {
//Si la liste est déjà triée par la bonne catégorie, on l'inverse
if (sortBy == this.state.sortBy) {
this.state.items.reverse();
}
//Sinon on l'ordonne par la nouvelle catégorie (ascendant par défaut)
else {
this.state.sortBy = sortBy;
switch (sortBy) {
case SORT_TABLE[3].id:
case SORT_TABLE[4].id:
{
this.state.items.sort((a, b) => {
if (a.fields[sortBy] > b.fields[sortBy]) return 1;else return -1;
});
break;
}
default:
{
this.state.items.sort((a, b) => {
return a.fields[sortBy].localeCompare(b.fields[sortBy]);
});
break;
}
}
}
this.update({
items: this.state.items
});
},
onBeforeMount(props, state) {
},
onMounted(props, state) {
this.update({
sortFields: SORT_TABLE
});
},
onUpdated(props, state) {
if (!props.shouldShowInfos || state.parentUpdate == props.parentUpdate) return;
this.updateList();
}
};
},
template: (template, expressionTypes, bindingTypes, getComponent) => template('<div expr336="expr336" class="box p-2 m-2"></div>', [{
exports: null,
template: (template, expressionTypes, bindingTypes, getComponent) => template('<div expr345="expr345" class="box p-2 m-2" disabled></div>', [{
type: bindingTypes.IF,
evaluate: _scope => _scope.props.shouldShowInfos,
redundantAttribute: 'expr336',
selector: '[expr336]',
template: template('<iframe width="100%" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="https://www.openstreetmap.org/export/embed.html?bbox=-14.655761718750002%2C40.56389453066509%2C13.601074218750002%2C51.754240074033525&amp;layer=mapnik" style="border-radius: 5px;"></iframe><br/><div class="block control has-icons-left is-inline-block is-pulled-right"><input class="input" type="search" placeholder="Établissement"/><span class="icon is-small is-left"><i class="fas fa-search"></i></span></div><table class="table is-fullwidth is-hoverable"><thead><tr><th expr337="expr337"></th></tr></thead><tbody><tr expr339="expr339"></tr></tbody></table>', [{
redundantAttribute: 'expr345',
selector: '[expr345]',
template: template('<iframe expr346="expr346" width="100%" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="https://www.openstreetmap.org/export/embed.html?bbox=-14.655761718750002%2C40.56389453066509%2C13.601074218750002%2C51.754240074033525&amp;layer=mapnik" style="border-radius: 5px;"></iframe><br/><div class="block control has-icons-left is-inline-block is-pulled-right"><input class="input" type="search" placeholder="Établissement"/><span class="icon is-small is-left"><i class="fas fa-search"></i></span></div><table class="table is-fullwidth is-hoverable"><thead><tr><th expr347="expr347"></th></tr></thead><tbody><tr expr349="expr349"></tr></tbody></table>', [{
type: bindingTypes.IF,
evaluate: _scope => false,
redundantAttribute: 'expr346',
selector: '[expr346]',
template: template(null, [])
}, {
type: bindingTypes.EACH,
getKey: null,
condition: null,
template: template(' <a expr338="expr338"><span class="icon"><i class="fas fa-sort"></i></span></a>', [{
template: template(' <a expr348="expr348"><span class="icon"><i class="fas fa-sort"></i></span></a>', [{
expressions: [{
type: expressionTypes.TEXT,
childNodeIndex: 0,
evaluate: _scope => [_scope.sortField.name].join('')
}]
}, {
redundantAttribute: 'expr338',
selector: '[expr338]',
redundantAttribute: 'expr348',
selector: '[expr348]',
expressions: [{
type: expressionTypes.ATTRIBUTE,
name: 'id',
@ -152,64 +32,68 @@ var school = {
}, {
type: expressionTypes.EVENT,
name: 'onclick',
evaluate: _scope => () => _scope.sortList(_scope.sortField.id)
evaluate: _scope => () => _scope.props.sortList(_scope.sortField.id)
}]
}]),
redundantAttribute: 'expr337',
selector: '[expr337]',
redundantAttribute: 'expr347',
selector: '[expr347]',
itemName: 'sortField',
indexName: null,
evaluate: _scope => _scope.state.sortFields
evaluate: _scope => _scope.props.sortFields
}, {
type: bindingTypes.EACH,
getKey: null,
condition: null,
template: template('<td expr340="expr340"> </td><td expr341="expr341"> </td><td expr342="expr342"> </td><td expr343="expr343"> </td><td expr344="expr344"> </td>', [{
redundantAttribute: 'expr340',
selector: '[expr340]',
template: template('<td expr350="expr350"> </td><td expr351="expr351"> </td><td expr352="expr352"> </td><td expr353="expr353"> </td><td><title-progress expr354="expr354" max="100" style="margin: auto"></title-progress></td>', [{
redundantAttribute: 'expr350',
selector: '[expr350]',
expressions: [{
type: expressionTypes.TEXT,
childNodeIndex: 0,
evaluate: _scope => _scope.etablissement.fields.g_ea_lib_vx
evaluate: _scope => _scope.school.fields.g_ea_lib_vx
}]
}, {
redundantAttribute: 'expr341',
selector: '[expr341]',
redundantAttribute: 'expr351',
selector: '[expr351]',
expressions: [{
type: expressionTypes.TEXT,
childNodeIndex: 0,
evaluate: _scope => _scope.etablissement.fields.ville_etab
evaluate: _scope => _scope.school.fields.ville_etab
}]
}, {
redundantAttribute: 'expr342',
selector: '[expr342]',
redundantAttribute: 'expr352',
selector: '[expr352]',
expressions: [{
type: expressionTypes.TEXT,
childNodeIndex: 0,
evaluate: _scope => _scope.etablissement.fields.dep
evaluate: _scope => _scope.school.fields.dep
}]
}, {
redundantAttribute: 'expr343',
selector: '[expr343]',
redundantAttribute: 'expr353',
selector: '[expr353]',
expressions: [{
type: expressionTypes.TEXT,
childNodeIndex: 0,
evaluate: _scope => _scope.etablissement.fields.moyenne
evaluate: _scope => _scope.school.fields.moyenne
}]
}, {
redundantAttribute: 'expr344',
selector: '[expr344]',
expressions: [{
type: expressionTypes.TEXT,
childNodeIndex: 0,
evaluate: _scope => _scope.etablissement.fields.taux_acces_ens
}]
type: bindingTypes.TAG,
getComponent: getComponent,
evaluate: _scope => 'title-progress',
slots: [],
attributes: [{
type: expressionTypes.ATTRIBUTE,
name: 'value',
evaluate: _scope => _scope.school.fields.taux_acces_ens
}],
redundantAttribute: 'expr354',
selector: '[expr354]'
}]),
redundantAttribute: 'expr339',
selector: '[expr339]',
itemName: 'etablissement',
redundantAttribute: 'expr349',
selector: '[expr349]',
itemName: 'school',
indexName: null,
evaluate: _scope => _scope.state.items
evaluate: _scope => _scope.props.schoolList
}])
}]),
name: 'school'

View File

@ -23,17 +23,17 @@ class PAPI {
localStorage.setItem("fili." + filiere, JSON.stringify(response));
return response;
}
static async fetchSpecialites(specialite) {
if (localStorage.getItem("spe." + specialite)) return JSON.parse(localStorage.getItem("spe." + specialite));
let request = await fetch(`${PAPI.searchURL}&rows=0&sort=tri&facet=fil_lib_voe_acc&refine.form_lib_voe_acc=${specialite}`);
static async fetchSpecialites(filiere, specialite) {
if (localStorage.getItem(`spe.${filiere}.${specialite}`)) return JSON.parse(localStorage.getItem(`spe.${filiere}.${specialite}`));
let request = await fetch(`${PAPI.searchURL}&rows=0&sort=tri&facet=fil_lib_voe_acc&refine.form_lib_voe_acc=${specialite}&refine.fili=${filiere}`);
let result = await request.json();
let response = result["facet_groups"][0]["facets"];
localStorage.setItem("spe." + specialite, JSON.stringify(response));
localStorage.setItem(`spe.${filiere}.${specialite}`, JSON.stringify(response));
return response;
}
static async fetchEtablissement(filiere, sousfiliere, soussousfiliere) {
if (localStorage.getItem(`eta.${filiere}.${sousfiliere}.${soussousfiliere}`)) return JSON.parse(localStorage.getItem(`eta.${filiere}.${sousfiliere}.${soussousfiliere}`));
let request = await fetch(`${PAPI.searchURL}&refine.fil_lib_voe_acc=${soussousfiliere}&refine.form_lib_voe_acc=${sousfiliere}&refine.fili=${filiere}`);
let request = await fetch(`${PAPI.searchURL}&rows=10000&refine.fil_lib_voe_acc=${soussousfiliere}&refine.form_lib_voe_acc=${sousfiliere}&refine.fili=${filiere}`);
let result = await request.json();
let response = result["records"];
localStorage.setItem(`eta.${filiere}.${sousfiliere}.${soussousfiliere}`, JSON.stringify(response));
@ -55,7 +55,7 @@ var search = {
promise = PAPI.fetchFiliere(this.state.course.fili);
break;
case 2:
promise = PAPI.fetchSpecialites(this.state.course.sousfili);
promise = PAPI.fetchSpecialites(this.state.course.fili, this.state.course.sousfili);
break;
default:
return;
@ -144,9 +144,9 @@ var search = {
this.updateList();
}
},
template: (template, expressionTypes, bindingTypes, getComponent) => template('<div class="box p-1 m-2"><div class="columns m-1"><input expr27="expr27" class="input" type="input"/><button expr28="expr28" class="button ml-1">&lt;</button></div><div id="list-formations"><ul><li expr29="expr29" class="m-1"></li></ul></div></div>', [{
redundantAttribute: 'expr27',
selector: '[expr27]',
template: (template, expressionTypes, bindingTypes, getComponent) => template('<div class="box p-1 m-2"><div class="columns m-1"><input expr23="expr23" class="input" type="input"/><button expr24="expr24" class="button ml-1">&lt;</button></div><div id="list-formations"><ul><li expr25="expr25" class="m-1"></li></ul></div></div>', [{
redundantAttribute: 'expr23',
selector: '[expr23]',
expressions: [{
type: expressionTypes.EVENT,
name: 'onkeyup',
@ -157,8 +157,8 @@ var search = {
evaluate: _scope => _scope.state.placeholder
}]
}, {
redundantAttribute: 'expr28',
selector: '[expr28]',
redundantAttribute: 'expr24',
selector: '[expr24]',
expressions: [{
type: expressionTypes.ATTRIBUTE,
name: 'disabled',
@ -172,9 +172,9 @@ var search = {
type: bindingTypes.EACH,
getKey: null,
condition: null,
template: template('<button expr30="expr30" class="button is-fullwidth p-2"><span style="font-size: .75em; max-size: 90%"><strong expr31="expr31"> </strong></span><div style="margin-left: auto;"></div><span expr32="expr32" class="tag is-primary"> </span></button>', [{
redundantAttribute: 'expr30',
selector: '[expr30]',
template: template('<button expr26="expr26" class="button is-fullwidth p-2"><span style="font-size: .75em; max-size: 90%"><strong expr27="expr27"> </strong></span><div style="margin-left: auto;"></div><span expr28="expr28" class="tag is-primary"> </span></button>', [{
redundantAttribute: 'expr26',
selector: '[expr26]',
expressions: [{
type: expressionTypes.ATTRIBUTE,
name: 'disabled',
@ -185,24 +185,24 @@ var search = {
evaluate: _scope => () => _scope.cruiseForward(_scope.item.name)
}]
}, {
redundantAttribute: 'expr31',
selector: '[expr31]',
redundantAttribute: 'expr27',
selector: '[expr27]',
expressions: [{
type: expressionTypes.TEXT,
childNodeIndex: 0,
evaluate: _scope => _scope.item.name
}]
}, {
redundantAttribute: 'expr32',
selector: '[expr32]',
redundantAttribute: 'expr28',
selector: '[expr28]',
expressions: [{
type: expressionTypes.TEXT,
childNodeIndex: 0,
evaluate: _scope => _scope.item.count
}]
}]),
redundantAttribute: 'expr29',
selector: '[expr29]',
redundantAttribute: 'expr25',
selector: '[expr25]',
itemName: 'item',
indexName: null,
evaluate: _scope => _scope.state.items

View File

@ -0,0 +1,68 @@
const DEFAULT_CLASSES = "progress is-small m-2 mt-auto mb-auto";
const COLOR_CLASSES = ["is-link", "is-info", "is-success", "is-warning", "is-danger"];
var titleProgress = {
css: null,
exports: {
computeClasses() {
if (!this.props.value) return DEFAULT_CLASSES;
let n = Math.floor(this.props.value / 20);
if (n == 5) n = 4;
return DEFAULT_CLASSES + " " + COLOR_CLASSES[n];
},
calcPct() {
if (!this.props.value) {
return "???";
} else {
return Math.round(this.props.value / this.props.max * 100) + "%";
}
},
onMounted(props, state) {
this.update({
class: this.computeClasses()
});
},
onBeforeUpdate(props, state) {
state.class = this.computeClasses();
}
},
template: (template, expressionTypes, bindingTypes, getComponent) => template('<div style="display: flex;"><span expr493="expr493"></span><span expr494="expr494" class="ml-1"> </span><progress expr495="expr495" style="box-shadow: 0 0.5em 1em -0.125em rgb(10 10 10 / 10%), 0 0 0 1px rgb(10 10 10 / 2%);"></progress></div>', [{
type: bindingTypes.IF,
evaluate: _scope => _scope.props.title,
redundantAttribute: 'expr493',
selector: '[expr493]',
template: template(' ', [{
expressions: [{
type: expressionTypes.TEXT,
childNodeIndex: 0,
evaluate: _scope => _scope.props.title
}]
}])
}, {
redundantAttribute: 'expr494',
selector: '[expr494]',
expressions: [{
type: expressionTypes.TEXT,
childNodeIndex: 0,
evaluate: _scope => _scope.calcPct()
}]
}, {
redundantAttribute: 'expr495',
selector: '[expr495]',
expressions: [{
type: expressionTypes.ATTRIBUTE,
name: 'value',
evaluate: _scope => _scope.props.value
}, {
type: expressionTypes.ATTRIBUTE,
name: 'max',
evaluate: _scope => _scope.props.max
}, {
type: expressionTypes.ATTRIBUTE,
name: 'class',
evaluate: _scope => _scope.state.class
}]
}]),
name: 'title-progress'
};
export { titleProgress as default };

View File

@ -3,6 +3,7 @@
*/
import MainController from './javascript/main-controller.js'
import TitleProgress from './javascript/title-progress.js'
import SchoolInfo from './javascript/school-info.js'
import LineGraph from './javascript/line-graph.js'
import FiliInfo from './javascript/fili-info.js'
@ -10,6 +11,7 @@ import Search from './javascript/search.js'
import School from './javascript/school.js'
riot.register("main-controller", MainController)
riot.register("title-progress", TitleProgress)
riot.register("school-info", SchoolInfo)
riot.register("line-graph", LineGraph)
riot.register("fili-info", FiliInfo)
@ -17,6 +19,7 @@ riot.register("search", Search)
riot.register("school", School)
riot.mount("title-progress")
riot.mount("line-graph")
riot.mount("search")
riot.mount("school-info")

View File

@ -6,11 +6,11 @@
id="Calque_1"
x="0px"
y="0px"
viewBox="0 0 360.50001 58.400003"
viewBox="0 0 409.00221 69.400003"
xml:space="preserve"
sodipodi:docname="logo-parcoursup.svg"
width="360.5"
height="58.400002"
width="409.0022"
height="69.400002"
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
@ -26,13 +26,13 @@
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="3.8800706"
inkscape:cx="177.83182"
inkscape:cy="71.519317"
inkscape:zoom="2.7436242"
inkscape:cx="225.61399"
inkscape:cy="45.195694"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-height="1057"
inkscape:window-x="1912"
inkscape:window-y="-5"
inkscape:window-maximized="1"
inkscape:current-layer="Calque_1" />
<style
@ -43,180 +43,55 @@
</style>
<path
class="st0"
d="M 70.7,33.3 C 68.9,35.1 66,36.2 62.8,36.2 59.5,36.2 57.1,35.3 55,33 V 47.7 H 46.9 V 3.4999995 h 7.8 v 3 c 2.2,-2.5 4.7,-3.4 8.1,-3.4 3.2,0 6.1,1.1 7.9,2.9 C 73.9,9.2 74,14.8 74,19.6 74,24.5 73.9,30.1 70.7,33.3 Z M 60.4,10.4 c -4.8,0 -5.5,4 -5.5,9.3 0,5.3 0.6,9.3 5.5,9.3 4.9,0 5.5,-4 5.5,-9.3 0,-5.3 -0.6,-9.3 -5.5,-9.3 z"
d="m 70.7,46.9 c -1.8,1.8 -4.7,2.9 -7.9,2.9 -3.3,0 -5.7,-0.9 -7.8,-3.2 V 61.3 H 46.9 V 17.1 h 7.8 v 3 c 2.2,-2.5 4.7,-3.400001 8.1,-3.400001 3.2,0 6.1,1.100001 7.9,2.900001 3.2,3.2 3.3,8.8 3.3,13.6 0,4.9 -0.1,10.5 -3.3,13.7 z M 60.4,24 c -4.8,0 -5.5,4 -5.5,9.3 0,5.3 0.6,9.3 5.5,9.3 4.9,0 5.5,-4 5.5,-9.3 C 65.9,28 65.3,24 60.4,24 Z"
id="path4" />
<path
class="st0"
d="M 98.2,35.8 V 33 C 96,35.2 94,36.1 90.3,36.1 86.6,36.1 84,35.2 82,33.2 80.3,31.5 79.4,28.9 79.4,26 c 0,-5.2 3.5,-9.4 11.1,-9.4 h 7.6 V 15 c 0,-3.5 -1.7,-5.1 -6,-5.1 -3.1,0 -4.5,0.7 -6.2,2.7 L 80.7,7.5999995 c 3.2,-3.5 6.3,-4.5 11.7,-4.5 9.1,0 13.8,3.8 13.8,11.4000005 V 35.8 Z M 98,22.2 h -6.4 c -2.9,0 -4.5,1.4 -4.5,3.7 0,2.2 1.5,3.7 4.7,3.7 2.2,0 3.7,-0.2 5.1,-1.6 0.9,-0.8 1.2,-2.1 1.2,-4.1 v -1.7 z"
d="m 98.2,49.4 v -2.8 c -2.2,2.2 -4.2,3.1 -7.9,3.1 -3.7,0 -6.3,-0.9 -8.3,-2.9 -1.7,-1.7 -2.6,-4.3 -2.6,-7.2 0,-5.2 3.5,-9.4 11.1,-9.4 h 7.6 v -1.6 c 0,-3.5 -1.7,-5.1 -6,-5.1 -3.1,0 -4.5,0.7 -6.2,2.7 l -5.2,-5.000001 c 3.2,-3.5 6.3,-4.5 11.7,-4.5 9.1,0 13.8,3.800001 13.8,11.400001 V 49.4 Z M 98,35.8 h -6.4 c -2.9,0 -4.5,1.4 -4.5,3.7 0,2.2 1.5,3.7 4.7,3.7 2.2,0 3.7,-0.2 5.1,-1.6 0.9,-0.8 1.2,-2.1 1.2,-4.1 v -1.7 z"
id="path6" />
<path
class="st0"
d="m 132.4,12.3 c -1.2,-1.2 -2.3,-1.9 -4.3,-1.9 -2.5,0 -5.2,1.9 -5.2,6 v 19.5 h -8.1 V 3.4999995 h 7.9 v 3.1 c 1.6,-1.9 4.7,-3.5 8.1,-3.5 3.2,0 5.4,0.8 7.6,3 z"
d="m 132.4,25.9 c -1.2,-1.2 -2.3,-1.9 -4.3,-1.9 -2.5,0 -5.2,1.9 -5.2,6 v 19.5 h -8.1 V 17.1 h 7.9 v 3.099999 c 1.6,-1.899999 4.7,-3.5 8.1,-3.5 3.2,0 5.4,0.800001 7.6,3 z"
id="path8" />
<path
class="st0"
d="m 154,36.2 c -6.5,0 -14.5,-3.5 -14.5,-16.6 0,-13.1000005 8,-16.5000005 14.5,-16.5000005 4.5,0 7.8,1.4 10.7,4.3 L 159.2,12.9 c -1.7,-1.8 -3.1,-2.5 -5.2,-2.5 -1.9,0 -3.4,0.7 -4.6,2.1 -1.2,1.6 -1.8,3.7 -1.8,7.1 0,3.4 0.6,5.7 1.8,7.2 1.2,1.4 2.7,2.1 4.6,2.1 2.1,0 3.5,-0.7 5.2,-2.5 l 5.5,5.4 c -2.9,3 -6.2,4.4 -10.7,4.4 z"
d="m 154,49.8 c -6.5,0 -14.5,-3.5 -14.5,-16.6 0,-13.1 8,-16.5 14.5,-16.5 4.5,0 7.8,1.4 10.7,4.3 l -5.5,5.5 C 157.5,24.7 156.1,24 154,24 c -1.9,0 -3.4,0.7 -4.6,2.1 -1.2,1.6 -1.8,3.7 -1.8,7.1 0,3.4 0.6,5.7 1.8,7.2 1.2,1.4 2.7,2.1 4.6,2.1 2.1,0 3.5,-0.7 5.2,-2.5 l 5.5,5.4 c -2.9,3 -6.2,4.4 -10.7,4.4 z"
id="path10" />
<path
class="st0"
d="m 192.2,32.2 c -2,2.1 -5.3,4 -10.1,4 -4.8,0 -8,-1.9 -10,-4 -2.9,-3 -3.7,-6.7 -3.7,-12.6 0,-5.8 0.7,-9.5 3.7,-12.5000005 2,-2.1 5.2,-4 10,-4 4.8,0 8.1,1.9 10.1,4 C 195.1,10.1 195.9,13.8 195.9,19.6 c -0.1,5.9 -0.8,9.6 -3.7,12.6 z m -6.3,-20.4 c -0.9,-0.9 -2.2,-1.4 -3.8,-1.4 -1.6,0 -2.8,0.5 -3.7,1.4 -1.7,1.7 -1.9,4.5 -1.9,7.8 0,3.4 0.2,6.2 1.9,7.9 0.9,0.9 2.1,1.4 3.7,1.4 1.6,0 2.9,-0.5 3.8,-1.4 1.7,-1.7 1.9,-4.5 1.9,-7.9 0,-3.3 -0.2,-6.1 -1.9,-7.8 z"
d="m 192.2,45.8 c -2,2.1 -5.3,4 -10.1,4 -4.8,0 -8,-1.9 -10,-4 -2.9,-3 -3.7,-6.7 -3.7,-12.6 0,-5.8 0.7,-9.5 3.7,-12.5 2,-2.1 5.2,-4 10,-4 4.8,0 8.1,1.9 10.1,4 2.9,3 3.7,6.7 3.7,12.5 -0.1,5.9 -0.8,9.6 -3.7,12.6 z M 185.9,25.4 C 185,24.5 183.7,24 182.1,24 c -1.6,0 -2.8,0.5 -3.7,1.4 -1.7,1.7 -1.9,4.5 -1.9,7.8 0,3.4 0.2,6.2 1.9,7.9 0.9,0.9 2.1,1.4 3.7,1.4 1.6,0 2.9,-0.5 3.8,-1.4 1.7,-1.7 1.9,-4.5 1.9,-7.9 0,-3.3 -0.2,-6.1 -1.9,-7.8 z"
id="path12" />
<path
class="st0"
d="m 222.1,35.8 v -3 c -2.1,2.2 -5.1,3.4 -8.1,3.4 -3.2,0 -5.8,-1.1 -7.6,-2.9 -2.6,-2.6 -3.3,-5.6 -3.3,-9.2 V 3.4999995 h 8.1 V 23.1 c 0,4.4 2.8,5.9 5.3,5.9 2.5,0 5.4,-1.5 5.4,-5.9 V 3.4999995 H 230 V 35.8 Z"
d="m 222.1,49.4 v -3 c -2.1,2.2 -5.1,3.4 -8.1,3.4 -3.2,0 -5.8,-1.1 -7.6,-2.9 -2.6,-2.6 -3.3,-5.6 -3.3,-9.2 V 17.1 h 8.1 v 19.6 c 0,4.4 2.8,5.9 5.3,5.9 2.5,0 5.4,-1.5 5.4,-5.9 V 17.1 h 8.1 v 32.3 z"
id="path14" />
<path
class="st0"
d="m 256.7,12.3 c -1.2,-1.2 -2.3,-1.9 -4.3,-1.9 -2.5,0 -5.2,1.9 -5.2,6 v 19.5 h -8.1 V 3.4999995 h 7.9 v 3.1 c 1.6,-1.9 4.7,-3.5 8.1,-3.5 3.2,0 5.4,0.8 7.6,3 z"
d="m 256.7,25.9 c -1.2,-1.2 -2.3,-1.9 -4.3,-1.9 -2.5,0 -5.2,1.9 -5.2,6 v 19.5 h -8.1 V 17.1 h 7.9 v 3.099999 c 1.6,-1.899999 4.7,-3.5 8.1,-3.5 3.2,0 5.4,0.800001 7.6,3 z"
id="path16" />
<path
class="st1"
d="m 316.4,35.8 v -3 c -2.1,2.2 -5.1,3.4 -8.1,3.4 -3.2,0 -5.8,-1.1 -7.6,-2.9 -2.6,-2.6 -3.3,-5.6 -3.3,-9.2 V 3.4999995 h 8.1 V 23.1 c 0,4.4 2.8,5.9 5.3,5.9 2.5,0 5.4,-1.5 5.4,-5.9 V 3.4999995 h 8.1 V 35.8 Z"
id="path18"
inkscape:label="path18" />
<path
class="st1"
d="m 357.2,33.3 c -1.8,1.8 -4.7,2.9 -7.9,2.9 -3.3,0 -5.7,-0.9 -7.8,-3.2 v 14.7 h -8.1 V 3.4999995 h 7.8 v 3 c 2.2,-2.5 4.7,-3.4 8.1,-3.4 3.2,0 6.1,1.1 7.9,2.9 C 360.4,9.2 360.5,14.8 360.5,19.6 c 0,4.9 -0.1,10.5 -3.3,13.7 z M 346.9,10.4 c -4.8,0 -5.5,4 -5.5,9.3 0,5.3 0.6,9.3 5.5,9.3 4.9,0 5.5,-4 5.5,-9.3 0,-5.3 -0.6,-9.3 -5.5,-9.3 z"
id="path20" />
<g
id="g88"
transform="translate(-17.6,-46.1)">
<path
class="st0"
d="m 91,101.6 v -10 h 6.4 V 93 h -4.9 v 2.9 h 4.1 v 1.3 h -4.1 v 3 h 4.9 v 1.4 z"
id="path22" />
<path
class="st0"
d="m 103.8,101.6 v -4.3 c 0,-1.1 -0.6,-1.6 -1.4,-1.6 -0.8,0 -1.5,0.5 -1.5,1.6 v 4.3 h -1.4 v -7.1 h 1.4 v 0.7 c 0.5,-0.5 1.2,-0.8 1.9,-0.8 0.7,0 1.3,0.2 1.8,0.6 0.5,0.5 0.7,1.2 0.7,2 v 4.5 h -1.5 z"
id="path24" />
<path
class="st0"
d="m 109.6,101.6 c -1.3,0 -1.9,-1 -1.9,-2 v -3.9 h -0.8 v -1.1 h 0.8 v -2.2 h 1.4 v 2.2 h 1.4 v 1.1 h -1.4 v 3.8 c 0,0.5 0.3,0.8 0.8,0.8 h 0.6 v 1.2 h -0.9 z"
id="path26" />
<path
class="st0"
d="m 116.4,96.2 c -0.3,-0.3 -0.6,-0.5 -1.1,-0.5 -0.8,0 -1.4,0.6 -1.4,1.6 v 4.3 h -1.4 v -7.1 h 1.4 v 0.8 c 0.4,-0.5 1.1,-0.9 1.9,-0.9 0.7,0 1.2,0.2 1.7,0.7 z"
id="path28" />
<path
class="st0"
d="m 119.3,98.5 c 0,1.2 0.6,2 1.8,2 0.8,0 1.2,-0.2 1.7,-0.7 l 0.9,0.9 c -0.7,0.7 -1.4,1.1 -2.7,1.1 -1.8,0 -3.2,-0.9 -3.2,-3.6 0,-2.3 1.2,-3.6 3,-3.6 1.9,0 3,1.4 3,3.4 v 0.6 h -4.5 z m 3,-2 c -0.2,-0.5 -0.7,-0.9 -1.4,-0.9 -0.7,0 -1.2,0.4 -1.4,0.9 -0.1,0.3 -0.2,0.5 -0.2,1 h 3.2 c 0,-0.5 0,-0.7 -0.2,-1 z"
id="path30" />
<path
class="st0"
d="m 125.4,101.6 v -1.1 l 3.5,-4.7 h -3.3 v -1.3 h 5.1 v 1.1 l -3.6,4.7 h 3.6 v 1.3 z"
id="path32" />
<path
class="st0"
d="m 140.3,101.6 v -0.8 c -0.5,0.6 -1.1,0.8 -1.9,0.8 -0.7,0 -1.3,-0.2 -1.7,-0.6 -0.7,-0.7 -0.8,-1.9 -0.8,-3 0,-1.1 0.1,-2.3 0.8,-3 0.4,-0.4 1,-0.6 1.7,-0.6 0.8,0 1.3,0.2 1.9,0.8 v -3.6 h 1.4 v 10 z m -1.5,-5.9 c -1.3,0 -1.5,1.1 -1.5,2.4 0,1.3 0.2,2.4 1.5,2.4 1.3,0 1.5,-1.1 1.5,-2.4 0,-1.3 -0.3,-2.4 -1.5,-2.4 z"
id="path34" />
<path
class="st0"
d="M 147.9,101.6 V 101 c -0.5,0.5 -1,0.7 -1.9,0.7 -0.9,0 -1.5,-0.2 -1.9,-0.6 -0.4,-0.4 -0.6,-0.9 -0.6,-1.5 0,-1.2 0.8,-2 2.5,-2 h 1.9 V 97 c 0,-0.9 -0.4,-1.3 -1.6,-1.3 -0.8,0 -1.2,0.2 -1.6,0.7 l -0.9,-0.9 c 0.7,-0.8 1.4,-1 2.5,-1 1.9,0 2.9,0.8 2.9,2.4 v 4.7 z m 0,-3.1 h -1.7 c -0.8,0 -1.3,0.4 -1.3,1 0,0.6 0.4,1 1.3,1 0.5,0 1,0 1.3,-0.4 0.2,-0.2 0.3,-0.5 0.3,-1.1 v -0.5 z"
id="path36" />
<path
class="st0"
d="m 155.9,101.6 v -4.3 c 0,-1.1 -0.6,-1.6 -1.4,-1.6 -0.8,0 -1.5,0.5 -1.5,1.6 v 4.3 h -1.4 v -7.1 h 1.4 v 0.7 c 0.5,-0.5 1.2,-0.8 1.9,-0.8 0.7,0 1.3,0.2 1.8,0.6 0.5,0.5 0.7,1.2 0.7,2 v 4.5 h -1.5 z"
id="path38" />
<path
class="st0"
d="m 162,101.7 c -1.2,0 -2.1,-0.2 -3,-1 l 0.9,-0.9 c 0.6,0.6 1.3,0.7 2,0.7 0.9,0 1.6,-0.3 1.6,-1 0,-0.5 -0.3,-0.8 -1,-0.8 l -1.1,-0.1 c -1.3,-0.1 -2.1,-0.7 -2.1,-2 0,-1.4 1.2,-2.2 2.7,-2.2 1.1,0 2,0.2 2.6,0.8 l -0.9,0.9 c -0.4,-0.4 -1.1,-0.5 -1.8,-0.5 -0.9,0 -1.3,0.4 -1.3,0.9 0,0.4 0.2,0.7 1,0.8 l 1.1,0.1 c 1.3,0.1 2.1,0.7 2.1,2 0.2,1.5 -1.1,2.3 -2.8,2.3 z"
id="path40" />
<path
class="st0"
d="m 172.2,101.6 c -1.4,0 -1.9,-0.9 -1.9,-2 v -8 h 1.4 v 7.9 c 0,0.5 0.2,0.8 0.8,0.8 h 0.6 v 1.2 h -0.9 z"
id="path42" />
<path
class="st0"
d="m 173.9,94.4 v -2.7 h 1.6 v 1.5 z"
id="path44" />
<path
class="st0"
d="m 178.9,98.5 c 0,1.2 0.6,2 1.8,2 0.8,0 1.2,-0.2 1.7,-0.7 l 0.9,0.9 c -0.7,0.7 -1.4,1.1 -2.7,1.1 -1.8,0 -3.2,-0.9 -3.2,-3.6 0,-2.3 1.2,-3.6 3,-3.6 1.9,0 3,1.4 3,3.4 v 0.6 h -4.5 z m 3,-2 c -0.2,-0.5 -0.7,-0.9 -1.4,-0.9 -0.7,0 -1.2,0.4 -1.4,0.9 -0.1,0.3 -0.2,0.5 -0.2,1 h 3.2 c 0,-0.5 0,-0.7 -0.2,-1 z"
id="path46" />
<path
class="st0"
d="m 189.9,101.6 v -4.3 c 0,-1.1 -0.6,-1.6 -1.4,-1.6 -0.8,0 -1.5,0.5 -1.5,1.6 v 4.3 h -1.4 v -7.1 h 1.4 v 0.7 c 0.5,-0.5 1.2,-0.8 1.9,-0.8 0.7,0 1.3,0.2 1.8,0.6 0.5,0.5 0.7,1.2 0.7,2 v 4.5 h -1.5 z"
id="path48" />
<path
class="st0"
d="m 196,101.7 c -1.2,0 -2.1,-0.2 -3,-1 l 0.9,-0.9 c 0.6,0.6 1.3,0.7 2,0.7 0.9,0 1.6,-0.3 1.6,-1 0,-0.5 -0.3,-0.8 -1,-0.8 l -1.1,-0.1 c -1.3,-0.1 -2.1,-0.7 -2.1,-2 0,-1.4 1.2,-2.2 2.7,-2.2 1.1,0 2,0.2 2.6,0.8 l -0.9,0.9 c -0.4,-0.4 -1.1,-0.5 -1.8,-0.5 -0.9,0 -1.3,0.4 -1.3,0.9 0,0.4 0.2,0.7 1,0.8 l 1.1,0.1 c 1.3,0.1 2.1,0.7 2.1,2 0.1,1.5 -1.1,2.3 -2.8,2.3 z"
id="path50" />
<path
class="st0"
d="m 201.8,98.5 c 0,1.2 0.6,2 1.8,2 0.8,0 1.2,-0.2 1.7,-0.7 l 0.9,0.9 c -0.7,0.7 -1.4,1.1 -2.7,1.1 -1.8,0 -3.2,-0.9 -3.2,-3.6 0,-2.3 1.2,-3.6 3,-3.6 1.9,0 3,1.4 3,3.4 v 0.6 h -4.5 z m 3,-2 c -0.2,-0.5 -0.7,-0.9 -1.4,-0.9 -0.7,0 -1.2,0.4 -1.4,0.9 -0.1,0.3 -0.2,0.5 -0.2,1 h 3.2 c 0,-0.5 0,-0.7 -0.2,-1 z"
id="path52" />
<path
class="st0"
d="m 208.4,93.1 v -1.5 h 1.5 v 1.5 z m 0.1,8.5 v -7.1 h 1.4 v 7.1 z"
id="path54" />
<path
class="st0"
d="m 214.7,104.5 c -1.1,0 -1.8,-0.3 -2.5,-0.9 l 0.9,-0.9 c 0.4,0.4 0.8,0.6 1.5,0.6 1.2,0 1.7,-0.9 1.7,-1.8 v -0.9 c -0.5,0.6 -1.1,0.8 -1.8,0.8 -0.7,0 -1.3,-0.2 -1.7,-0.6 -0.7,-0.7 -0.8,-1.7 -0.8,-2.9 0,-1.2 0.1,-2.2 0.8,-2.9 0.4,-0.4 1,-0.6 1.7,-0.6 0.8,0 1.3,0.2 1.9,0.8 v -0.8 h 1.4 v 7.1 c -0.1,1.8 -1.2,3 -3.1,3 z m 0.2,-8.8 c -1.3,0 -1.5,1.1 -1.5,2.2 0,1.1 0.2,2.2 1.5,2.2 1.3,0 1.4,-1.1 1.4,-2.2 0,-1.1 -0.2,-2.2 -1.4,-2.2 z"
id="path56" />
<path
class="st0"
d="m 224.5,101.6 v -4.3 c 0,-1.1 -0.6,-1.6 -1.4,-1.6 -0.8,0 -1.5,0.5 -1.5,1.6 v 4.3 h -1.4 v -7.1 h 1.4 v 0.7 c 0.5,-0.5 1.2,-0.8 1.9,-0.8 0.7,0 1.3,0.2 1.8,0.6 0.5,0.5 0.7,1.2 0.7,2 v 4.5 h -1.5 z"
id="path58" />
<path
class="st0"
d="m 229.3,98.5 c 0,1.2 0.6,2 1.8,2 0.8,0 1.2,-0.2 1.7,-0.7 l 0.9,0.9 c -0.7,0.7 -1.4,1.1 -2.7,1.1 -1.8,0 -3.2,-0.9 -3.2,-3.6 0,-2.3 1.2,-3.6 3,-3.6 1.9,0 3,1.4 3,3.4 v 0.6 h -4.5 z m 3,-2 c -0.2,-0.5 -0.7,-0.9 -1.4,-0.9 -0.7,0 -1.2,0.4 -1.4,0.9 -0.1,0.3 -0.2,0.5 -0.2,1 h 3.2 c 0,-0.5 -0.1,-0.7 -0.2,-1 z"
id="path60" />
<path
class="st0"
d="m 244.6,101.6 v -4.3 c 0,-1.1 -0.6,-1.6 -1.4,-1.6 -0.8,0 -1.5,0.5 -1.5,1.5 v 4.4 h -1.4 v -4.3 c 0,-1.1 -0.6,-1.6 -1.4,-1.6 -0.8,0 -1.5,0.5 -1.5,1.6 v 4.3 H 236 v -7.1 h 1.4 v 0.7 c 0.5,-0.5 1.2,-0.8 1.9,-0.8 0.9,0 1.6,0.3 2,1 0.6,-0.7 1.3,-1 2.2,-1 0.7,0 1.4,0.2 1.8,0.6 0.5,0.5 0.8,1.2 0.8,2 v 4.5 h -1.5 z"
id="path62" />
<path
class="st0"
d="m 249.4,98.5 c 0,1.2 0.6,2 1.8,2 0.8,0 1.2,-0.2 1.7,-0.7 l 0.9,0.9 c -0.7,0.7 -1.4,1.1 -2.7,1.1 -1.8,0 -3.2,-0.9 -3.2,-3.6 0,-2.3 1.2,-3.6 3,-3.6 1.9,0 3,1.4 3,3.4 v 0.6 h -4.5 z m 3,-2 c -0.2,-0.5 -0.7,-0.9 -1.4,-0.9 -0.7,0 -1.2,0.4 -1.4,0.9 -0.1,0.3 -0.2,0.5 -0.2,1 h 3.2 c 0,-0.5 -0.1,-0.7 -0.2,-1 z"
id="path64" />
<path
class="st0"
d="m 260.3,101.6 v -4.3 c 0,-1.1 -0.6,-1.6 -1.4,-1.6 -0.8,0 -1.5,0.5 -1.5,1.6 v 4.3 H 256 v -7.1 h 1.4 v 0.7 c 0.5,-0.5 1.2,-0.8 1.9,-0.8 0.7,0 1.3,0.2 1.8,0.6 0.5,0.5 0.7,1.2 0.7,2 v 4.5 h -1.5 z"
id="path66" />
<path
class="st0"
d="m 266.2,101.6 c -1.3,0 -1.9,-1 -1.9,-2 v -3.9 h -0.8 v -1.1 h 0.8 v -2.2 h 1.4 v 2.2 h 1.4 v 1.1 h -1.4 v 3.8 c 0,0.5 0.3,0.8 0.8,0.8 h 0.6 v 1.2 h -0.9 z"
id="path68" />
<path
class="st0"
d="m 274.8,101.7 c -1.2,0 -2.1,-0.2 -3,-1 l 0.9,-0.9 c 0.6,0.6 1.3,0.7 2,0.7 0.9,0 1.6,-0.3 1.6,-1 0,-0.5 -0.3,-0.8 -1,-0.8 l -1.1,-0.1 c -1.3,-0.1 -2.1,-0.7 -2.1,-2 0,-1.4 1.2,-2.2 2.7,-2.2 1.1,0 2,0.2 2.6,0.8 l -0.9,0.9 c -0.4,-0.4 -1.1,-0.5 -1.8,-0.5 -0.9,0 -1.3,0.4 -1.3,0.9 0,0.4 0.2,0.7 1,0.8 l 1.1,0.1 c 1.3,0.1 2.1,0.7 2.1,2 0.2,1.5 -1.1,2.3 -2.8,2.3 z"
id="path70" />
<path
class="st0"
d="m 283.9,101.6 v -0.7 c -0.5,0.5 -1.2,0.8 -1.9,0.8 -0.7,0 -1.3,-0.2 -1.8,-0.6 -0.5,-0.5 -0.7,-1.2 -0.7,-2 v -4.5 h 1.4 v 4.3 c 0,1.1 0.6,1.6 1.4,1.6 0.8,0 1.5,-0.5 1.5,-1.6 v -4.3 h 1.4 v 7.1 h -1.3 z"
id="path72" />
<path
class="st0"
d="m 292.8,101 c -0.4,0.4 -1,0.6 -1.7,0.6 -0.8,0 -1.3,-0.2 -1.9,-0.8 v 3.6 h -1.4 v -10 h 1.4 v 0.8 c 0.5,-0.6 1.1,-0.8 1.9,-0.8 0.7,0 1.3,0.2 1.7,0.6 0.7,0.7 0.8,1.9 0.8,3 0,1.1 -0.1,2.3 -0.8,3 z m -2.1,-5.3 c -1.3,0 -1.5,1.1 -1.5,2.4 0,1.3 0.2,2.4 1.5,2.4 1.3,0 1.5,-1.1 1.5,-2.4 0,-1.3 -0.2,-2.4 -1.5,-2.4 z"
id="path74" />
<path
class="st0"
d="m 296.7,98.5 c 0,1.2 0.6,2 1.8,2 0.8,0 1.2,-0.2 1.7,-0.7 l 0.9,0.9 c -0.7,0.7 -1.4,1.1 -2.7,1.1 -1.8,0 -3.2,-0.9 -3.2,-3.6 0,-2.3 1.2,-3.6 3,-3.6 1.9,0 3,1.4 3,3.4 v 0.6 h -4.5 z m 3,-2 c -0.2,-0.5 -0.7,-0.9 -1.4,-0.9 -0.7,0 -1.2,0.4 -1.4,0.9 -0.1,0.3 -0.2,0.5 -0.2,1 h 3.2 c 0,-0.5 -0.1,-0.7 -0.2,-1 z m -1,-3.3 h -1.1 l 1.1,-2.3 h 1.6 z"
id="path76" />
<path
class="st0"
d="m 307.2,96.2 c -0.3,-0.3 -0.6,-0.5 -1.1,-0.5 -0.8,0 -1.4,0.6 -1.4,1.6 v 4.3 h -1.4 v -7.1 h 1.4 v 0.8 c 0.4,-0.5 1.1,-0.9 1.9,-0.9 0.7,0 1.2,0.2 1.7,0.7 z"
id="path78" />
<path
class="st0"
d="m 309.6,93.1 v -1.5 h 1.5 v 1.5 z m 0,8.5 v -7.1 h 1.4 v 7.1 z"
id="path80" />
<path
class="st0"
d="m 314.5,98.5 c 0,1.2 0.6,2 1.8,2 0.8,0 1.2,-0.2 1.7,-0.7 l 0.9,0.9 c -0.7,0.7 -1.4,1.1 -2.7,1.1 -1.8,0 -3.2,-0.9 -3.2,-3.6 0,-2.3 1.2,-3.6 3,-3.6 1.9,0 3,1.4 3,3.4 v 0.6 h -4.5 z m 3,-2 c -0.2,-0.5 -0.7,-0.9 -1.4,-0.9 -0.7,0 -1.2,0.4 -1.4,0.9 -0.1,0.3 -0.2,0.5 -0.2,1 h 3.2 c 0,-0.5 -0.1,-0.7 -0.2,-1 z"
id="path82" />
<path
class="st0"
d="m 325.4,101.6 v -0.7 c -0.5,0.5 -1.2,0.8 -1.9,0.8 -0.7,0 -1.3,-0.2 -1.8,-0.6 -0.5,-0.5 -0.7,-1.2 -0.7,-2 v -4.5 h 1.4 v 4.3 c 0,1.1 0.6,1.6 1.4,1.6 0.8,0 1.5,-0.5 1.5,-1.6 v -4.3 h 1.4 v 7.1 h -1.3 z"
id="path84" />
<path
class="st0"
d="m 333.1,96.2 c -0.3,-0.3 -0.6,-0.5 -1.1,-0.5 -0.8,0 -1.4,0.6 -1.4,1.6 v 4.3 h -1.4 v -7.1 h 1.4 v 0.8 c 0.4,-0.5 1.1,-0.9 1.9,-0.9 0.7,0 1.2,0.2 1.7,0.7 z"
id="path86" />
</g>
transform="matrix(0.00979287,0,0,-0.00979287,263.62278,68.749182)"
fill="#000000"
stroke="none"
id="g354"
style="fill:#ff3333;fill-opacity:1"><path
d="m 6697,6592 c -16,-17 -17,-163 -17,-1903 0,-2023 -1,-1981 51,-2168 11,-42 41,-119 67,-171 37,-77 61,-110 127,-176 66,-67 97,-89 175,-128 182,-89 353,-116 738,-116 208,0 251,2 270,16 l 22,15 v 373 c 0,349 -1,374 -18,389 -15,14 -40,17 -128,17 -232,0 -316,54 -344,221 -6,42 -10,665 -10,1840 0,1708 -1,1777 -18,1792 -17,15 -63,17 -459,17 -413,0 -441,-1 -456,-18 z"
id="path344"
style="fill:#ff3333;fill-opacity:1" /><path
d="m 4568,5340 c -164,-20 -293,-63 -410,-134 -96,-58 -169,-119 -220,-182 l -43,-54 -5,141 c -4,124 -7,142 -24,155 -16,12 -96,14 -458,14 -425,0 -439,-1 -458,-20 -20,-20 -20,-33 -20,-2250 0,-2217 0,-2230 20,-2250 19,-19 33,-20 458,-20 363,0 442,2 458,14 18,14 19,37 24,765 l 5,752 40,-51 c 48,-61 147,-144 230,-192 148,-85 300,-125 520,-134 583,-27 1002,241 1183,756 73,209 107,414 123,741 13,262 2,610 -26,794 -33,217 -91,416 -163,560 -158,319 -407,508 -762,580 -89,18 -376,27 -472,15 z m 25,-814 c 208,-40 331,-170 393,-413 53,-210 55,-760 4,-973 -29,-120 -87,-234 -151,-298 -119,-119 -325,-169 -524,-127 -242,51 -374,232 -415,565 -13,109 -13,571 0,680 24,199 83,350 171,440 117,118 313,166 522,126 z"
id="path346"
style="fill:#ff3333;fill-opacity:1" /><path
d="m 8747,5262 c -16,-17 -17,-111 -17,-1152 0,-971 2,-1147 16,-1237 91,-615 495,-973 1099,-973 330,0 584,102 782,314 l 62,65 3,-140 c 3,-126 5,-142 22,-155 16,-12 96,-14 458,-14 425,0 439,1 458,20 20,20 20,33 20,1635 0,1602 0,1615 -20,1635 -19,19 -33,20 -458,20 -363,0 -442,-2 -458,-14 -19,-14 -19,-40 -24,-1073 l -5,-1058 -31,-85 c -82,-231 -235,-340 -473,-340 -242,1 -401,131 -474,388 -21,77 -22,83 -25,1112 -2,936 -4,1036 -19,1052 -15,17 -46,18 -458,18 -415,0 -443,-1 -458,-18 z"
id="path350"
style="fill:#ff3333;fill-opacity:1" /><path
d="m 127,4172 c -15,-17 -17,-59 -17,-399 0,-355 1,-381 18,-396 17,-16 103,-17 1030,-17 999,0 1012,0 1032,20 19,19 20,33 20,395 0,362 -1,376 -20,395 -20,20 -33,20 -1033,20 -970,0 -1015,-1 -1030,-18 z"
id="path352"
style="fill:#ff3333;fill-opacity:1" /></g>
<g
id="g102"
transform="translate(-17.6,-46.1)">
transform="translate(100.4,-32.5)">
<g
id="g94">
<path
@ -242,7 +117,7 @@
</g>
<g
id="g110"
transform="translate(-17.6,-46.1)">
transform="translate(-17.6,-32.5)">
<path
class="st1"
d="M 35.4,79.9 H 21.7 c -2.2,0 -4.1,1.8 -4.1,4.1 0,2.2 1.8,4.1 4.1,4.1 h 9.7 v 9.7 c 0,2.2 1.8,4.1 4.1,4.1 1.1,0 2.1,-0.5 2.9,-1.2 0.7,-0.7 1.2,-1.8 1.2,-2.9 V 84.1 c 0,-1.1 -0.5,-2.1 -1.2,-2.9 -0.9,-0.9 -1.9,-1.3 -3,-1.3"
@ -250,7 +125,11 @@
<path
class="st0"
d="M 52,63 H 38.3 c -2.2,0 -4.1,1.8 -4.1,4.1 0,2.2 1.8,4.1 4.1,4.1 H 48 v 9.7 c 0,2.2 1.8,4.1 4.1,4.1 1.1,0 2.1,-0.5 2.9,-1.2 0.7,-0.7 1.2,-1.8 1.2,-2.9 V 67.2 C 56.2,66.1 55.7,65.1 55,64.3 54.1,63.5 53.1,63 52,63"
id="path106" />
id="path106" /><path
class="st1"
d="m 68.7,54.5 h 13.7 c 2.2,0 4.1,-1.8 4.1,-4.100001 0,-2.200001 -1.8,-4.1 -4.1,-4.1 H 72.7 V 36.6 c 0,-2.200001 -1.8,-4.1 -4.1,-4.1 -1.1,0 -2.1,0.5 -2.9,1.2 -0.7,0.7 -1.2,1.8 -1.2,2.9 v 13.7 c 0,1.1 0.5,2.1 1.2,2.9 0.9,0.899999 1.9,1.3 3,1.3"
id="path104-6"
style="fill:#ff3333" />
<path
class="st1"
d="M 68.5,46.1 H 54.8 c -2.2,0 -4.1,1.8 -4.1,4.1 0,2.2 1.8,4.1 4.1,4.1 h 9.7 V 64 c 0,2.2 1.8,4.1 4.1,4.1 1.1,0 2.1,-0.5 2.9,-1.2 0.7,-0.7 1.2,-1.8 1.2,-2.9 V 50.3 c 0,-1.1 -0.5,-2.1 -1.2,-2.9 -0.7,-0.8 -1.8,-1.3 -3,-1.3"

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

75
resources/logo.svg Normal file
View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 21.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
version="1.1"
id="Calque_1"
x="0px"
y="0px"
viewBox="0 0 68.900004 69.400003"
xml:space="preserve"
sodipodi:docname="logo.svg"
width="68.900002"
height="69.400002"
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs115" /><sodipodi:namedview
id="namedview113"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="2.7436242"
inkscape:cx="225.61399"
inkscape:cy="45.195694"
inkscape:window-width="1920"
inkscape:window-height="1057"
inkscape:window-x="1912"
inkscape:window-y="-5"
inkscape:window-maximized="1"
inkscape:current-layer="Calque_1" />
<style
type="text/css"
id="style2">
.st0{fill:#3D566E;}
.st1{fill:#FF3333;}
</style>
<g
id="g110"
transform="translate(-17.6,-32.5)">
<path
class="st1"
d="M 35.4,79.9 H 21.7 c -2.2,0 -4.1,1.8 -4.1,4.1 0,2.2 1.8,4.1 4.1,4.1 h 9.7 v 9.7 c 0,2.2 1.8,4.1 4.1,4.1 1.1,0 2.1,-0.5 2.9,-1.2 0.7,-0.7 1.2,-1.8 1.2,-2.9 V 84.1 c 0,-1.1 -0.5,-2.1 -1.2,-2.9 -0.9,-0.9 -1.9,-1.3 -3,-1.3"
id="path104" />
<path
class="st0"
d="M 52,63 H 38.3 c -2.2,0 -4.1,1.8 -4.1,4.1 0,2.2 1.8,4.1 4.1,4.1 H 48 v 9.7 c 0,2.2 1.8,4.1 4.1,4.1 1.1,0 2.1,-0.5 2.9,-1.2 0.7,-0.7 1.2,-1.8 1.2,-2.9 V 67.2 C 56.2,66.1 55.7,65.1 55,64.3 54.1,63.5 53.1,63 52,63"
id="path106" /><path
class="st1"
d="m 68.7,54.5 h 13.7 c 2.2,0 4.1,-1.8 4.1,-4.100001 0,-2.200001 -1.8,-4.1 -4.1,-4.1 H 72.7 V 36.6 c 0,-2.200001 -1.8,-4.1 -4.1,-4.1 -1.1,0 -2.1,0.5 -2.9,1.2 -0.7,0.7 -1.2,1.8 -1.2,2.9 v 13.7 c 0,1.1 0.5,2.1 1.2,2.9 0.9,0.899999 1.9,1.3 3,1.3"
id="path104-6"
style="fill:#ff3333" />
<path
class="st1"
d="M 68.5,46.1 H 54.8 c -2.2,0 -4.1,1.8 -4.1,4.1 0,2.2 1.8,4.1 4.1,4.1 h 9.7 V 64 c 0,2.2 1.8,4.1 4.1,4.1 1.1,0 2.1,-0.5 2.9,-1.2 0.7,-0.7 1.2,-1.8 1.2,-2.9 V 50.3 c 0,-1.1 -0.5,-2.1 -1.2,-2.9 -0.7,-0.8 -1.8,-1.3 -3,-1.3"
id="path108" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -1,8 +1,5 @@
body, html {
width: 100vw;
height: 100vh;
background-color: gainsboro;
min-height: 100vh;
top: 0px;
left: 0px;
background-color: #EFEFEF;
padding-bottom: 0px;
}

4232
test.json

File diff suppressed because it is too large Load Diff