10 Commits
18 changed files with 1249 additions and 1370 deletions

No files matched your search

+2 -2
View File
@@ -1,7 +1,7 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.16.0
rev: v0.16.10
hooks:
- id: ruff-check # just check the code, and print the errors
- id: ruff-check # actually fix the fixable errors, but print nothing
@@ -12,7 +12,7 @@ repos:
rev: v0.6.1
hooks:
- id: biome-check
additional_dependencies: ["@biomejs/biome@2.5.1"]
additional_dependencies: ["@biomejs/biome@2.5.15"]
- repo: https://github.com/rtts/djhtml
rev: 3.0.11
hooks:
+1
View File
@@ -42,6 +42,7 @@ details.accordion>.accordion-content {
background: #ffffff;
color: #333333;
padding: 1em 2.2em;
margin-top: 0;
border: 1px solid #dddddd;
border-bottom-right-radius: 3px;
border-bottom-left-radius: 3px;
+82 -72
View File
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-09-21 13:16+0200\n"
"POT-Creation-Date: 2026-10-02 12:56+0200\n"
"PO-Revision-Date: 2016-07-18\n"
"Last-Translator: Maréchal <thomas.girod@utbm.fr\n"
"Language-Team: AE info <ae.info@utbm.fr>\n"
@@ -832,7 +832,7 @@ msgstr "Méthode de paiement"
#: counter/templates/counter/last_ops.jinja
#: election/templates/election/election_detail.jinja
#: forum/templates/forum/macros.jinja
#: pedagogy/templates/pedagogy/fragments/ue_details/comments.jinja
#: pedagogy/templates/pedagogy/fragments/ue_detail/comments.jinja
#: pedagogy/templates/pedagogy/guide.jinja sas/templates/sas/album.jinja
#: sas/templates/sas/moderation.jinja sas/templates/sas/picture.jinja
#: trombi/templates/trombi/detail.jinja
@@ -1028,7 +1028,7 @@ msgstr "Outils"
#: counter/templates/counter/counter_list.jinja
#: election/templates/election/election_detail.jinja
#: forum/templates/forum/macros.jinja
#: pedagogy/templates/pedagogy/fragments/ue_details/comments.jinja
#: pedagogy/templates/pedagogy/fragments/ue_detail/comments.jinja
#: pedagogy/templates/pedagogy/guide.jinja sas/templates/sas/album.jinja
#: trombi/templates/trombi/detail.jinja
#: trombi/templates/trombi/edit_profile.jinja
@@ -1285,8 +1285,9 @@ msgstr "Actions"
#: com/templates/com/mailing_admin.jinja com/templates/com/poster_list.jinja
#: core/templates/core/file_detail.jinja
#: core/templates/core/file_moderation.jinja sas/templates/sas/moderation.jinja
#: sas/templates/sas/picture.jinja
#: core/templates/core/file_moderation.jinja
#: pedagogy/templates/pedagogy/fragments/ue_detail/comments.jinja
#: sas/templates/sas/moderation.jinja sas/templates/sas/picture.jinja
msgid "Moderate"
msgstr "Modérer"
@@ -1588,7 +1589,6 @@ msgstr "Descendre"
#: com/templates/com/weekmail_preview.jinja
#: core/templates/core/user_account_detail.jinja
#: pedagogy/templates/pedagogy/ue_detail.jinja
#: trombi/templates/trombi/comment_moderation.jinja
#: trombi/templates/trombi/export.jinja
msgid "Back"
@@ -1933,8 +1933,8 @@ msgstr ""
"toujours le voir."
#: core/models.py
msgid "ToS approved"
msgstr "CGU approuvées"
msgid "ToS approved at"
msgstr "CGU approuvées le"
#: core/models.py
msgid "A user with that username already exists"
@@ -1943,7 +1943,9 @@ msgstr "Un utilisateur de ce nom d'utilisateur existe déjà"
#: core/models.py core/templates/core/macros.jinja
#: core/templates/core/user_detail.jinja core/templates/core/user_edit.jinja
#: election/templates/election/election_detail.jinja
#: forum/templates/forum/macros.jinja trombi/templates/trombi/user_tools.jinja
#: forum/templates/forum/macros.jinja
#: pedagogy/templates/pedagogy/fragments/ue_detail/comments.jinja
#: trombi/templates/trombi/user_tools.jinja
msgid "Profile"
msgstr "Profil"
@@ -2374,7 +2376,6 @@ msgstr "Propriétés"
#: core/templates/core/file_delete_confirm.jinja
#: counter/templates/counter/fragments/delete_student_card.jinja
#: pedagogy/templates/pedagogy/fragments/ue_details/comments.jinja
#, python-format
msgid "Are you sure you want to delete \"%(obj)s\"?"
msgstr "Êtes-vous sûr de vouloir supprimer \"%(obj)s\" ?"
@@ -3907,7 +3908,6 @@ msgid "Emptied"
msgstr "Coffre vidé"
#: counter/templates/counter/cash_summary_list.jinja counter/views/cash.py
#: pedagogy/templates/pedagogy/fragments/ue_comment_form.jinja
#: pedagogy/templates/pedagogy/moderation.jinja
#: trombi/templates/trombi/comment.jinja
#: trombi/templates/trombi/user_tools.jinja
@@ -5239,6 +5239,7 @@ msgid "reporter"
msgstr "signalant"
#: pedagogy/templates/pedagogy/fragments/comment_report.jinja
#: pedagogy/templates/pedagogy/fragments/ue_detail/comments.jinja
msgid "Report"
msgstr "Signaler"
@@ -5246,45 +5247,46 @@ msgstr "Signaler"
msgid "Leave comment"
msgstr "Laisser un commentaire"
#: pedagogy/templates/pedagogy/fragments/ue_details/comments.jinja
#: pedagogy/templates/pedagogy/fragments/ue_detail/comments.jinja
#: trombi/templates/trombi/export.jinja
msgid "Comments"
msgstr "Commentaires"
#: pedagogy/templates/pedagogy/fragments/ue_details/comments.jinja
#: pedagogy/templates/pedagogy/fragments/ue_details/grade.jinja
msgid "Global grade"
msgstr "Note globale"
#: pedagogy/templates/pedagogy/fragments/ue_details/comments.jinja
#: pedagogy/templates/pedagogy/fragments/ue_details/grade.jinja
msgid "Utility"
msgstr "Utilité"
#: pedagogy/templates/pedagogy/fragments/ue_details/comments.jinja
#: pedagogy/templates/pedagogy/fragments/ue_details/grade.jinja
msgid "Interest"
msgstr "Intérêt"
#: pedagogy/templates/pedagogy/fragments/ue_details/comments.jinja
#: pedagogy/templates/pedagogy/fragments/ue_details/grade.jinja
msgid "Teaching"
msgstr "Enseignement"
#: pedagogy/templates/pedagogy/fragments/ue_details/comments.jinja
#: pedagogy/templates/pedagogy/fragments/ue_details/grade.jinja
msgid "Work load"
msgstr "Charge de travail"
#: pedagogy/templates/pedagogy/fragments/ue_details/comments.jinja
#: pedagogy/templates/pedagogy/fragments/ue_detail/comments.jinja
msgid "This comment has been reported"
msgstr "Ce commentaire a été signalé"
#: pedagogy/templates/pedagogy/fragments/ue_details/comments.jinja
msgid "Report this comment"
msgstr "Signaler ce commentaire"
#: pedagogy/templates/pedagogy/fragments/ue_detail/comments.jinja
msgid "It will be hidden until moderated."
msgstr "Il sera caché tant qu'il ne sera pas modéré."
#: pedagogy/templates/pedagogy/fragments/ue_details/form.jinja
#: pedagogy/templates/pedagogy/fragments/ue_detail/comments.jinja
#: pedagogy/templates/pedagogy/fragments/ue_detail/grade.jinja
msgid "Global grade"
msgstr "Note globale"
#: pedagogy/templates/pedagogy/fragments/ue_detail/comments.jinja
#: pedagogy/templates/pedagogy/fragments/ue_detail/grade.jinja
msgid "Utility"
msgstr "Utilité"
#: pedagogy/templates/pedagogy/fragments/ue_detail/comments.jinja
#: pedagogy/templates/pedagogy/fragments/ue_detail/grade.jinja
msgid "Interest"
msgstr "Intérêt"
#: pedagogy/templates/pedagogy/fragments/ue_detail/comments.jinja
#: pedagogy/templates/pedagogy/fragments/ue_detail/grade.jinja
msgid "Teaching"
msgstr "Enseignement"
#: pedagogy/templates/pedagogy/fragments/ue_detail/comments.jinja
#: pedagogy/templates/pedagogy/fragments/ue_detail/grade.jinja
msgid "Workload"
msgstr "Charge de travail"
#: pedagogy/templates/pedagogy/fragments/ue_detail/ue_detail.jinja
#: pedagogy/templates/pedagogy/ue_detail.jinja
msgid ""
"You already posted a comment on this UE. If you want to comment again, "
"please modify or delete your previous comment."
@@ -5292,26 +5294,6 @@ msgstr ""
"Vous avez déjà commenté cette UE. Si vous voulez de nouveau commenter, "
"veuillez modifier ou supprimer votre commentaire précédent."
#: pedagogy/templates/pedagogy/fragments/ue_details/grade.jinja
msgid "Objectives"
msgstr "Objectifs"
#: pedagogy/templates/pedagogy/fragments/ue_details/grade.jinja
msgid "Program"
msgstr "Programme"
#: pedagogy/templates/pedagogy/fragments/ue_details/grade.jinja
msgid "Earned skills"
msgstr "Compétences acquises"
#: pedagogy/templates/pedagogy/fragments/ue_details/grade.jinja
msgid "Key concepts"
msgstr "Concepts clefs"
#: pedagogy/templates/pedagogy/fragments/ue_details/grade.jinja
msgid "UE manager: "
msgstr "Gestionnaire d'UE : "
#: pedagogy/templates/pedagogy/guide.jinja
msgid "A guide of courses available at UTBM."
msgstr "Un guide de tous les cours disponibles à l'UTBM."
@@ -5377,24 +5359,52 @@ msgid "UE Details"
msgstr "Détails d'UE"
#: pedagogy/templates/pedagogy/ue_detail.jinja
msgid "CM: "
msgstr "CM : "
msgid "Category"
msgstr "Catégorie"
#: pedagogy/templates/pedagogy/ue_detail.jinja
msgid "TD: "
msgstr "TD : "
msgid "Credits"
msgstr "Crédits"
#: pedagogy/templates/pedagogy/ue_detail.jinja
msgid "TP: "
msgstr "TP : "
msgid "Lectures"
msgstr "Cours magistraux"
#: pedagogy/templates/pedagogy/ue_detail.jinja
msgid "TE: "
msgstr "TE : "
msgid "Tutorials"
msgstr "Travaux dirigés"
#: pedagogy/templates/pedagogy/ue_detail.jinja
msgid "THE: "
msgstr "THE : "
msgid "Practicals"
msgstr "Travaux pratiques"
#: pedagogy/templates/pedagogy/ue_detail.jinja
msgid "Work without supervision"
msgstr "Travail hors encadrement"
#: pedagogy/templates/pedagogy/ue_detail.jinja
msgid "Availability"
msgstr "Disponibilité"
#: pedagogy/templates/pedagogy/ue_detail.jinja
msgid "Manager"
msgstr "Responsable"
#: pedagogy/templates/pedagogy/ue_detail.jinja
msgid "Objectives"
msgstr "Objectifs"
#: pedagogy/templates/pedagogy/ue_detail.jinja
msgid "Program"
msgstr "Programme"
#: pedagogy/templates/pedagogy/ue_detail.jinja
msgid "Earned skills"
msgstr "Compétences acquises"
#: pedagogy/templates/pedagogy/ue_detail.jinja
msgid "Key concepts"
msgstr "Concepts clefs"
#: pedagogy/templates/pedagogy/ue_edit.jinja
msgid "Edit UE"
+385 -355
View File
File diff suppressed because it is too large. Load diff
+14 -14
View File
@@ -24,24 +24,24 @@
"#com:*": "./com/static/bundled/*"
},
"devDependencies": {
"@babel/core": "^8.0.1",
"@babel/preset-env": "^8.0.2",
"@biomejs/biome": "^2.5.1",
"@babel/core": "^8.0.6",
"@babel/preset-env": "^8.0.6",
"@biomejs/biome": "^2.5.15",
"@hey-api/openapi-ts": "^0.99.0",
"@types/alpinejs": "^3.13.11",
"@types/alpinejs": "^3.17.0",
"@types/alpinejs__sort": "^3.13.0",
"@types/cytoscape-cxtmenu": "^3.4.5",
"@types/cytoscape-klay": "^3.1.5",
"@types/js-cookie": "^3.0.6",
"@types/node": "^26.2.0",
"@types/node": "^26.6.4",
"@typescript/native": "npm:typescript@^7.0.2",
"rollup-plugin-visualizer": "^7.1.1",
"typescript": "npm:@typescript/typescript6@^6.0.2",
"vite": "^8.2.2"
"vite": "^8.3.2"
},
"dependencies": {
"@ae_utbm/aemark": "^0.1.3",
"@alpinejs/sort": "^3.16.2",
"@alpinejs/sort": "^3.17.4",
"@arendjr/text-clipper": "npm:@jsr/arendjr__text-clipper@^3.0.0",
"@floating-ui/dom": "^1.8.0",
"@fortawesome/fontawesome-free": "^7.3.1",
@@ -49,13 +49,13 @@
"@fullcalendar/daygrid": "^6.1.21",
"@fullcalendar/icalendar": "^6.1.21",
"@fullcalendar/list": "^6.1.21",
"@sentry/browser": "^10.70.0",
"@zip.js/zip.js": "^2.8.57",
"3d-force-graph": "^1.80.0",
"alpinejs": "^3.16.2",
"@sentry/browser": "^11.3.0",
"@zip.js/zip.js": "^2.22.0",
"3d-force-graph": "^1.80.1",
"alpinejs": "^3.17.4",
"chart.js": "^4.5.1",
"country-flag-emoji-polyfill": "^0.1.10",
"cytoscape": "^3.34.1",
"cytoscape": "^3.34.3",
"cytoscape-cxtmenu": "^3.5.0",
"cytoscape-klay": "^3.1.4",
"d3-force-3d": "^3.0.6",
@@ -66,8 +66,8 @@
"js-cookie": "^3.0.8",
"lit-html": "^3.3.3",
"native-file-system-adapter": "^3.0.1",
"temporal-polyfill": "^1.0.4",
"three": "^0.185.1",
"temporal-polyfill": "^1.0.5",
"three": "^0.186.1",
"three-spritetext": "^1.10.0",
"tom-select": "^2.6.2"
}
+110 -346
View File
@@ -1,52 +1,22 @@
@import "core/static/core/devices";
@import "core/static/core/colors";
$pedagogy-blue: #1bb9ea;
$pedagogy-orange: #ea7900;
$pedagogy-hover-blue: #0e97ce;
$pedagogy-light-blue: #caf0ff;
$pedagogy-white-text: #f0f0f0;
.pedagogy {
&.star-not-checked {
color: #f7f7f7;
.star-not-checked {
color: lightgray;
margin-bottom: 0;
margin-top: 0;
}
&.star-checked {
.star-checked {
color: $pedagogy-orange;
margin-bottom: 0;
margin-top: 0;
}
&.grade-without-star {
display: none;
}
@media screen and (max-width: $large-devices) {
&.star-not-checked {
margin-left: 5px;
margin-right: 5px;
}
&.star-checked {
margin-left: 5px;
margin-right: 5px;
}
}
@media screen and (max-width: $small-devices) {
&.grade-without-star {
display: block;
}
&.grade-with-star {
display: none;
}
}
#ue-list {
font-size: 1.1em;
@@ -64,12 +34,10 @@ $pedagogy-white-text: #f0f0f0;
}
#search_form {
.radio-guide fieldset {
input[type="checkbox"] {
display: none;
}
margin-top: 10px;
margin-bottom: 0;
color: white;
@@ -85,80 +53,79 @@ $pedagogy-white-text: #f0f0f0;
}
}
#ue_detail {
color: #062f38;
.ue-quick-info-container {
&#ue_detail {
.ue-infos {
display: flex;
gap: 2em;
flex-direction: row;
@media screen and (max-width: 700px) {
flex-direction: column;
}
}
.infos-column {
display: flex;
flex-direction: column;
gap: 1em;
min-width: 300px;
}
.info-container {
// Darken the background color just enough to make this part
// stand out a little, while not being too perceptible
background: darken($white-color, 1%);
display: grid;
grid-template-columns: 20% 20% 20% 20% auto;
grid-template-rows: auto auto;
grid-template-areas:
"hours-cm hours-td hours-tp hours-te hours-the"
"department credit-type semester . .";
grid-template-columns: 1fr 1fr;
border-radius: 5px;
padding: .75rem 1rem ;
grid-gap: .5rem;
@include shadow;
.info-container-item {
display: grid;
grid-column: span 2;
grid-template-rows: subgrid;
grid-template-columns: subgrid;
grid-column-gap: 1rem;
div {
display: flex;
align-items: center;
}
.department {
grid-area: department;
:first-child {
justify-content: right;
text-align: right;
}
}
.credit-type {
grid-area: credit-type;
}
.semester {
grid-area: semester;
}
.hours-cm {
grid-area: hours-cm;
}
.hours-td {
grid-area: hours-td;
}
.hours-tp {
grid-area: hours-tp;
}
.hours-te {
grid-area: hours-te;
}
.hours-the {
grid-area: hours-the;
}
.leave-comment-not-allowed {
p {
text-align: center;
color: red;
hr {
grid-column: span 2;
width: 50%;
margin: auto;
}
}
.leave-comment {
.leave-comment-grid-container {
display: grid;
grid-template-columns: 270px auto;
grid-template-rows: 100%;
grid-template-areas: "stars comment";
.comment-form-content {
display: flex;
gap: 2em;
@media screen and (max-width: $large-devices) {
grid-template-columns: 100%;
grid-template-rows: auto auto;
grid-template-areas:
"stars"
"comment";
gap: 1em;
flex-direction: column;
}
}
.form-stars {
grid-area: stars;
flex: 0;
min-width: 250px;
display: flex;
align-content: flex-start;
justify-content: center;
flex-wrap: wrap;
gap: 1rem 2em;
height: unset;
}
.form-comment {
grid-area: comment;
flex: 2;
}
.ui-accordion-header-icon {
@@ -166,45 +133,18 @@ $pedagogy-white-text: #f0f0f0;
margin-right: 10px;
}
.input-stars {
margin-top: 20px;
}
input[type="submit"] {
display: block;
margin-left: auto;
}
.ue-details-container {
display: grid;
grid-template-columns: 150px 130px auto;
grid-template-rows: 156px 1fr;
grid-template-areas:
"grade grade-stars ue-infos"
". . ue-infos";
@media screen and (max-width: $large-devices) {
grid-template-columns: 50% 50%;
grid-template-rows: auto auto;
grid-template-areas:
"grade grade-stars"
"ue-infos ue-infos";
}
}
.grade {
grid-area: grade;
summary {
background: $pedagogy-orange;
color: $pedagogy-white-text;
background-color: $pedagogy-blue;
padding-right: 10px;
>p {
text-align: right;
font-weight: bold;
@media screen and (min-width: $large-devices) {
clip-path: polygon(0 0%, 0 100%, 30% 100%, 33% 0);
}
}
.grade-stars {
grid-area: grade-stars;
color: $pedagogy-white-text;
background-color: $pedagogy-blue;
font-weight: bold;
}
.ue-infos {
@@ -212,237 +152,61 @@ $pedagogy-white-text: #f0f0f0;
padding-left: 10px;
}
.comment-container {
display: grid;
grid-template-columns: 300px auto;
grid-template-rows: auto auto auto;
grid-template-areas:
"grade-block comment"
"grade-block info"
"comment-end-bar comment-end-bar";
margin-bottom: 30px;
margin-top: 10px;
@media screen and (max-width: $large-devices) {
grid-template-columns: auto;
grid-template-rows: auto auto auto auto;
grid-template-areas:
"grade-block"
"comment"
"info"
"comment-end-bar";
}
.grade-block {
grid-area: grade-block;
width: 300px;
display: grid;
grid-template-columns: 150px 150px;
grid-template-rows: 156px auto;
grid-template-areas:
"grade-type grade-stars"
"grade-extension grade-extension";
grid-gap: 15px;
clip-path: polygon(0 0, 0 100%, 100% 100%, 100% 30px, 270px 0);
align-items: start;
background-color: $pedagogy-blue;
@media screen and (max-width: $large-devices) {
grid-template-columns: 50% auto;
grid-template-rows: auto;
grid-template-areas: "grade-type grade-stars";
width: auto;
clip-path: none;
align-content: space-evenly;
align-items: end;
}
.grade-extension {
grid-area: grade-extension;
background-color: $pedagogy-blue;
}
.grade-type {
grid-area: grade-type;
>p {
color: $pedagogy-white-text;
font-weight: bold;
text-align: right;
}
}
.grade-stars {
grid-area: grade-stars;
}
}
.comment {
grid-area: comment;
padding: 15px;
margin: 20px;
display: flex;
flex-direction: column;
gap: 10px;
background: $primary-neutral-light-color;
border-radius: 5px;
border: 1px darken($secondary-neutral-light-color, 10%) solid;
display: grid;
grid-template-columns: auto;
grid-template-rows: auto auto;
grid-template-areas:
"anchor"
"markdown";
@media screen and (max-width: $large-devices) {
border-left: solid;
border-right: solid;
border-color: $pedagogy-blue;
&.reported {
border: #fc8181 1px solid;
}
.anchor {
grid-area: anchor;
text-align: right;
margin-right: 15px;
.comment-header {
display: flex;
gap: 20px;
img {
width: 50px;
height: 50px;
border-radius: 50%;
}
.markdown {
grid-area: markdown;
.comment-metadata {
display: flex;
flex-direction: column;
justify-content: center;
}
min-height: 139px;
margin-top: 0;
margin-right: 0;
padding: 10px;
.comment-options {
flex: 2;
display: flex;
justify-content: right;
gap: 15px;
}
}
.comment-stars {
display: flex;
justify-content: space-evenly;
flex-wrap: wrap;
gap: 1em 2em;
padding: 1.5em;
border-top: 0.0625rem grey dotted;
border-bottom: 0.0625rem grey dotted;
}
.comment-content {
text-align: justify;
overflow: auto;
}
}
.info {
grid-area: info;
padding-bottom: 10px;
@media screen and (max-width: $large-devices) {
border-left: solid;
border-right: solid;
border-color: $pedagogy-blue;
}
.status-reported {
color: red;
float: left;
padding-left: 10px;
}
.action {
float: right;
margin-top: 0;
}
}
.comment-end-bar {
grid-area: comment-end-bar;
display: grid;
grid-template-columns: 33% auto auto;
grid-template-rows: 2.5em;
grid-template-areas: "author date report";
background-color: $pedagogy-blue;
margin-top: -1px;
@media screen and (max-width: $large-devices) {
grid-template-columns: auto;
grid-template-rows: auto auto auto;
grid-template-areas:
"report"
"date"
"author";
margin-top: 0;
text-align: center;
}
.author {
grid-area: author;
padding-top: 6px;
padding-left: 20px;
background-color: $pedagogy-orange;
clip-path: polygon(0 10px, 0 100%, 350px 200%, 300px 10px);
@media screen and (max-width: $large-devices) {
clip-path: none;
padding: 0;
padding-bottom: 7px;
}
a {
color: $pedagogy-white-text;
font-weight: bold;
}
a:hover {
color: $pedagogy-hover-blue;
}
}
.date {
grid-area: date;
color: $pedagogy-white-text;
@media screen and (max-width: $large-devices) {
padding-bottom: 7px;
}
}
.report {
grid-area: report;
justify-self: right;
padding-right: 30px;
padding-left: 30px;
a {
color: $pedagogy-white-text;
cursor: pointer;
}
a:hover {
color: $pedagogy-hover-blue;
}
@media screen and (max-width: $large-devices) {
text-align: center;
justify-self: inherit;
padding-bottom: 7px;
background-color: $white-color;
border-left: solid;
border-right: solid;
border-color: $pedagogy-blue;
a {
color: $black-color;
padding: .5em 20px 1em;
}
}
}
}
}
}
}
details.accordion summary {
background: $pedagogy-orange !important;
color: $pedagogy-white-text !important;
clip-path: polygon(0 0%, 0 100%, 30% 100%, 33% 0);
@media screen and (max-width: $large-devices) {
clip-path: none;
}
}
details.accordion>.accordion-content {
background-color: $white-color;
border-color: $pedagogy-orange;
border-right: none;
}
.buttons {
display: flex;
@@ -11,44 +11,39 @@
hx-disabled-elt="find input[type='submit']"
>
{% csrf_token %}
<div class="leave-comment-grid-container">
<div class="form-stars">
{{ form.non_field_errors() }}
{{ form.author.errors }}
{{ form.ue.errors }}
{{ form.author }}
{{ form.ue }}
<div class="input-stars">
<label for="{{ form.grade_global.id_for_label }}">{{ form.grade_global.label }} :</label>
<div class="comment-form-content">
<div class="form-stars">
<fieldset>
<legend>{{ form.grade_global.label }} :</legend>
{{ form.grade_global.errors }}
{{ form.grade_global }}
</div>
<div class="input-stars">
<label for="{{ form.grade_utility.id_for_label }}">{{ form.grade_utility.label }} :</label>
</fieldset>
<fieldset>
<legend>{{ form.grade_utility.label }} :</legend>
{{ form.grade_utility.errors }}
{{ form.grade_utility }}
</div>
<div class="input-stars">
<label for="{{ form.grade_interest.id_for_label }}">{{ form.grade_interest.label }} :</label>
</fieldset>
<fieldset>
<legend>{{ form.grade_interest.label }} :</legend>
{{ form.grade_interest.errors }}
{{ form.grade_interest }}
</div>
<div class="input-stars">
<label for="{{ form.grade_teaching.id_for_label }}">{{ form.grade_teaching.label }} :</label>
</fieldset>
<fieldset>
<legend>{{ form.grade_teaching.label }} :</legend>
{{ form.grade_teaching.errors }}
{{ form.grade_teaching }}
</div>
<div class="input-stars">
<label for="{{ form.grade_work_load.id_for_label }}">{{ form.grade_work_load.label }} :</label>
</fieldset>
<fieldset>
<legend>{{ form.grade_work_load.label }} :</legend>
{{ form.grade_work_load.errors }}
{{ form.grade_work_load }}
</div>
</fieldset>
</div>
<div class="form-comment">
<label for="{{ form.comment.id_for_label }}">{{ form.comment.label }} :</label>
@@ -56,9 +51,7 @@
{{ form.comment }}
</div>
</div>
<div class="buttons">
<input type="submit" value="{% trans %}Comment{% endtrans %}" />
</div>
<p><input type="submit" class="btn btn-blue"/></p>
</form>
{% if form.is_creation %}
@@ -0,0 +1,129 @@
{% from "pedagogy/macros.jinja" import display_star %}
{% from "core/macros.jinja" import user_profile_link %}
{% if comments %}
<h2>{% trans %}Comments{% endtrans %}</h2>
<br>
{% endif %}
<section>
{%- for comment in comments -%}
<article
id="comment-{{ comment.id }}"
class="comment {% if comment.is_reported %}reported{% endif %}"
>
{% if comment.is_reported %}
<div class="alert alert-red">
<div class="alert-main">
<h5 class="alert-title margin-bottom">
{% trans %}This comment has been reported{% endtrans %}
</h5>
<p>{% trans %}It will be hidden until moderated.{% endtrans %}</p>
{% if user.has_perm("pedagogy.view_uecommentreport") %}
{% for report in comment.reports.all() %}
<div class="markdown margin-bottom">
<blockquote>
<em>{{ report.reporter.get_display_name() }}</em>
{{ report.reason|markdown }}
</blockquote>
</div>
{% endfor %}
{% endif %}
</div>
{% if comment.author_id == user.id or user.has_perm("pedagogy.delete_uecomment") %}
<div class="alert-aside">
<a
href="{{ url("pedagogy:comment_delete", comment_id=comment.id) }}"
class="btn btn-red"
>
<i class="fa fa-trash"></i>{% trans %}Delete{% endtrans %}
</a>
<a href="{{ url("pedagogy:moderation") }}" class="btn btn-green">
<i class="fa fa-check"></i>{% trans %}Moderate{% endtrans %}
</a>
</div>
{% endif %}
</div>
{% endif %}
<div class="comment-header">
<img
{% if comment.author.avatar_pict %}
src="{{ comment.author.avatar_pict.get_download_url() }}"
{% elif comment.author.profile_pict %}
src="{{ comment.author.profile_pict.get_download_url() }}"
{% else %}
src="{{ static("core/img/unknown.jpg") }}"
{% endif %}
alt="{% trans %}Profile{% endtrans %}"
/>
<div class="comment-metadata">
<a href="{{ comment.author.get_absolute_url() }}">
<strong>{{ comment.author.get_display_name() }}</strong>
</a>
<time datetime="{{ comment.publish_date.isoformat(timespec="seconds") }}">
{{ comment.publish_date|localtime|date(DATETIME_FORMAT) }}
{{ comment.publish_date|localtime|time(DATETIME_FORMAT) }}
</time>
</div>
<div class="comment-options">
{% if comment.author_id == user.id or user.has_perm("pedagogy.change_uecomment") %}
<a
class="clickable"
hx-get="{{ url('pedagogy:comment_update', comment_id=comment.id) }}"
hx-swap="outerHTML"
hx-target="#comment-{{ comment.id }}"
tooltip="{% trans %}Edit{% endtrans %}"
>
<i class="fa fa-pencil edit-action"></i>
</a>
{% endif %}
{% if not comment.is_reported %}
<a
class="clickable"
hx-get="{{ url('pedagogy:comment_report', comment_id=comment.id) }}"
hx-swap="outerHTML"
hx-target="#comment-{{ comment.id }}"
tooltip="{% trans %}Report{% endtrans %}"
>
<i class="fa fa-exclamation delete-action"></i>
</a>
{% if comment.author_id == user.id or user.has_perm("pedagogy.delete_uecomment") %}
<a
href="{{ url("pedagogy:comment_delete", comment_id=comment.id) }}"
tooltip="{% trans %}Delete{% endtrans %}"
>
<i class="fa fa-trash-can delete-action"></i>
</a>
{% endif %}
{% endif %}
</div>
</div>
<div class="comment-stars">
<div>
<span>{% trans %}Global grade{% endtrans %}</span>
<span>{{ display_star(comment.grade_global) }}</span>
</div>
<div>
<span>{% trans %}Utility{% endtrans %}</span>
<span>{{ display_star(comment.grade_utility) }}</span>
</div>
<div>
<span>{% trans %}Interest{% endtrans %}</span>
<span>{{ display_star(comment.grade_interest) }}</span>
</div>
<div>
<span>{% trans %}Teaching{% endtrans %}</span>
<span>{{ display_star(comment.grade_teaching) }}</span>
</div>
<div>
<span>{% trans %}Workload{% endtrans %}</span>
<span>{{ display_star(comment.grade_work_load) }}</span>
</div>
</div>
<div class="comment-content">
{{ comment.comment|markdown }}
</div>
</article>
{%- endfor -%}
</section>
@@ -0,0 +1,20 @@
<div class="info-container-item">
<span>{% trans %}Global grade{% endtrans %}</span>
<span>{{ display_star(object.grade_global_average) }}</span>
</div>
<div class="info-container-item">
<span>{% trans %}Utility{% endtrans %}</span>
<span>{{ display_star(object.grade_utility_average) }}</span>
</div>
<div class="info-container-item">
<span>{% trans %}Interest{% endtrans %}</span>
<span>{{ display_star(object.grade_interest_average) }}</span>
</div>
<div class="info-container-item">
<span>{% trans %}Teaching{% endtrans %}</span>
<span>{{ display_star(object.grade_teaching_average) }}</span>
</div>
<div class="info-container-item">
<span>{% trans %}Workload{% endtrans %}</span>
<span>{{ display_star(object.grade_work_load_average) }}</span>
</div>
@@ -0,0 +1,25 @@
{# A few hx-partials for swapping a few parts of the main ue_detail.jinja #}
{% from "pedagogy/macros.jinja" import display_star %}
<hx-partial id="ue-grade">
{% include "pedagogy/fragments/ue_detail/grade.jinja" %}
</hx-partial>
<hx-partial id="comment-form">
{% if object.has_user_already_commented(user) %}
<em>
{% trans trimmed %}
You already posted a comment on this UE.
If you want to comment again, please modify or delete your previous comment.
{% endtrans %}
</em>
<br>
{% elif user.has_perm("pedagogy.add_uecomment") %}
{{ add_comment_form }}
{% endif %}
</hx-partial>
<hx-partial id="comments" hx-swap="innerMorph">
{% include "pedagogy/fragments/ue_detail/comments.jinja" %}
</hx-partial>
@@ -1,91 +0,0 @@
{% from "pedagogy/macros.jinja" import display_star %}
{% from "core/macros.jinja" import user_profile_link %}
{% if comments %}
<h2>{% trans %}Comments{% endtrans %}</h2>
<br>
{% endif %}
<section>
{% for comment in comments %}
<div id="comment-{{ comment.id }}" class="comment-container">
<div class="grade-block">
<div class="grade-type">
<p>{% trans %}Global grade{% endtrans %}</p>
<p>{% trans %}Utility{% endtrans %}</p>
<p>{% trans %}Interest{% endtrans %}</p>
<p>{% trans %}Teaching{% endtrans %}</p>
<p>{% trans %}Work load{% endtrans %}</p>
</div>
<div class="grade-stars">
<p>{{ display_star(comment.grade_global) }}</p>
<p>{{ display_star(comment.grade_utility) }}</p>
<p>{{ display_star(comment.grade_interest) }}</p>
<p>{{ display_star(comment.grade_teaching) }}</p>
<p>{{ display_star(comment.grade_work_load) }}</p>
</div>
<div class="grade-extension"></div>
</div>
<div class="comment">
<div class="anchor">
<a href="{{ url('pedagogy:ue_detail', ue_id=ue.id) }}#comment-{{ comment.id }}"><i class="fa fa-paragraph"></i></a>
</div>
{{ comment.comment|markdown }}
</div>
<div class="info">
{% if comment.is_reported %}
<p class="status-reported">
{% trans %}This comment has been reported{% endtrans %}
</p>
{% endif %}
{% if comment.author_id == user.id or user.has_perm("pedagogy.change_comment") %}
<button
class="btn btn-orange action"
hx-get="{{ url('pedagogy:comment_update', comment_id=comment.id) }}"
hx-swap="outerHTML"
hx-target="#comment-{{ comment.id }}"
>
<i class="fa fa-pencil"></i> {% trans %}Edit{% endtrans %}
</button>
{% endif %}
{% if comment.author_id == user.id or user.has_perm("pedagogy.delete_comment") %}
<form class="action"
hx-post="{{ url('pedagogy:comment_delete', comment_id=comment.id) }}"
hx-confirm='{% trans obj=object %}Are you sure you want to delete "{{ obj }}"?{% endtrans %}'
hx-swap="outerHTML"
hx-target="#comment-{{ comment.id }}"
>
{% csrf_token %}
<button class="btn btn-red action">
<i class="fa fa-trash-can"></i> {% trans %}Delete{% endtrans %}
</button>
</form>
{% endif %}
</div>
<div class="comment-end-bar">
<div class="report">
<p>
<a
hx-get="{{ url('pedagogy:comment_report', comment_id=comment.id) }}"
hx-swap="outerHTML"
hx-target="#comment-{{ comment.id }}"
>
{% trans %}Report this comment{% endtrans %}
</a>
</p>
</div>
<div class="date"><p>{{ comment.publish_date.strftime('%d/%m/%Y') }}</p></div>
<div class="author"><p>{{ user_profile_link(comment.author) }}</p></div>
</div>
</div>
{% endfor %}
</section>
@@ -1,10 +0,0 @@
{% if object.has_user_already_commented(user) %}
<div class="leave-comment-not-allowed">
<p>{% trans %}You already posted a comment on this UE. If you want to comment again, please modify or delete your previous comment.{% endtrans %}</p>
</div>
<br>
{% endif %}
{% if not object.has_user_already_commented(user) and user.has_perm("pedagogy.add_uecomment") %}
{{ add_comment_form }}
{% endif %}
@@ -1,27 +0,0 @@
<div class="ue-details-container">
<div class="grade">
<p>{% trans %}Global grade{% endtrans %}</p>
<p>{% trans %}Utility{% endtrans %}</p>
<p>{% trans %}Interest{% endtrans %}</p>
<p>{% trans %}Teaching{% endtrans %}</p>
<p>{% trans %}Work load{% endtrans %}</p>
</div>
<div class="grade-stars">
<p>{{ display_star(object.grade_global_average) }}</p>
<p>{{ display_star(object.grade_utility_average) }}</p>
<p>{{ display_star(object.grade_interest_average) }}</p>
<p>{{ display_star(object.grade_teaching_average) }}</p>
<p>{{ display_star(object.grade_work_load_average) }}</p>
</div>
<div class="ue-infos">
<p><b>{% trans %}Objectives{% endtrans %}</b></p>
<p>{{ object.objectives|markdown }}</p>
<p><b>{% trans %}Program{% endtrans %}</b></p>
<p>{{ object.program|markdown }}</p>
<p><b>{% trans %}Earned skills{% endtrans %}</b></p>
<p>{{ object.skills|markdown }}</p>
<p><b>{% trans %}Key concepts{% endtrans %}</b></p>
<p>{{ object.key_concepts|markdown }}</p>
<p><b>{% trans %}UE manager: {% endtrans %}</b>{{ object.manager }}</p>
</div>
</div>
-3
View File
@@ -1,5 +1,4 @@
{% macro display_star(grade) -%}
{% if grade >= 0 %}
{% for i in range(5) %}
{% if i <= grade %}
@@ -8,9 +7,7 @@
<span class="fa-solid fa-star pedagogy star-not-checked grade-with-star"></span>
{% endif %}
{% endfor %}
<span class="pedagogy grade-without-star">{{ grade }}/5</span>
{% else %}
<span class="grade-text"> {% trans %} not rated {% endtrans %} </span>
{% endif %}
{%- endmacro %}
+60 -59
View File
@@ -1,21 +1,6 @@
{% extends "core/base.jinja" %}
{% from "pedagogy/macros.jinja" import display_star %}
{% if is_fragment %}
<hx-partial id="ue-grade">
{% include "pedagogy/fragments/ue_details/grade.jinja" %}
</hx-partial>
<hx-partial id="comment-form">
{% include "pedagogy/fragments/ue_details/form.jinja" %}
</hx-partial>
<hx-partial id="comments" hx-swap="innerMorph">
{% include "pedagogy/fragments/ue_details/comments.jinja" %}
</hx-partial>
{% else %}
{% extends "core/base.jinja" %}
{% block additional_css %}
<link rel="stylesheet" href="{{ static('pedagogy/css/pedagogy.scss') }}">
@@ -26,66 +11,82 @@
{% endblock %}
{% block content %}
<div class="pedagogy">
<div id="ue_detail">
<button onclick='(function(){
// If comes from the guide page, go back with history
if (document.referrer.replace(/\?(.+)/gm,"").endsWith(`{{ url("pedagogy:guide") }}`)){
window.history.back();
return;
}
// Simply goes to the guide page
window.location.href = `{{ url("pedagogy:guide") }}`;
})()' hidden>{% trans %}Back{% endtrans %}</button>
<h1>{{ object.code }} - {{ object.title }}</h1>
<br>
<div class="ue-quick-info-container">
<div class="hours-cm">
<b>{% trans %}CM: {% endtrans %}</b>{{ object.hours_CM }}
<h1>{{ object.code }}</h1>
<h2 class="margin-bottom">{{ object.title }}</h2>
<div class="pedagogy" id="ue_detail">
<div class="ue-infos">
<div class="infos-column">
<aside class="info-container">
<div class="info-container-item">
<div>{% trans %}Category{% endtrans %}</div>
<div>{{ object.credit_type }}</div>
</div>
<div class="hours-td">
<b>{% trans %}TD: {% endtrans %}</b>{{ object.hours_TD }}
<div class="info-container-item">
<div>{% trans %}Credits{% endtrans %}</div>
<div>{{ object.credits }}</div>
</div>
<div class="hours-tp">
<b>{% trans %}TP: {% endtrans %}</b>{{ object.hours_TP }}
<hr>
<div class="info-container-item">
<div>{% trans %}Lectures{% endtrans %}</div>
<div>{{ object.hours_CM }}h</div>
</div>
<div class="hours-te">
<b>{% trans %}TE: {% endtrans %}</b>{{ object.hours_TE }}
<div class="info-container-item">
<div>{% trans %}Tutorials{% endtrans %}</div>
<div>{{ object.hours_TD }}h</div>
</div>
<div class="hours-the">
<b>{% trans %}THE: {% endtrans %}</b>{{ object.hours_THE }}
<div class="info-container-item">
<div>{% trans %}Practicals{% endtrans %}</div>
<div>{{ object.hours_TP }}h</div>
</div>
<div class="department">
{{ object.department }}
<div class="info-container-item">
<div>{% trans %}Work without supervision{% endtrans %}</div>
<div>{{ object.hours_THE }}h</div>
</div>
<div class="credit-type">
{{ object.credit_type }}
<hr>
<div class="info-container-item">
<div>{% trans %}Availability{% endtrans %}</div>
<div>{{ object.get_semester_display() }}</div>
</div>
<div class="semester">
{{ object.get_semester_display() }}
<hr>
<div class="info-container-item">
<div>{% trans %}Manager{% endtrans %}</div>
<div>{{ object.manager }}</div>
</div>
</aside>
<aside class="info-container" id="ue-grade">
{% include "pedagogy/fragments/ue_detail/grade.jinja" %}
</aside>
</div>
<br>
<div id="ue-grade">
{% include "pedagogy/fragments/ue_details/grade.jinja" %}
<section class="ue-main-infos">
<h3>{% trans %}Objectives{% endtrans %}</h3>
<p>{{ object.objectives|markdown }}</p>
<h3>{% trans %}Program{% endtrans %}</h3>
<p>{{ object.program|markdown }}</p>
<h3>{% trans %}Earned skills{% endtrans %}</h3>
<p>{{ object.skills|markdown }}</p>
<h3>{% trans %}Key concepts{% endtrans %}</h3>
<p>{{ object.key_concepts|markdown }}</p>
</section>
</div>
<br>
<div id="comment-form">
{% include "pedagogy/fragments/ue_details/form.jinja" %}
{% if object.has_user_already_commented(user) %}
<em>
{% trans trimmed %}
You already posted a comment on this UE.
If you want to comment again, please modify or delete your previous comment.
{% endtrans %}
</em>
<br>
{% elif user.has_perm("pedagogy.add_uecomment") %}
{{ add_comment_form }}
{% endif %}
</div>
<div id="comments">
{% include "pedagogy/fragments/ue_details/comments.jinja" %}
</div>
{% include "pedagogy/fragments/ue_detail/comments.jinja" %}
</div>
</div>
{% endblock %}
{% endif %}
+10 -7
View File
@@ -88,16 +88,19 @@ class UEDetailView(
model = UE
pk_url_kwarg = "ue_id"
template_name = "pedagogy/ue_detail.jinja"
permission_required = "pedagogy.view_ue"
fragments = {
"add_comment_form": UECommentCreateView,
}
fragments = {"add_comment_form": UECommentCreateView}
def get_template_names(self) -> list[str]:
is_fragment = self.request.headers.get("HX-Request", False)
return (
["pedagogy/fragments/ue_detail/ue_detail.jinja"]
if is_fragment
else ["pedagogy/ue_detail.jinja"]
)
def get_fragment_data(self):
return {
"add_comment_form": {"ue_id": self.object.id},
}
return {"add_comment_form": {"ue_id": self.object.id}}
def get_context_data(self, **kwargs):
return super().get_context_data(**kwargs) | {
+14 -14
View File
@@ -20,14 +20,14 @@ license = { text = "GPL-3.0-only" }
requires-python = "<4.0,>=3.14"
dependencies = [
"django>=5.2.17,<6.0.0",
"django-ninja>=1.7.0,<2.0.0",
"django-ninja>=1.7.1,<2.0.0",
"django-ninja-extra>=0.31.7",
"Pillow>=12.3.0,<13.0.0",
"aemark>=0.1.1",
"django-jinja<3.0.0,>=2.11.0",
"cryptography>=50.0.1,<51.0.0",
"cryptography>=50.0.2,<51.0.0",
"django-phonenumber-field>=8.5.0,<9.0.0",
"phonenumbers>=9.0.38,<10.0.0",
"phonenumbers>=9.0.40,<10.0.0",
"reportlab>=5.0.1,<6.0.0",
"django-haystack>=3.4.0,<4.0.0",
"xapian-haystack>=4.0.0,<5.0.0",
@@ -35,21 +35,21 @@ dependencies = [
"django-ordered-model>=3.7.4,<4.0.0",
"django-simple-captcha>=0.7.0,<1.0.0",
"python-dateutil>=2.9.0.post0,<3.0.0",
"sentry-sdk>=2.68.1,<3.0.0",
"sentry-sdk>=2.71.0,<3.0.0",
"jinja2>=3.1.6,<4.0.0",
"django-countries>=9.0.0,<10.0.0",
"django-countries>=9.1.0,<10.0.0",
"dict2xml>=1.7.8,<2.0.0",
"Sphinx>=9.1.0,<10", # Used by xapian during installation
"tomli>=2.4.1,<3.0.0",
"django-honeypot>=1.3.0,<2",
"pydantic-extra-types>=2.11.1,<3.0.0",
"ical>=14.1.1",
"redis[hiredis]>=6.4.0,<9.0.0",
"environs[django]>=15.1.0,<16",
"ical>=14.2.0",
"redis[hiredis]>=8.1.0,<9",
"environs[django]>=15.2.0,<16",
"requests>=2.34.2,<3.0.0",
"honcho>=2.0.0",
"psutil>=7.2.2,<8.0.0",
"celery[redis]>=5.6.2,<7",
"celery[redis]>=5.6.3,<7",
"django-celery-results>=2.6.0",
"django-celery-beat>=2.9.0",
]
@@ -65,10 +65,10 @@ prod = [
dev = [
"django-debug-toolbar>=8.0.0,<9",
"ipython>=9.17.1,<10.0.0",
"pre-commit>=4.6.1,<5.0.0",
"ruff>=0.16.6,<1.0.0",
"pre-commit>=4.6.2,<5.0.0",
"ruff>=0.16.10,<1.0.0",
"djhtml>=3.0.11,<4.0.0",
"faker>=40.38.0,<41.0.0",
"faker>=40.40.0,<41.0.0",
"rjsmin>=1.2.5,<2.0.0",
]
tests = [
@@ -76,7 +76,7 @@ tests = [
"pytest>=9.1.1,<10.0.0",
"pytest-cov>=7.1.0,<8.0.0",
"pytest-django>=4.14.0,<5.0.0",
"model-bakery>=1.24.0,<2.0.0",
"model-bakery>=1.24.1,<2.0.0",
"beautifulsoup4>=4.15.0,<5",
"lxml>=6.1.3,<7",
]
@@ -84,7 +84,7 @@ docs = [
"mkdocs>=1.6.1,<2.0.0",
"mkdocs-material>=9.7.7,<10.0.0",
"mkdocstrings>=1.0.6,<2.0.0",
"mkdocstrings-python>=2.0.7,<3.0.0",
"mkdocstrings-python>=2.0.9,<3.0.0",
"mkdocs-include-markdown-plugin>=7.3.0,<8.0.0",
]
Generated
+379 -345
View File
File diff suppressed because it is too large. Load diff