bientôt a alpha
This commit is contained in:
@@ -3,24 +3,43 @@ from studenteval.models import cl_Student_eval
|
||||
from django.urls import reverse
|
||||
from django.utils.html import format_html
|
||||
from . import views
|
||||
from rangefilter.filters import *
|
||||
from django.core.exceptions import PermissionDenied
|
||||
|
||||
|
||||
def is_member(user, group):
|
||||
return user.groups.filter(name=group).exists()
|
||||
|
||||
class _cl_Student_eval_admin(admin.ModelAdmin):
|
||||
request = None
|
||||
|
||||
list_display = ('ID','action_buttons','sStudent', "get_ref_of_eval", "nEval_Type", "nEval_Mode", "sAuthor", 'get_mirrored')
|
||||
|
||||
list_display = ('ID','sStudent', "get_ref_of_eval", "nEval_Type", "nEval_Mode", "sAuthor", 'get_mirrored', 'action_buttons')
|
||||
|
||||
|
||||
def action_buttons(self, obj):
|
||||
action1_url = '/student_eval/show_pdf/{}/'.format(obj.uuid)
|
||||
action1_url = f"/student_eval/show_pdf/{obj.uuid}/?dtDate__range__gte={self.request.GET.get('dtDate__range__gte')}&dtDate__range__lte={self.request.GET.get('dtDate__range__lte')}"
|
||||
return format_html('<a href="{}">Voir PDF</a>', action1_url)
|
||||
|
||||
action_buttons.short_description = 'Voir la fiche PDF'
|
||||
|
||||
def get_queryset(self, request):
|
||||
self.request = request
|
||||
return super(_cl_Student_eval_admin, self).get_queryset(request)
|
||||
|
||||
|
||||
|
||||
search_fields = ['sStudent', 'sRef']
|
||||
list_filter = ['sStudent',"sAuthor", "nEval_Type", "nEval_Mode"]
|
||||
list_filter = ['sStudent',"sAuthor", "nEval_Type", "nEval_Mode", ('dtDate', DateRangeFilter)]
|
||||
|
||||
def get_form(self, request, obj=None, **kwargs):
|
||||
user_obj = request.user
|
||||
author_id = obj.Author.id if obj.Author is not None else 0
|
||||
student_id = obj.Student.id if obj.Student is not None else 0
|
||||
|
||||
if not user_obj.id == author_id and not user_obj.id == student_id and not is_member(user_obj, "FI-Encadrants"):
|
||||
raise PermissionDenied
|
||||
return super().get_form(request, obj, **kwargs)
|
||||
|
||||
|
||||
|
||||
#fields = ["Vehicle", "nType",'sTitle', "sDesc","dtStart", "dtEnd", "Author"]
|
||||
|
10
studenteval/filters.py
Normal file
10
studenteval/filters.py
Normal file
@@ -0,0 +1,10 @@
|
||||
import django_filters
|
||||
from studenteval.models import cl_Student_eval
|
||||
|
||||
class cl_Student_eval_Filter(django_filters.FilterSet):
|
||||
|
||||
class Meta:
|
||||
model = cl_Student_eval
|
||||
fields = {
|
||||
'Student' : ['exact']
|
||||
}
|
48
studenteval/migrations/0001_initial.py
Normal file
48
studenteval/migrations/0001_initial.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# Generated by Django 4.0 on 2023-08-11 17:22
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('auth', '0012_alter_user_first_name_max_length'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='cl_Student_eval',
|
||||
fields=[
|
||||
('uuid', models.UUIDField(default=uuid.UUID('619562fd-9ca4-45be-8504-c136ddc0864f'), editable=False, primary_key=True, serialize=False)),
|
||||
('sAuthor', models.CharField(max_length=120, verbose_name='Auteur')),
|
||||
('sAuthor_2e', models.CharField(max_length=120, verbose_name='Second auteur')),
|
||||
('sStudent', models.CharField(max_length=120, verbose_name="Nom de l'étudiant/stagiaire")),
|
||||
('nEval_Type', models.CharField(choices=[('1', 'Intervention'), ('2', 'Journée')], default=1, max_length=1, verbose_name='Type de suivi')),
|
||||
('dtDate', models.DateField(default=django.utils.timezone.now, verbose_name='Date')),
|
||||
('sRef', models.CharField(max_length=120, verbose_name='N° de référence / FIP')),
|
||||
('nEval_Mode', models.CharField(choices=[('1', 'Auto-évaluation'), ('2', 'Ecadrant')], default=1, max_length=1, verbose_name='Mode de suivi ')),
|
||||
('sDesc_neg', models.TextField(verbose_name='Points à améliorer')),
|
||||
('sDesc_pos', models.TextField(verbose_name='Points positifs')),
|
||||
('sDesc_global', models.TextField(verbose_name="Avis global sur l'intervention/journée/exercice")),
|
||||
('nInter_Nature', models.CharField(choices=[('1', 'Trauma'), ('2', 'non-Trauma')], default=1, max_length=1, verbose_name='Nature')),
|
||||
('nInter_Priority', models.CharField(choices=[('1', 'P1'), ('2', 'P2'), ('3', 'P3'), ('4', 'S1'), ('5', 'S2'), ('6', 'S3'), ('7', 'Exercice')], default=1, max_length=1, verbose_name='Priorité')),
|
||||
('nInter_Complexity', models.CharField(choices=[('1', 'Stable / Simple'), ('2', 'Stable / Complexe'), ('3', 'Instable / Simple'), ('4', 'Instable / Complexe')], default=1, max_length=1, verbose_name='Nature de complexité')),
|
||||
('sInter_Desc', models.TextField(verbose_name='Description courte')),
|
||||
('nStudent_Roles', models.CharField(choices=[('1', 'Leader'), ('2', 'Équipier'), ('3', '3e position (observateur')], default=1, max_length=1, verbose_name="Rôle de l'étudiant/stagiaire")),
|
||||
('dtUpdated', models.DateTimeField(auto_now=True, verbose_name='date updated')),
|
||||
('dtCreated', models.DateTimeField(auto_now_add=True, verbose_name='date published')),
|
||||
('Author', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='eval_author', to='auth.user', verbose_name='Auteur')),
|
||||
('Author_2e', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='eval_second_author', to='auth.user', verbose_name='Second auteur')),
|
||||
('Student', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='auth.user', verbose_name='Nom du stagiaire/étudaint')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Suivi étudiants - stagiaires',
|
||||
'verbose_name_plural': 'Suivis étudiants - stagiaires',
|
||||
},
|
||||
),
|
||||
]
|
19
studenteval/migrations/0002_alter_cl_student_eval_uuid.py
Normal file
19
studenteval/migrations/0002_alter_cl_student_eval_uuid.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 4.0 on 2023-08-11 17:27
|
||||
|
||||
from django.db import migrations, models
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('studenteval', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='uuid',
|
||||
field=models.UUIDField(default=uuid.UUID('0ec70ee4-a015-42ea-aa8b-cf385010d233'), editable=False, primary_key=True, serialize=False),
|
||||
),
|
||||
]
|
@@ -0,0 +1,31 @@
|
||||
# Generated by Django 4.0 on 2023-08-11 17:51
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('auth', '0012_alter_user_first_name_max_length'),
|
||||
('studenteval', '0002_alter_cl_student_eval_uuid'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='Author_2e',
|
||||
field=models.ForeignKey(limit_choices_to={'groups__name': 'FI-Encadrants'}, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='eval_second_author', to='auth.user', verbose_name='Second auteur'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='Student',
|
||||
field=models.ForeignKey(limit_choices_to={'groups__name': 'FI-Étudiants'}, null=True, on_delete=django.db.models.deletion.SET_NULL, to='auth.user', verbose_name='Nom du stagiaire/étudaint'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='uuid',
|
||||
field=models.UUIDField(default=uuid.UUID('aade911f-b849-4235-be64-85ed63673322'), editable=False, primary_key=True, serialize=False),
|
||||
),
|
||||
]
|
@@ -0,0 +1,39 @@
|
||||
# Generated by Django 4.0 on 2023-08-11 18:08
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.utils.timezone
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('studenteval', '0003_alter_cl_student_eval_author_2e_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='cl_student_eval',
|
||||
name='nStudent_Roles',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='cl_student_eval',
|
||||
name='nStudent_Role',
|
||||
field=models.CharField(choices=[('1', 'Leader'), ('2', 'Équipier'), ('3', '3e position (observateur)')], default=1, max_length=1, verbose_name="Rôle de l'étudiant/stagiaire"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='dtDate',
|
||||
field=models.DateField(default=django.utils.timezone.now, verbose_name='Date concernée'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='nEval_Mode',
|
||||
field=models.CharField(choices=[('1', 'Auto-évaluation'), ('2', 'Encadrant')], default=1, max_length=1, verbose_name='Mode de suivi '),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='uuid',
|
||||
field=models.UUIDField(default=uuid.UUID('01f714cc-4405-420e-996c-5d3a0df76250'), editable=False, primary_key=True, serialize=False),
|
||||
),
|
||||
]
|
@@ -0,0 +1,61 @@
|
||||
# Generated by Django 4.0 on 2023-08-11 18:14
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('auth', '0012_alter_user_first_name_max_length'),
|
||||
('studenteval', '0004_remove_cl_student_eval_nstudent_roles_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='Author_2e',
|
||||
field=models.ForeignKey(blank=True, limit_choices_to={'groups__name': 'FI-Encadrants'}, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='eval_second_author', to='auth.user', verbose_name='Second auteur'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='nEval_Type',
|
||||
field=models.CharField(choices=[('1', 'Intervention/Exercice'), ('2', 'Journée')], default=1, max_length=1, verbose_name='Type de suivi'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='nInter_Complexity',
|
||||
field=models.CharField(blank=True, choices=[('1', 'Stable / Simple'), ('2', 'Stable / Complexe'), ('3', 'Instable / Simple'), ('4', 'Instable / Complexe')], default=1, max_length=1, verbose_name='Nature de complexité'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='nInter_Nature',
|
||||
field=models.CharField(blank=True, choices=[('1', 'Trauma'), ('2', 'non-Trauma')], default=1, max_length=1, verbose_name='Nature'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='nInter_Priority',
|
||||
field=models.CharField(blank=True, choices=[('1', 'P1'), ('2', 'P2'), ('3', 'P3'), ('4', 'S1'), ('5', 'S2'), ('6', 'S3'), ('7', 'Exercice')], default=1, max_length=1, verbose_name='Priorité'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='nStudent_Role',
|
||||
field=models.CharField(blank=True, choices=[('1', 'Leader'), ('2', 'Équipier'), ('3', '3e position (observateur)')], default=1, max_length=1, verbose_name="Rôle de l'étudiant/stagiaire"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='sAuthor_2e',
|
||||
field=models.CharField(blank=True, max_length=120, verbose_name='Second auteur'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='sInter_Desc',
|
||||
field=models.TextField(blank=True, verbose_name='Description courte'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='uuid',
|
||||
field=models.UUIDField(default=uuid.UUID('090d4087-8142-46bd-9af6-9cf3a4530d60'), editable=False, primary_key=True, serialize=False),
|
||||
),
|
||||
]
|
@@ -0,0 +1,24 @@
|
||||
# Generated by Django 4.0 on 2023-08-11 18:19
|
||||
|
||||
from django.db import migrations, models
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('studenteval', '0005_alter_cl_student_eval_author_2e_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='sRef',
|
||||
field=models.CharField(blank=True, max_length=120, verbose_name='N° de référence / FIP'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='uuid',
|
||||
field=models.UUIDField(default=uuid.UUID('d284f62d-691a-4e36-a63a-0accebe949ee'), editable=False, primary_key=True, serialize=False),
|
||||
),
|
||||
]
|
@@ -0,0 +1,25 @@
|
||||
# Generated by Django 4.0 on 2023-08-11 19:01
|
||||
|
||||
from django.db import migrations, models
|
||||
import studenteval.models
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('studenteval', '0006_alter_cl_student_eval_sref_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='cl_student_eval',
|
||||
name='ID',
|
||||
field=models.IntegerField(default=studenteval.models.increment_ID, editable=False, unique=True, verbose_name='ID du Suivi'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='uuid',
|
||||
field=models.UUIDField(default=uuid.UUID('bb6f22e7-e78d-492f-a8ec-87a154482db1'), editable=False, primary_key=True, serialize=False),
|
||||
),
|
||||
]
|
19
studenteval/migrations/0008_alter_cl_student_eval_uuid.py
Normal file
19
studenteval/migrations/0008_alter_cl_student_eval_uuid.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 4.0 on 2023-08-11 19:02
|
||||
|
||||
from django.db import migrations, models
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('studenteval', '0007_cl_student_eval_id_alter_cl_student_eval_uuid'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='cl_student_eval',
|
||||
name='uuid',
|
||||
field=models.UUIDField(default=uuid.UUID('ba52e37d-25c3-44fa-bec8-2af3e6bd5458'), editable=False, primary_key=True, serialize=False),
|
||||
),
|
||||
]
|
@@ -143,6 +143,8 @@ class cl_Student_eval(models.Model):
|
||||
if sStudent is None:
|
||||
sStudent = self.sStudent
|
||||
|
||||
print(f"get_all_evals_for_student launched ! {sStudent}")
|
||||
|
||||
self.a_evals = []
|
||||
evals = cl_Student_eval.objects.filter(sStudent=sStudent).order_by('sRef')
|
||||
for eval in evals:
|
||||
@@ -152,29 +154,42 @@ class cl_Student_eval(models.Model):
|
||||
#print(self.a_evals)
|
||||
return self.a_evals
|
||||
|
||||
@admin.display(description="Présence d'évaluation mirroir", boolean=True)
|
||||
@admin.display(description="Mirroir ?", boolean=True)
|
||||
def get_mirrored(self):
|
||||
self.get_all_evals_for_student()
|
||||
self.get_mirror_eval(self.a_evals)
|
||||
return self.mirrored
|
||||
|
||||
def get_eval_type(self):
|
||||
return EVAL_TYPE[int(self.nEval_Type)-1][1]
|
||||
|
||||
def get_inter_nature(self):
|
||||
return INTER_NATURE[int(self.nInter_Nature)-1][1]
|
||||
if isinstance(self.nEval_Type, int):
|
||||
return EVAL_TYPE[int(self.nEval_Type) - 1][1]
|
||||
return "Unknown"
|
||||
|
||||
def get_inter_complexity(self):
|
||||
return INTER_COMPLEXITY[int(self.nInter_Nature)-1][1]
|
||||
if isinstance(self.nInter_Nature, int):
|
||||
return INTER_COMPLEXITY[int(self.nInter_Nature) - 1][1]
|
||||
return "Unknown"
|
||||
|
||||
def get_inter_priority(self):
|
||||
return INTER_PRIORITY[int(self.nInter_Priority)-1][1]
|
||||
if isinstance(self.nInter_Priority, int):
|
||||
return INTER_PRIORITY[int(self.nInter_Priority) - 1][1]
|
||||
return "Unknown"
|
||||
|
||||
def get_eval_mode(self):
|
||||
return EVAL_MODE[int(self.nEval_Mode)-1][1]
|
||||
if isinstance(self.nEval_Mode, int):
|
||||
return EVAL_MODE[int(self.nEval_Mode) - 1][1]
|
||||
return "Unknown"
|
||||
|
||||
def get_student_role(self):
|
||||
return STUDENT_ROLE[int(self.nStudent_Role)-1][1]
|
||||
if isinstance(self.nStudent_Role, int):
|
||||
return STUDENT_ROLE[int(self.nStudent_Role) - 1][1]
|
||||
return "Unknown"
|
||||
|
||||
def get_inter_nature(self):
|
||||
if isinstance(self.nInter_Nature,int):
|
||||
return INTER_NATURE[int(self.nInter_Nature)-1][1]
|
||||
return "Uncknow"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -212,6 +227,9 @@ def import_data_csv():
|
||||
value = line[key]
|
||||
if key == "dtDate":
|
||||
value = datetime.strptime(value, "%d.%m.%Y").date()
|
||||
elif key == "sStudent":
|
||||
temp_obj = cl_Student_eval(
|
||||
|
||||
setattr(new_eval, key,value)
|
||||
|
||||
new_eval.save()
|
||||
|
51
studenteval/templates/base.html
Normal file
51
studenteval/templates/base.html
Normal file
@@ -0,0 +1,51 @@
|
||||
{% load static %}
|
||||
<!doctype html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport"
|
||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Custom CSS -->
|
||||
<link rel="stylesheet" href="{% static 'bootstrap.min.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'style.css' %}">
|
||||
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.16/dist/tailwind.min.css" rel="stylesheet">
|
||||
<title>Intranet StudentEval</title>
|
||||
</head>
|
||||
<body class="bg-gray-100">
|
||||
<div id="wrap">
|
||||
<nav class="navbar navbar-expand navbar-dark bg-primary mb-3 ps-3 pe-3">
|
||||
<a href="" class="navbar-brand">Intranet Ambulance Clerc</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarColor01"
|
||||
aria-controls="navbarColor01"
|
||||
aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="w-100">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
|
||||
</li>
|
||||
<li class="nav-item mr-auto">
|
||||
<a href="{% url 'admin:index' %}" class="nav-link" target="_blank">Administration intranet</a>
|
||||
</li>
|
||||
{% block url_nav %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
<footer class="mt-2 text-center">© 2023 <a href="https://ambulance-clerc.ch"
|
||||
target="_blank">Ambulance Clerc</a></footer>
|
||||
|
||||
{% block script %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
8
studenteval/templates/studenteval/base_studenteval.html
Normal file
8
studenteval/templates/studenteval/base_studenteval.html
Normal file
@@ -0,0 +1,8 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container w-full%">
|
||||
{% block cl_content %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
124
studenteval/templates/studenteval/cl_student_eval.html
Normal file
124
studenteval/templates/studenteval/cl_student_eval.html
Normal file
@@ -0,0 +1,124 @@
|
||||
<div class="container mx-auto p-6">
|
||||
<h1 class="text-2xl font-bold mb-4">{% block title %}Détails de l'évaluation ({{ object.ID }}) étudiant de {{ object.sStudent }}{% endblock %}</h1>
|
||||
<div class="flex rounded-lg shadow overflow-hidden">
|
||||
<div class="bg-white rounded-lg shadow overflow-hidden w-1/3 m-3">
|
||||
<table class="w-full table-auto">
|
||||
<tbody>
|
||||
<tr class="border-b">
|
||||
<th class="py-2 px-1 text-left font-semibold">Date de suivi</th>
|
||||
<td class="py-2 px-1">{{ object.dtDate }}</td>
|
||||
<th class="py-2 px-1 text-left font-semibold">Date de d'écriture</th>
|
||||
<td class="py-2 px-1">{{ object.dtCreated }}</td>
|
||||
</tr>
|
||||
<tr class="border-b">
|
||||
<th class="py-2 px-1 text-left font-semibold">Auteur</th>
|
||||
<td class="py-2 px-1">{{ object.sAuthor }}</td>
|
||||
<th class="py-2 px-1 text-left font-semibold">Second auteur</th>
|
||||
<td class="py-2 px-1">{{ object.sAuthor_2e }}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="border-b">
|
||||
<th class="py-2 px-1 text-left font-semibold">Type de suivi</th>
|
||||
<td class="py-2 px-1" colspan="3">{{ object.get_eval_type }}</td>
|
||||
</tr>
|
||||
{% if object.nEval_Type == "1" %}
|
||||
<tr class="border-b">
|
||||
<th class="py-2 px-1 text-left font-semibold">N° FIP</th>
|
||||
<td class="py-2 px-1">{{ object.sRef }}</td>
|
||||
<th class="py-2 px-1 text-left font-semibold">Priorité</th>
|
||||
<td class="py-2 px-1">{{ object.get_inter_priority }}</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="py-2 px-1 text-left font-semibold">Description</th>
|
||||
<td class="py-2 px-1" colspan="3">{{ object.sInter_Desc }}</td>
|
||||
</tr>
|
||||
<tr class="border-b">
|
||||
<th class="py-2 px-1 text-left font-semibold">Rôle de l'étudiant</th>
|
||||
<td class="py-2 px-1">{{ object.get_student_role }}</td>
|
||||
</tr>
|
||||
<tr class="border-b">
|
||||
<th class="py-2 px-1 text-left font-semibold">Nature de l'intervention</th>
|
||||
<td class="py-2 px-1">{{ object.get_inter_nature }}</td>
|
||||
</tr>
|
||||
<tr class="border-b">
|
||||
<th class="py-2 px-1 text-left font-semibold">Complexité de l'intervention</th>
|
||||
<td class="py-2 px-1" colspan="2">{{ object.get_inter_complexity }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="bg-white rounded-lg shadow overflow-hidden w-3/4 m-3">
|
||||
<table class="w-full table-auto border-solid">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="py-2 px-4 border-solid border-b border-r">
|
||||
Éléments positifs (auto-évaluation)
|
||||
</th>
|
||||
<th class="py-2 px-4 border-solid border-b border-l">
|
||||
Éléments positifs (Encadrant)
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-2 px-4 border-solid border-b border-r" >
|
||||
{{object.o_Auto_eval.sDesc_pos}}
|
||||
</td>
|
||||
<td class="py-2 px-4 border-solid border-b border-l" >
|
||||
{{object.o_Encadrant_eval.sDesc_pos}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-2 px-4"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="py-2 px-4 border-solid border-b border-r">
|
||||
Éléments à améliorer (auto-évaluation)
|
||||
</th>
|
||||
<th class="py-2 px-4 border-solid border-b border-l">
|
||||
Éléments améliorer (Encadrant)
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-2 px-4 border-solid border-b border-r" >
|
||||
{{object.o_Auto_eval.sDesc_neg}}
|
||||
</td>
|
||||
<td class="py-2 px-4 border-solid border-b border-l" >
|
||||
{{object.o_Encadrant_eval.sDesc_neg}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="bg-white rounded-lg shadow overflow-hidden w-full" style="margin-top:10px;">
|
||||
<table class="w-full">
|
||||
<tbody>
|
||||
<tr class="border-b">
|
||||
<th class="py-2 px-4 text-left font-semibold">Avis Global</th>
|
||||
|
||||
</tr>
|
||||
<tr class="border-b">
|
||||
<td class="py-2 px-4">{{ object.o_Encadrant_eval.sDesc_global }}</td>
|
||||
</tr>
|
||||
<tr class="border-b">
|
||||
<th class="py-2 px-4 text-left font-semibold">Avis Global (auto)</th>
|
||||
|
||||
</tr>
|
||||
<tr class="border-b">
|
||||
<td class="py-2 px-4">{{ object.o_Auto_eval.sDesc_global }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
@@ -1,137 +1,12 @@
|
||||
{% extends 'studenteval/base_studenteval.html' %}
|
||||
|
||||
{% block url_nav %}
|
||||
<li>
|
||||
<a href="{% url 'studenteval:student_eval_list' object.Student.id %}?dtDate__range__gte={{ dtDate__range__gte }}&dtDate__range__lte={{ dtDate__range__lte }}" class="nav-link" target="_blank">Voir toutes les évaluations</a>
|
||||
</li>
|
||||
{% endblock %}
|
||||
{% block cl_content %}
|
||||
{% include 'studenteval/cl_student_eval.html' with object=object %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Détails de l'évaluation étudiant de {{ object.sStudent }}</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.16/dist/tailwind.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body class="bg-gray-100">
|
||||
<div class="container mx-auto p-6">
|
||||
<h1 class="text-2xl font-bold mb-4">{% block title %}Détails de l'évaluation ({{ object.ID }}) étudiant de {{ object.sStudent }}{% endblock %}</h1>
|
||||
<div class="flex rounded-lg shadow overflow-hidden">
|
||||
<div class="bg-white rounded-lg shadow overflow-hidden w-1/3 m-3">
|
||||
<table class="w-full table-auto">
|
||||
<tbody>
|
||||
<tr class="border-b">
|
||||
<th class="py-2 px-4 text-left font-semibold">Date de suivi</th>
|
||||
<td class="py-2 px-4">{{ object.dtDate }}</td>
|
||||
<th class="py-2 px-4 text-left font-semibold">Date de d'écriture</th>
|
||||
<td class="py-2 px-4">{{ object.dtCreated }}</td>
|
||||
</tr>
|
||||
<tr class="border-b">
|
||||
<th class="py-2 px-4 text-left font-semibold">Auteur</th>
|
||||
<td class="py-2 px-4">{{ object.sAuthor }}</td>
|
||||
<th class="py-2 px-4 text-left font-semibold">Second auteur</th>
|
||||
<td class="py-2 px-4">{{ object.sAuthor_2e }}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="border-b">
|
||||
<th class="py-2 px-4 text-left font-semibold">Type de suivi</th>
|
||||
<td class="py-2 px-4" colspan="3">{{ object.get_eval_type }}</td>
|
||||
</tr>
|
||||
{% if object.nEval_Type == "1" %}
|
||||
<tr class="border-b">
|
||||
<th class="py-2 px-4 text-left font-semibold">N° FIP</th>
|
||||
<td class="py-2 px-4">{{ object.sRef }}</td>
|
||||
<th class="py-2 px-4 text-left font-semibold">Priorité</th>
|
||||
<td class="py-2 px-4">{{ object.get_inter_priority }}</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="py-2 px-4 text-left font-semibold">Description</th>
|
||||
<td class="py-2 px-4" colspan="3">{{ object.sInter_Desc }}</td>
|
||||
</tr>
|
||||
<tr class="border-b">
|
||||
<th class="py-2 px-4 text-left font-semibold">Rôle de l'étudiant</th>
|
||||
<td class="py-2 px-4">{{ object.get_student_role }}</td>
|
||||
</tr>
|
||||
<tr class="border-b">
|
||||
<th class="py-2 px-4 text-left font-semibold">Nature de l'intervention</th>
|
||||
<td class="py-2 px-4">{{ object.get_inter_nature }}</td>
|
||||
</tr>
|
||||
<tr class="border-b">
|
||||
<th class="py-2 px-4 text-left font-semibold">Complexité de l'intervention</th>
|
||||
<td class="py-2 px-4" colspan="2">{{ object.get_inter_complexity }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="bg-white rounded-lg shadow overflow-hidden w-3/4 m-3">
|
||||
<table class="w-full table-auto border-solid">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="py-2 px-4 border-solid border-b border-r">
|
||||
Éléments positifs (auto-évaluation) => {{object.o_Auto_eval.ID}}
|
||||
</th>
|
||||
<th class="py-2 px-4 border-solid border-b border-l">
|
||||
Éléments positifs (Encadrant) => {{object.o_Encadrant_eval.ID}}
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-2 px-4 border-solid border-b border-r" >
|
||||
{{object.o_Auto_eval.sDesc_pos}}
|
||||
</td>
|
||||
<td class="py-2 px-4 border-solid border-b border-l" >
|
||||
{{object.o_Encadrant_eval.sDesc_pos}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-2 px-4"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="py-2 px-4 border-solid border-b border-r">
|
||||
Éléments à améliorer (auto-évaluation) => {{object.o_Auto_eval.ID}}
|
||||
</th>
|
||||
<th class="py-2 px-4 border-solid border-b border-l">
|
||||
Éléments améliorer (Encadrant) => {{object.o_Encadrant_eval.ID}}
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-2 px-4 border-solid border-b border-r" >
|
||||
{{object.o_Auto_eval.sDesc_neg}}
|
||||
</td>
|
||||
<td class="py-2 px-4 border-solid border-b border-l" >
|
||||
{{object.o_Encadrant_eval.sDesc_neg}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="bg-white rounded-lg shadow overflow-hidden w-full" style="margin-top:10px;">
|
||||
<table class="w-full">
|
||||
<tbody>
|
||||
<tr class="border-b">
|
||||
<th class="py-2 px-4 text-left font-semibold">Avis Global</th>
|
||||
|
||||
</tr>
|
||||
<tr class="border-b">
|
||||
<td class="py-2 px-4">{{ object.o_Encadrant_eval.sDesc_global }}</td>
|
||||
</tr>
|
||||
<tr class="border-b">
|
||||
<th class="py-2 px-4 text-left font-semibold">Avis Global (auto)</th>
|
||||
|
||||
</tr>
|
||||
<tr class="border-b">
|
||||
<td class="py-2 px-4">{{ object.o_Auto_eval.sDesc_global }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
19
studenteval/templates/studenteval/cl_student_eval_list.html
Normal file
19
studenteval/templates/studenteval/cl_student_eval_list.html
Normal file
@@ -0,0 +1,19 @@
|
||||
{% extends 'studenteval/base_studenteval.html' %}
|
||||
|
||||
{% block title %}Liste des évaluations{% endblock %}
|
||||
|
||||
{% block cl_content %}
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
{% if object_list %}
|
||||
{% for obj in object_list reversed %}
|
||||
{% include 'studenteval/cl_student_eval.html' with object=obj %}
|
||||
{% if not forloop.last %}
|
||||
<hr>{% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<p>There is no post.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
@@ -9,6 +9,7 @@ app_name = "studenteval"
|
||||
|
||||
urlpatterns = [
|
||||
path('show_pdf/<uuid:pk>/', views.student_eval_detail.as_view(), name='student_eval_detail'),
|
||||
path('show_pdf_all/<int:Student>/', views.student_eval_list.as_view(), name='student_eval_list'),
|
||||
#path('peremptions', views.view_peremptions, name='view_peremptions'),
|
||||
|
||||
|
||||
|
@@ -1,20 +1,83 @@
|
||||
from django.http import HttpResponse
|
||||
import requests
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import HttpResponse, Http404
|
||||
from django.shortcuts import render
|
||||
from django.views.generic import ListView, UpdateView, DetailView, FormView, CreateView
|
||||
from django.core.exceptions import PermissionDenied
|
||||
|
||||
|
||||
from studenteval.models import cl_Student_eval
|
||||
from studenteval.filters import cl_Student_eval_Filter
|
||||
|
||||
def show_pdf(request, uuid):
|
||||
# Votre logique pour l'action 1 ici
|
||||
return HttpResponse("Action 1 a été effectuée pour l'objet avec l'ID : {}".format(uuid))
|
||||
|
||||
|
||||
class student_eval_detail(DetailView):
|
||||
def is_member(user, group):
|
||||
return user.groups.filter(name=group).exists()
|
||||
class student_eval_detail(LoginRequiredMixin,DetailView):
|
||||
model =cl_Student_eval
|
||||
login_url = ""
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
user_obj = self.request.user
|
||||
|
||||
author_id = self.get_object().Author.id if self.get_object().Author is not None else 0
|
||||
student_id = self.get_object().Student.id if self.get_object().Student is not None else 0
|
||||
|
||||
if not user_obj.id == author_id and not user_obj.id == student_id and not is_member(user_obj,"FI-Encadrants"):
|
||||
raise PermissionDenied
|
||||
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["dtDate__range__gte"] = self.request.GET.get('dtDate__range__gte')
|
||||
context["dtDate__range__lte"] = self.request.GET.get('dtDate__range__lte')
|
||||
|
||||
self.object.get_all_evals_for_student()
|
||||
self.object.get_mirror_eval(self.object.a_evals)
|
||||
|
||||
|
||||
return context
|
||||
class student_eval_list(LoginRequiredMixin,ListView):
|
||||
model = cl_Student_eval
|
||||
login_url = ""
|
||||
|
||||
|
||||
|
||||
def get_queryset(self):
|
||||
nStudent_id = self.kwargs['Student']
|
||||
return cl_Student_eval.objects.filter(Student=nStudent_id)
|
||||
|
||||
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
user_obj = self.request.user
|
||||
|
||||
#self.object_list.filter(Student=requests.GET['Student'])
|
||||
|
||||
|
||||
'''
|
||||
author_id = self.get_object().Author.id if self.get_object().Author is not None else 0
|
||||
student_id = self.get_object().Student.id if self.get_object().Student is not None else 0
|
||||
|
||||
if not user_obj.id == author_id and not user_obj.id == student_id and not is_member(user_obj,"FI-Encadrants"):
|
||||
raise PermissionDenied
|
||||
'''
|
||||
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['my_objects'] =[]
|
||||
|
||||
print(self.get_queryset())
|
||||
for object in self.get_queryset():
|
||||
object.get_all_evals_for_student()
|
||||
object.get_mirror_eval(object.a_evals)
|
||||
context['my_objects'].append(object)
|
||||
|
||||
|
||||
return context
|
@@ -38,10 +38,15 @@
|
||||
$link.addClass('active');
|
||||
} else if ($parent_link.length) {
|
||||
$parent_link.addClass('active');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const $a_active = $('a.nav-link.active');
|
||||
const $main_li_parent = $a_active.closest('li.nav-item.has-treeview');
|
||||
const $ul_child = $main_li_parent.children('ul');
|
||||
|
||||
$ul_child.show();
|
||||
$main_li_parent.addClass('menu-is-opening menu-open');
|
||||
};
|
||||
|
||||
$(document).ready(function () {
|
||||
// Set active status on links
|
||||
@@ -56,8 +61,7 @@
|
||||
const $changeListTable = $('#changelist .results table');
|
||||
if ($changeListTable.length && !$changeListTable.hasClass('table table-striped')) {
|
||||
$changeListTable.addClass('table table-striped');
|
||||
}
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
|
@@ -1,60 +1,10 @@
|
||||
{% load i18n static jazzmin admin_urls %}
|
||||
{% get_current_language as LANGUAGE_CODE %}
|
||||
{% get_current_language_bidi as LANGUAGE_BIDI %}
|
||||
{% extends "registration/base.html" %}
|
||||
|
||||
{% load i18n jazzmin %}
|
||||
{% get_jazzmin_settings request as jazzmin_settings %}
|
||||
{% get_jazzmin_ui_tweaks as jazzmin_ui %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ LANGUAGE_CODE|default:"en-us" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
|
||||
<title>{% block title %}{{ title }} | {% trans 'Log in again' %}{% endblock %}</title>
|
||||
|
||||
<!-- Font Awesome Icons -->
|
||||
<link rel="stylesheet" href="{% static "vendor/fontawesome-free/css/all.min.css" %}">
|
||||
|
||||
<!-- Bootstrap and adminLTE -->
|
||||
<link rel="stylesheet" href="{% static "vendor/adminlte/css/adminlte.min.css" %}">
|
||||
|
||||
<!-- Bootswatch theme -->
|
||||
{% if jazzmin_ui.theme.name != 'default' %}
|
||||
<link rel="stylesheet" href="{{ jazzmin_ui.theme.src }}" id="jazzmin-theme" />
|
||||
{% endif %}
|
||||
|
||||
{% if jazzmin_ui.dark_mode_theme %}
|
||||
<link rel="stylesheet" href="{{ jazzmin_ui.dark_mode_theme.src }}" id="jazzmin-dark-mode-theme" media="(prefers-color-scheme: dark)"/>
|
||||
{% endif %}
|
||||
|
||||
<!-- Custom fixes for django -->
|
||||
<link rel="stylesheet" href="{% static "jazzmin/css/main.css" %}">
|
||||
|
||||
{% if jazzmin_settings.custom_css %}
|
||||
<!-- Custom CSS -->
|
||||
<link rel="stylesheet" href="{% static jazzmin_settings.custom_css %}">
|
||||
{% endif %}
|
||||
|
||||
<!-- favicons -->
|
||||
<link rel="shortcut icon" href="{% static jazzmin_settings.site_icon %}" type="image/png">
|
||||
<link rel="icon" href="{% static jazzmin_settings.site_icon %}" sizes="32x32" type="image/png">
|
||||
|
||||
<!-- Google Font: Source Sans Pro -->
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700" rel="stylesheet">
|
||||
|
||||
{% block extrastyle %} {% endblock %}
|
||||
{% block extrahead %} {% endblock %}
|
||||
</head>
|
||||
<body class="hold-transition jazzmin-login-page">
|
||||
|
||||
<div class="login-box">
|
||||
<div class="login-logo">
|
||||
<h1>{{ jazzmin_settings.site_header }}</h1>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{% block content %}
|
||||
<p class="login-box-msg">{{ jazzmin_settings.welcome_sign }}</p>
|
||||
<form action="{{ app_path }}" method="post">
|
||||
{% csrf_token %}
|
||||
@@ -71,19 +21,16 @@
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if form.errors %}
|
||||
|
||||
{% if form.username.errors %}
|
||||
<div class="callout callout-danger">
|
||||
<p>{{ form.username.label }}: {{ form.username.errors|join:', ' }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if form.password.errors %}
|
||||
<div class="callout callout-danger">
|
||||
<p>{{ form.password.label }}: {{ form.password.errors|join:', ' }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if form.non_field_errors %}
|
||||
<div class="callout callout-danger">
|
||||
{% for error in form.non_field_errors %}
|
||||
@@ -91,7 +38,6 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
<div class="input-group mb-3">
|
||||
<input type="text" name="username" class="form-control" placeholder="{{ form.username.label }}" required>
|
||||
@@ -109,27 +55,22 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% url 'admin_password_reset' as password_reset_url %}
|
||||
{% if password_reset_url %}
|
||||
<div class="mb-3">
|
||||
<div class="password-reset-link" style="text-align: center;">
|
||||
<a href="{{ password_reset_url }}">
|
||||
{% trans 'Forgotten your password or username?' %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<button type="submit" class="btn {{ jazzmin_ui.button_classes.primary }} btn-block">{% trans "Log in" %}</button>
|
||||
<button type="submit" class="btn {{ jazzmin_ui.button_classes.primary }} btn-block">
|
||||
{% trans "Log in" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="{% static "admin/js/vendor/jquery/jquery.js" %}"></script>
|
||||
<!-- Bootstrap 4 -->
|
||||
<script src="{% static 'vendor/bootstrap/js/bootstrap.min.js' %}"></script>
|
||||
<!-- AdminLTE App -->
|
||||
<script src="{% static 'vendor/adminlte/js/adminlte.min.js' %}"></script>
|
||||
|
||||
{% if jazzmin_settings.custom_js %}
|
||||
<script src="{% static jazzmin_settings.custom_js %}"></script>
|
||||
{% endif %}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
{% endblock %}
|
||||
|
Reference in New Issue
Block a user