diff --git a/app/static/css/bulletin-but.css b/app/static/css/releve-but.css similarity index 92% rename from app/static/css/bulletin-but.css rename to app/static/css/releve-but.css index 76b452bd0..2091f17c9 100644 --- a/app/static/css/bulletin-but.css +++ b/app/static/css/releve-but.css @@ -1,245 +1,237 @@ -/* Bulletin BUT, Seb. L. 2021-12-06 */ -/*******************/ -/* Styles généraux */ -/*******************/ -:root{ - --couleurPrincipale: rgb(240,250,255); - --couleurFondTitresUE: rgb(206,255,235); - --couleurFondTitresRes: rgb(125, 170, 255); - --couleurFondTitresSAE: rgb(255, 190, 69); - --couleurSecondaire: #fec; - --couleurIntense: #c09; - --couleurSurlignage: rgba(232, 255, 132, 0.47); -} -body{ - font-family: arial; - background: #f0f0f0; -} -.wait{ - width: 60px; - height: 6px; - margin: auto; - background: #424242; /* la réponse à tout */ - animation: wait .4s infinite alternate; -} -@keyframes wait{ - 100%{transform: translateY(40px) rotate(1turn);} -} -main{ - max-width: 1000px; - margin: auto; - display: none; -} -.ready .wait{display: none;} -.ready main{display: block;} -h2{ - margin: 0; - color: black; -} -section{ - background: #FFF; - border-radius: 16px; - border: 1px solid #AAA; - padding: 16px 32px; - margin: 8px 0; -} -section>div:nth-child(1){ - display: flex; - justify-content: space-between; - align-items: center; - gap: 8px; -} -.CTA_Liste{ - display: flex; - gap: 4px; - align-items: center; - background: var(--couleurIntense); - color: #FFF; - padding: 4px 8px; - border-radius: 4px; - box-shadow: 0 2px 2px rgba(0,0,0,0.26); - cursor: pointer; -} -.CTA_Liste>svg{ - transition: 0.2s; -} -.CTA_Liste:hover{ - outline: 2px solid #424242; -} -.listeOff svg{ - transform: rotate(180deg); -} -.listeOff .syntheseModule, -.listeOff .eval{ - display: none; -} - -/***********************/ -/* Options d'affichage */ -/***********************/ -.hide_abs .absences, -.hide_abs_modules .module>.absences, -.hide_coef .synthese em, -.hide_coef .eval>em, -.hide_date_inscr .dateInscription, -.hide_ects .ects - -{ - display: none; -} - -/************/ -/* Etudiant */ -/************/ -.etudiant{ - display: flex; - align-items: center; - gap: 16px; - border-color: var(--couleurPrincipale); - background: var(--couleurPrincipale); - color: rgb(0, 0, 0); -} -.civilite{ - font-weight: bold; - font-size: 130%; -} - -/************/ -/* Semestre */ -/************/ -.infoSemestre{ - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 4px; -} -.infoSemestre>div{ - border: 1px solid var(--couleurIntense); - padding: 4px 8px; - border-radius: 4px; - display: grid; - grid-template-columns: auto auto; - column-gap: 4px; -} -.infoSemestre>div:nth-child(1){ - margin-right: auto; -} -.infoSemestre>div>div:nth-child(even){ - text-align: right; -} -.rang{ - text-decoration: underline var(--couleurIntense); -} - -.enteteSemestre{ - color: black; - font-weight: bold; - font-size: 20px; - margin-bottom: 4px; -} - -/***************/ -/* Synthèse */ -/***************/ -.synthese>.ue{ - background: var(--couleurFondTitresUE); -} -.synthese h3{ - background: var(--couleurFondTitresUE); -} -.synthese em, -.eval em{ - opacity: 0.6; - width: 70px; - display: inline-block; -} - -/***************/ -/* Evaluations */ -/***************/ -.module, .ue { - background: var(--couleurSecondaire); - color: #000; - padding: 4px 32px; - border-radius: 4px; - display: flex; - gap: 16px; - margin: 4px 0 2px 0; - overflow: auto; -} -.sae .module, .sae .module h3 { - background: #d3ffff; -} -h3{ - display: flex; - align-items: center; - margin: 0 auto 0 0; - position: sticky; - left: -32px; - z-index: 1; - font-size: 16px; - background: var(--couleurSecondaire); -} - -.moyenne{ - font-weight: bold; - text-align: right; -} -.info{ - opacity: 0.9; -} -.eval, .syntheseModule{ - position: relative; - display: flex; - justify-content: space-between; - margin: 0 28px; - padding: 0px 4px; - border-bottom: 1px solid #aaa; -} -.eval:hover, .syntheseModule:hover{ - background: var(--couleurSurlignage); - /* color: #FFF; */ -} -.complement{ - pointer-events:none; - position: absolute; - bottom: 100%; - right: 0; - padding: 8px; - border-radius: 4px; - background: #FFF; - color: #000; - border: 1px solid var(--couleurIntense); - opacity: 0; - display: grid; - grid-template-columns: auto auto; - column-gap: 4px; -} -.eval:hover .complement{ - opacity: 1; - z-index: 1; -} -.complement>div:nth-child(even){ - text-align: right; -} -.complement>div:nth-child(1), -.complement>div:nth-child(2){ - font-weight: bold; -} -.complement>div:nth-child(1), -.complement>div:nth-child(7){ - margin-bottom: 8px; -} - -.absences{ - display: grid; - grid-template-columns: auto auto; - column-gap: 4px; - text-align: right; - border-left: 1px solid; - padding-left: 16px; -} -.absences>div:nth-child(1), -.absences>div:nth-child(2){ - font-weight: bold; +/* Bulletin BUT, Seb. L. 2021-12-06 */ +/*******************/ +/* Styles généraux */ +/*******************/ +.wait{ + width: 60px; + height: 6px; + margin: auto; + background: #424242; /* la réponse à tout */ + animation: wait .4s infinite alternate; +} +@keyframes wait{ + 100%{transform: translateY(40px) rotate(1turn);} +} +main{ + --couleurPrincipale: rgb(240,250,255); + --couleurFondTitresUE: rgb(206,255,235); + --couleurFondTitresRes: rgb(125, 170, 255); + --couleurFondTitresSAE: rgb(255, 190, 69); + --couleurSecondaire: #fec; + --couleurIntense: #c09; + --couleurSurlignage: rgba(232, 255, 132, 0.47); + max-width: 1000px; + margin: auto; + display: none; +} +.ready .wait{display: none;} +.ready main{display: block;} +h2{ + margin: 0; + color: black; +} +section{ + background: #FFF; + border-radius: 16px; + border: 1px solid #AAA; + padding: 16px 32px; + margin: 8px 0; +} +section>div:nth-child(1){ + display: flex; + justify-content: space-between; + align-items: center; + gap: 8px; +} +.CTA_Liste{ + display: flex; + gap: 4px; + align-items: center; + background: var(--couleurIntense); + color: #FFF; + padding: 4px 8px; + border-radius: 4px; + box-shadow: 0 2px 2px rgba(0,0,0,0.26); + cursor: pointer; +} +.CTA_Liste>svg{ + transition: 0.2s; +} +.CTA_Liste:hover{ + outline: 2px solid #424242; +} +.listeOff svg{ + transform: rotate(180deg); +} +.listeOff .syntheseModule, +.listeOff .eval{ + display: none; +} + +/***********************/ +/* Options d'affichage */ +/***********************/ +.hide_abs .absences, +.hide_abs_modules .module>.absences, +.hide_coef .synthese em, +.hide_coef .eval>em, +.hide_date_inscr .dateInscription, +.hide_ects .ects{ + display: none; +} + +/************/ +/* Etudiant */ +/************/ +.etudiant{ + display: flex; + align-items: center; + gap: 16px; + border-color: var(--couleurPrincipale); + background: var(--couleurPrincipale); + color: rgb(0, 0, 0); +} +.civilite{ + font-weight: bold; + font-size: 130%; +} + +/************/ +/* Semestre */ +/************/ +.infoSemestre{ + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 4px; +} +.infoSemestre>div{ + border: 1px solid var(--couleurIntense); + padding: 4px 8px; + border-radius: 4px; + display: grid; + grid-template-columns: auto auto; + column-gap: 4px; +} +.infoSemestre>div:nth-child(1){ + margin-right: auto; +} +.infoSemestre>div>div:nth-child(even){ + text-align: right; +} +.rang{ + text-decoration: underline var(--couleurIntense); +} + +.enteteSemestre{ + color: black; + font-weight: bold; + font-size: 20px; + margin-bottom: 4px; +} + +/***************/ +/* Synthèse */ +/***************/ +.synthese>.ue{ + background: var(--couleurFondTitresUE); +} +.synthese h3{ + background: var(--couleurFondTitresUE); +} +.synthese em, +.eval em{ + opacity: 0.6; + width: 70px; + display: inline-block; +} + +/***************/ +/* Evaluations */ +/***************/ +.module, .ue { + background: var(--couleurSecondaire); + color: #000; + padding: 4px 32px; + border-radius: 4px; + display: flex; + gap: 16px; + margin: 4px 0 2px 0; + overflow: auto; +} +h3{ + display: flex; + align-items: center; + margin: 0 auto 0 0; + position: sticky; + left: -32px; + z-index: 1; + font-size: 16px; + background: var(--couleurSecondaire); +} +.sae .module, .sae h3{ + background: var(--couleurFondTitresSAE); +} + +.moyenne{ + font-weight: bold; + text-align: right; +} +.info{ + opacity: 0.9; +} +.eval, .syntheseModule{ + position: relative; + display: flex; + justify-content: space-between; + margin: 0 28px; + padding: 0px 4px; + border-bottom: 1px solid #aaa; +} +.eval:hover, .syntheseModule:hover{ + background: var(--couleurSurlignage); + /* color: #FFF; */ +} +.complement{ + pointer-events:none; + position: absolute; + bottom: 100%; + right: 0; + padding: 8px; + border-radius: 4px; + background: #FFF; + color: #000; + border: 1px solid var(--couleurIntense); + opacity: 0; + display: grid; + grid-template-columns: auto auto; + column-gap: 4px; +} +.eval:hover .complement{ + opacity: 1; + z-index: 1; +} +.complement>div:nth-child(even){ + text-align: right; +} +.complement>div:nth-child(1), +.complement>div:nth-child(2){ + font-weight: bold; +} +.complement>div:nth-child(1), +.complement>div:nth-child(7){ + margin-bottom: 8px; +} + +.absences{ + display: grid; + grid-template-columns: auto auto; + column-gap: 4px; + text-align: right; + border-left: 1px solid; + padding-left: 16px; +} +.absences>div:nth-child(1), +.absences>div:nth-child(2){ + font-weight: bold; } \ No newline at end of file diff --git a/app/static/js/bulletin-but.js b/app/static/js/bulletin-but.js deleted file mode 100644 index cd562fe12..000000000 --- a/app/static/js/bulletin-but.js +++ /dev/null @@ -1,242 +0,0 @@ -/* Il manque : - - rangs - - Synthèse : moyenne UE - - Synthèse : min, max, moy classe - - Synthèse : absences - - Eval : absences - -Moi : - "show_codemodules" :true, - "show_minmax": true, - "show_minmax_eval": true, - "show_minmax_mod": false, - "show_mod_rangs": false, - "show_moypromo": true, - "show_rangs": true, - "show_ue_cap_current": true, - "show_ue_cap_details": true, - "show_ue_rangs": true, - "show_uevalid": true, -*/ -/*****************************/ -/* Gestionnaire d'événements */ -/*****************************/ -document.querySelectorAll(".CTA_Liste").forEach(e => { - e.addEventListener("click", listeOnOff) -}) - -function listeOnOff() { - this.parentElement.parentElement.classList.toggle("listeOff") -} -/*****************************/ -/* Recupération et affichage */ -/*****************************/ - -fetch(dataSrc) - .then(r => { return r.json() }) - .then(json => showData(json)) - -function showData(data) { - showInformations(data); - showSemestre(data); - showSynthese(data); - showEvaluations(data); - - setOptions(data.options); - - document.body.classList.add("ready"); -} - -/********************************/ -/* Informations sur l'étudiant */ -/********************************/ -function showInformations(data) { - document.querySelector(".studentPic").src = data.etudiant.photo_url || "default_Student.svg"; - - let output = ` -
-
- ${civilite(data.etudiant.civilite)} - ${data.etudiant.nom} - ${data.etudiant.prenom}`; - - if (data.etudiant.date_naissance) { - output += `né${(data.etudiant.civilite == "F") ? "e" : ""} le ${ISOToDate(data.etudiant.date_naissance)}`; - } - - output += ` -
-
- Numéro étudiant : ${data.etudiant.code_nip} - Code INE : ${data.etudiant.code_ine} -
-
${data.formation.titre}
- -
- `; - - document.querySelector(".infoEtudiant").innerHTML = output; -} - -/*******************************/ -/* Information sur le semestre */ -/*******************************/ -function showSemestre(data) { - document.querySelector("h2").innerHTML += data.semestre.numero; - document.querySelector(".dateInscription").innerHTML += ISOToDate(data.semestre.inscription); - let output = ` -
-
Moyenne
${data.semestre.notes.value}
-
Rang :
${data.semestre.rang.value} / ${data.semestre.rang.total}
-
Max. promo. :
${data.semestre.notes.max}
-
Moy. promo. :
${data.semestre.notes.moy}
-
Min. promo. :
${data.semestre.notes.min}
-
- ${data.semestre.groupes.map(groupe => { - return ` -
-
Groupe
${groupe.nom}
-
Rang :
${groupe.rang.value} / ${groupe.rang.total}
-
Max. groupe :
${groupe.notes.max}
-
Moy. groupe :
${groupe.notes.min}
-
Min. groupe :
${groupe.notes.min}
-
- `; - }).join("") - } - `; - document.querySelector(".infoSemestre").innerHTML = output; -} - -/*******************************/ -/* Synthèse */ -/*******************************/ -function showSynthese(data) { - let output = ``; - Object.entries(data.ues).forEach(([ue, dataUE]) => { - output += ` -
-

- ${(dataUE.competence) ? dataUE.competence + " - " : ""}${ue} -

-
-
Moyenne : ${dataUE.moyenne?.value || "-"}
-
- Bonus : ${dataUE.bonus || 0} - - Malus : ${dataUE.malus || 0} -  - - ECTS : ${dataUE.ECTS.acquis} / ${dataUE.ECTS.total} - -
-
-
-
Abs N.J.
${dataUE.absences?.injustifie || 0}
-
Total
${dataUE.absences?.total || 0}
-
-
- ${synthese(dataUE.ressources)} - ${synthese(dataUE.saes)} - `; - }); - document.querySelector(".synthese").innerHTML = output; - - function synthese(modules) { - let output = ""; - Object.entries(modules).forEach(([module, dataModule]) => { - let titre = data.ressources[module]?.titre || data.saes[module]?.titre; - let url = data.ressources[module]?.url || data.saes[module]?.url; - output += ` -
-
${module} - ${titre}
-
- ${dataModule.moyenne} - Coef. ${dataModule.coef} -
-
- `; - }) - return output; - } -} -/*******************************/ -/* Evaluations */ -/*******************************/ -function showEvaluations(data) { - document.querySelector(".evaluations").innerHTML = module(data.ressources); - document.querySelector(".sae").innerHTML += module(data.saes); - - function module(module) { - let output = ""; - Object.entries(module).forEach(([numero, content]) => { - output += ` -
-
-

${numero} - ${content.titre}

- -
-
Abs inj.
${content.absences?.injustifie || 0}
-
Total
${content.absences?.total || 0}
-
-
- ${evaluation(content.evaluations)} -
- `; - }) - return output; - } - - function evaluation(evaluations) { - let output = ""; - evaluations.forEach(eval => { - output += ` -
-
${eval.description}
-
- ${eval.note.value} - Coef. ${eval.coef} -
-
-
Coef
${eval.coef}
-
Max. promo.
${eval.note.max}
-
Moy. promo.
${eval.note.moy}
-
Min. promo.
${eval.note.min}
- ${Object.entries(eval.poids).map(([UE, poids]) => { - return ` -
Poids ${UE}
-
${poids}
- `; - }).join("")} -
-
- `; - }) - return output; - } -} - -/********************/ -/* Options */ -/********************/ -function setOptions(options) { - Object.entries(options).forEach(([option, value]) => { - if (value === false) { - document.body.classList.add(option.replace("show", "hide")) - } - }) -} - - -/********************/ -/* Fonctions d'aide */ -/********************/ -function civilite(txt) { - switch (txt) { - case "M": return "M."; - case "F": return "Mme"; - default: return ""; - } -} - -function ISOToDate(ISO) { - return ISO.split("-").reverse().join("/"); -} diff --git a/app/static/js/releve-but.js b/app/static/js/releve-but.js new file mode 100644 index 000000000..123a4cc4e --- /dev/null +++ b/app/static/js/releve-but.js @@ -0,0 +1,329 @@ +class releveBUT extends HTMLElement { + constructor(){ + super(); + this.shadow = this.attachShadow({mode: 'open'}); + + /* Config par defaut */ + this.config = { + showURL: true + }; + + /* Template du module */ + this.shadow.innerHTML = this.template(); + + /* Style du module */ + const styles = document.createElement('link'); + styles.setAttribute('rel', 'stylesheet'); + styles.setAttribute('href', '/ScoDoc/static/css/releve-but.css'); + this.shadow.appendChild(styles); + + this.shadow.querySelectorAll(".CTA_Liste").forEach(e => { + e.addEventListener("click", this.listeOnOff) + }) + + + } + listeOnOff() { + this.parentElement.parentElement.classList.toggle("listeOff") + } + + set setConfig(config){ + this.config.showURL = config.showURL ?? this.config.showURL; + } + + set showData(data) { + this.showInformations(data); + this.showSemestre(data); + this.showSynthese(data); + this.showEvaluations(data); + + this.setOptions(data.options); + + this.shadow.children[0].classList.add("ready"); + } + + + template(){ + return ` +
+
+
+ + + +
+ Photo de l'étudiant +
+
+ + + + +
+

Semestre

+
Inscrit le
+ Les moyennes servent à situer l'étudiant dans la promotion et ne correspondent pas à des validations de + compétences ou d'UE. +
+
+ + + + +
+
+
+

Synthèse

+ La moyenne des ressources dans une UE dépend des poids donnés aux évaluations. +
+
+ Liste + + +
+
+
+
+ + + + +
+
+

Ressources

+
+ Liste + + +
+
+
+
+ +
+
+

SAÉ

+
+ Liste + + +
+
+
+
+ +
+
`; + } + + /********************************/ + /* Informations sur l'étudiant */ + /********************************/ + showInformations(data) { + this.shadow.querySelector(".studentPic").src = data.etudiant.photo_url || "default_Student.svg"; + + let output = ` +
+
+ ${this.civilite(data.etudiant.civilite)} + ${data.etudiant.nom} + ${data.etudiant.prenom}`; + + if (data.etudiant.date_naissance) { + output += ` né${(data.etudiant.civilite == "F") ? "e" : ""} le ${this.ISOToDate(data.etudiant.date_naissance)}`; + } + + output += ` +
+
+ Numéro étudiant : ${data.etudiant.code_nip} - + Code INE : ${data.etudiant.code_ine} +
+
${data.formation.titre}
+
+ `; + + this.shadow.querySelector(".infoEtudiant").innerHTML = output; + } + + /*******************************/ + /* Information sur le semestre */ + /*******************************/ + showSemestre(data) { + this.shadow.querySelector("h2").innerHTML += data.semestre.numero; + this.shadow.querySelector(".dateInscription").innerHTML += this.ISOToDate(data.semestre.inscription); + let output = ` +
+
Moyenne
${data.semestre.notes.value}
+
Rang :
${data.semestre.rang.value} / ${data.semestre.rang.total}
+
Max. promo. :
${data.semestre.notes.max}
+
Moy. promo. :
${data.semestre.notes.moy}
+
Min. promo. :
${data.semestre.notes.min}
+
+ ${data.semestre.groupes.map(groupe => { + return ` +
+
Groupe
${groupe.nom}
+
Rang :
${groupe.rang.value} / ${groupe.rang.total}
+
Max. groupe :
${groupe.notes.max}
+
Moy. groupe :
${groupe.notes.min}
+
Min. groupe :
${groupe.notes.min}
+
+ `; + }).join("") + } + `; + this.shadow.querySelector(".infoSemestre").innerHTML = output; + } + + /*******************************/ + /* Synthèse */ + /*******************************/ + showSynthese(data) { + let output = ``; + Object.entries(data.ues).forEach(([ue, dataUE]) => { + output += ` +
+

+ ${(dataUE.competence) ? dataUE.competence + " - " : ""}${ue} +

+
+
Moyenne : ${dataUE.moyenne?.value || "-"}
+
+ Bonus : ${dataUE.bonus || 0} - + Malus : ${dataUE.malus || 0} +  - + ECTS : ${dataUE.ECTS.acquis} / ${dataUE.ECTS.total} + +
+
+
+
Abs N.J.
${dataUE.absences?.injustifie || 0}
+
Total
${dataUE.absences?.total || 0}
+
+
+ ${this.synthese(data, dataUE.ressources)} + ${this.synthese(data, dataUE.saes)} + `; + }); + this.shadow.querySelector(".synthese").innerHTML = output; + } + synthese(data, modules) { + let output = ""; + Object.entries(modules).forEach(([module, dataModule]) => { + let titre = data.ressources[module]?.titre || data.saes[module]?.titre; + let url = data.ressources[module]?.url || data.saes[module]?.url; + output += ` +
+
${this.URL(url, `${module} - ${titre}`)}
+
+ ${dataModule.moyenne} + Coef. ${dataModule.coef} +
+
+ `; + }) + return output; + } + + /*******************************/ + /* Evaluations */ + /*******************************/ + showEvaluations(data) { + this.shadow.querySelector(".evaluations").innerHTML = this.module(data.ressources); + this.shadow.querySelector(".sae").innerHTML += this.module(data.saes); + } + module(module) { + let output = ""; + Object.entries(module).forEach(([numero, content]) => { + output += ` +
+
+

${this.URL(content.url, `${numero} - ${content.titre}`)}

+
+
Moyenne indicative : ${content.moyenne.value}
+
+ Classe : ${content.moyenne.moy} - + Max : ${content.moyenne.max} - + Min : ${content.moyenne.min} +
+
+
+
Abs inj.
${content.absences?.injustifie || 0}
+
Total
${content.absences?.total || 0}
+
+
+ ${this.evaluation(content.evaluations)} +
+ `; + }) + return output; + } + + evaluation(evaluations) { + let output = ""; + evaluations.forEach((evaluation) => { + output += ` +
+
${this.URL(evaluation.url, evaluation.description)}
+
+ ${evaluation.note.value} + Coef. ${evaluation.coef} +
+
+
Coef
${evaluation.coef}
+
Max. promo.
${evaluation.note.max}
+
Moy. promo.
${evaluation.note.moy}
+
Min. promo.
${evaluation.note.min}
+ ${Object.entries(evaluation.poids).map(([UE, poids]) => { + return ` +
Poids ${UE}
+
${poids}
+ `; + }).join("")} +
+
+ `; + }) + return output; + } + + /********************/ + /* Options */ + /********************/ + setOptions(options) { + Object.entries(options).forEach(([option, value]) => { + if (value === false) { + document.body.classList.add(option.replace("show", "hide")) + } + }) + } + + + /********************/ + /* Fonctions d'aide */ + /********************/ + URL(href, content){ + if(this.config.showURL){ + return `${content}`; + } else { + return content; + } + } + civilite(txt) { + switch (txt) { + case "M": return "M."; + case "F": return "Mme"; + default: return ""; + } + } + + ISOToDate(ISO) { + return ISO.split("-").reverse().join("/"); + } + +} +customElements.define('releve-but', releveBUT); \ No newline at end of file diff --git a/app/templates/but/bulletin.html b/app/templates/but/bulletin.html index a82e28bf3..6ade88c0c 100644 --- a/app/templates/but/bulletin.html +++ b/app/templates/but/bulletin.html @@ -2,87 +2,32 @@ {% block styles %} {{super()}} - {% endblock %} {% block app_content %} -
-
- - - -
- Photo de l'étudiant -
-
+ - - - -
-

Semestre

-
Inscrit le
- Les moyennes servent à situer l'étudiant dans la promotion et ne correspondent pas à des validations de - compétences ou d'UE. -
-
- - - - -
-
-
-

Synthèse

- La moyenne des ressources dans une UE dépend des poids donnés aux évaluations. -
-
- Liste - - -
-
-
-
- - - - -
-
-

Ressources

-
- Liste - - -
-
-
-
- -
-
-

SAÉ

-
- Liste - - -
-
-
-
- -
{% endblock %} {% block scripts %} {{ super() }} + + - {% endblock %} \ No newline at end of file