Compare commits
2 Commits
main
...
41dcb84987
| Author | SHA1 | Date | |
|---|---|---|---|
| 41dcb84987 | |||
| 9fb079c9a7 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,9 +1,10 @@
|
|||||||
# SGL/sso.py
|
# SGL/sso.py
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.auth.models import Group
|
from django.contrib.auth.models import Group
|
||||||
from gestion_employe.models import Departement, Employe
|
|
||||||
from simple_sso.sso_client.client import Client
|
from simple_sso.sso_client.client import Client
|
||||||
|
|
||||||
|
from gestion_employe.models import Departement, Employe
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
class SIRHClient(Client):
|
class SIRHClient(Client):
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
{% include 'parts/menu_application.html' %}
|
{% include 'parts/menu_application.html' %}
|
||||||
<div class="row flex-nowrap">
|
<div class="row flex-nowrap">
|
||||||
{% include 'parts/menu_principal.html' %}
|
{% include 'parts/menu_principal.html' %}
|
||||||
<div class="col p-1 p-sm-4">
|
<div class="col p-4">
|
||||||
{% block 'contenu' %} {% endblock %}
|
{% block 'contenu' %} {% endblock %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
{% load static %}
|
{% load static %}
|
||||||
{% load tags_personnaliser %}
|
<nav class="navbar navbar-expand-lg bg-body-tertiary">
|
||||||
|
|
||||||
<nav class="navbar d-none d-lg-block navbar-expand-lg bg-body-tertiary">
|
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<a class="navbar-brand" href="#">
|
<a class="navbar-brand" href="#">
|
||||||
<img src="{% static 'img/cerfig.jpg' %}" alt="Logo" width="85" height="30" class="d-inline-block align-text-top">
|
<img src="{% static 'img/cerfig.jpg' %}" alt="Logo" width="85" height="30" class="d-inline-block align-text-top">
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse navbar-collapse">
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
<ul class="nav nav-tabs justify-content-end w-100">
|
<ul class="nav nav-tabs justify-content-end w-100">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link active" aria-current="page" href="{{ SIRH_LIEN }}">SIRH</a>
|
<a class="nav-link active" aria-current="page" href="{{ SIRH_LIEN }}">SIRH</a>
|
||||||
@@ -20,80 +21,4 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<nav class="navbar d-lg-none navbar-expand-lg bg-body-tertiary">
|
|
||||||
<div class="container-fluid">
|
|
||||||
<a class="navbar-brand" href="#">
|
|
||||||
<img src="{% static 'img/cerfig.jpg' %}" alt="Logo" width="85" height="30" class="d-inline-block align-text-top">
|
|
||||||
</a>
|
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
|
||||||
<span class="navbar-toggler-icon"></span>
|
|
||||||
</button>
|
|
||||||
<div class="collapse navbar-collapse" id="navbarNavDropdown">
|
|
||||||
<ul class="navbar-nav">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" aria-current="page" href="{% url 'gestion_employe:mon-profil' %}">
|
|
||||||
<i class="bi bi-person-circle"></i>
|
|
||||||
Mon profil
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% if user|has_group:"ressource_humaine" or user|has_group:"direction" %}
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" aria-current="page" href="{% url 'gestion_employe:index' %}">
|
|
||||||
<i class="bi bi-speedometer2"></i>
|
|
||||||
Tableau de bord
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
{% if user|has_group:"ressource_humaine" or user|has_group:"direction" %}
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" aria-current="page" href="{% url 'gestion_projet:index' %}">
|
|
||||||
<i class="bi bi-speedometer2"></i>
|
|
||||||
Gestion des projets
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="{% url 'gestion_conges:conge' %}">
|
|
||||||
<i class="bi bi-airplane"></i>
|
|
||||||
Gestion des congés
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% if user|is_chef_projet %}
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="{% url 'gestion_projet:activites-projet' %}">
|
|
||||||
<i class="bi bi-list-task"></i>
|
|
||||||
Suivi des Activités
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="{% url 'gestion_salle:reservation-salle' %}">
|
|
||||||
<i class="bi bi-calendar-check"></i>
|
|
||||||
Réservation
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="{% url 'deconnexion' %}">
|
|
||||||
<i class="bi bi-box-arrow-right"></i> Déconnexion
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<div class="container-fluid d-flex d-sm-none justify-content-center">
|
|
||||||
<ul class="nav nav-tabs">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link active" aria-current="page" href="{{ SIRH_LIEN }}">SIRH</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="{{ SGL_LIEN }}">SGL</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="#">Laboratoire</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{% load static %}
|
{% load static %}
|
||||||
{% load tags_personnaliser %}
|
{% load tags_personnaliser %}
|
||||||
|
|
||||||
<div class="col-3 bg-danger d-none d-sm-flex flex-column vh-100 pt-5 sticky-top">
|
<div class="col-3 bg-danger d-flex flex-column vh-100 pt-5 sticky-top">
|
||||||
<div class="text-center mb-4">
|
<div class="text-center mb-4">
|
||||||
{% if user.employe.photo %}
|
{% if user.employe.photo %}
|
||||||
<img src="{{ user.employe.photo.url }}"
|
<img src="{{ user.employe.photo.url }}"
|
||||||
@@ -41,6 +41,7 @@
|
|||||||
<a href="{% url 'gestion_salle:reservation-salle' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size: 1.2em;">
|
<a href="{% url 'gestion_salle:reservation-salle' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size: 1.2em;">
|
||||||
<i class="bi bi-calendar-check"></i> Réservation
|
<i class="bi bi-calendar-check"></i> Réservation
|
||||||
</a>
|
</a>
|
||||||
|
{% comment %} {% url 'deconnexion' %} {% endcomment %}
|
||||||
<a href="{% url 'deconnexion' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size: 1.2em;">
|
<a href="{% url 'deconnexion' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size: 1.2em;">
|
||||||
<i class="bi bi-box-arrow-right"></i> Déconnexion
|
<i class="bi bi-box-arrow-right"></i> Déconnexion
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -8,7 +8,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="row d-flex flex-column flex-lg-row justify-content-center mb-4">
|
<div class="row d-flex justify-content-center mb-4">
|
||||||
<div class="col text-white bg-danger d-flex flex-column justify-content-center align-items-center border rounded p-4">
|
<div class="col text-white bg-danger d-flex flex-column justify-content-center align-items-center border rounded p-4">
|
||||||
<div class="card-header fw-bold">
|
<div class="card-header fw-bold">
|
||||||
<i class="bi bi-x-circle me-2"></i> Congés refusés
|
<i class="bi bi-x-circle me-2"></i> Congés refusés
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
<h5 class="fw-bold">{{ nombre_conges_refuse }}</h5>
|
<h5 class="fw-bold">{{ nombre_conges_refuse }}</h5>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col my-2 my-lg-0 text-white bg-warning d-flex flex-column justify-content-center align-items-center border rounded p-4 mx-0 mx-lg-2">
|
<div class="col text-white bg-warning d-flex flex-column justify-content-center align-items-center border rounded p-4 mx-2">
|
||||||
<div class="card-header fw-bold">
|
<div class="card-header fw-bold">
|
||||||
<i class="bi bi-hourglass-split me-2"></i> Congés en attente
|
<i class="bi bi-hourglass-split me-2"></i> Congés en attente
|
||||||
</div>
|
</div>
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col d-flex flex-column flex-lg-row justify-content-between align-items-center">
|
<div class="col d-flex justify-content-between align-items-center">
|
||||||
<h3><i class="bi bi-list-ul"></i> Liste des demandes de congé</h3>
|
<h3><i class="bi bi-list-ul"></i> Liste des demandes de congé</h3>
|
||||||
<button class='btn btn-primary' id="bouton-demande-conge">Demande de congé</button>
|
<button class='btn btn-primary' id="bouton-demande-conge">Demande de congé</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -123,4 +123,4 @@ class Formation(models.Model):
|
|||||||
date_fin = models.DateField(blank=True, null=True, verbose_name="Date de fin de validité")
|
date_fin = models.DateField(blank=True, null=True, verbose_name="Date de fin de validité")
|
||||||
certificat = models.FileField(upload_to='documents/formations/', blank=True, null=True, verbose_name="Certificat (PDF/Image)")
|
certificat = models.FileField(upload_to='documents/formations/', blank=True, null=True, verbose_name="Certificat (PDF/Image)")
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.titre
|
return self.titre
|
||||||
@@ -10,8 +10,8 @@ const tableau_liste_employe = new Tabulator("#tableau_liste_employe", {
|
|||||||
{"title": "Téléphone", "field": "telephone"},
|
{"title": "Téléphone", "field": "telephone"},
|
||||||
],
|
],
|
||||||
pagination: true,
|
pagination: true,
|
||||||
paginationSize: 10
|
paginationSize: 10,
|
||||||
// responsiveLayout : "hide"
|
responsiveLayout : "hide"
|
||||||
})
|
})
|
||||||
|
|
||||||
fetch(url_liste_employe)
|
fetch(url_liste_employe)
|
||||||
|
|||||||
@@ -15,12 +15,12 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="row d-flex flex-column flex-lg-row">
|
<div class="row">
|
||||||
<div class="col text-white bg-success d-flex flex-column justify-content-center align-items-center border rounded p-4">
|
<div class="col text-white bg-success d-flex flex-column justify-content-center align-items-center border rounded p-4">
|
||||||
<span class="fs-5">Nombre d'employés</span>
|
<span class="fs-5">Nombre d'employés</span>
|
||||||
<h3>{{ nombre_employes }}</h3>
|
<h3>{{ nombre_employes }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="col text-white bg-info d-flex flex-column justify-content-center align-items-center border rounded p-4 mx-0 mx-lg-3 my-1 my-lg-0">
|
<div class="col text-white bg-info d-flex flex-column justify-content-center align-items-center border rounded p-4 mx-3">
|
||||||
<span class="fs-5">Nombre de prestataires</span>
|
<span class="fs-5">Nombre de prestataires</span>
|
||||||
<h3>{{ nombre_cps }}</h3>
|
<h3>{{ nombre_cps }}</h3>
|
||||||
</div>
|
</div>
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<div class="col d-flex flex-column flex-lg-row justify-content-between mb-3">
|
<div class="col d-flex justify-content-between mb-3">
|
||||||
<h3>
|
<h3>
|
||||||
<i class="bi bi-people"></i>
|
<i class="bi bi-people"></i>
|
||||||
La liste des employés
|
La liste des employés
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
{% load static %}
|
{% load static %}
|
||||||
{% block 'titre_page' %} Gestion des employés - Mon profil {% endblock %}
|
{% block 'titre_page' %} Gestion des employés - Mon profil {% endblock %}
|
||||||
{% block 'contenu' %}
|
{% block 'contenu' %}
|
||||||
<div class="d-flex flex-column flex-lg-row justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
<h5 class="fw-bold">
|
<h5 class="fw-bold">
|
||||||
<i class="bi bi-pencil-square me-2"></i> Les informations de mon profil
|
<i class="bi bi-pencil-square me-2"></i> Les informations de mon profil
|
||||||
</h5>
|
</h5>
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
<div class="accordion-body">
|
<div class="accordion-body">
|
||||||
<form class="row" action = "{% url 'gestion_employe:modifier-employe' %}" method = "POST" enctype = "multipart/form-data" id="information-personnelles" data-url="{% url 'gestion_employe:modifier-employe' %}">
|
<form class="row" action = "{% url 'gestion_employe:modifier-employe' %}" method = "POST" enctype = "multipart/form-data" id="information-personnelles" data-url="{% url 'gestion_employe:modifier-employe' %}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="col-12 col-sm-6">
|
<div class="col">
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label>Photo</label>
|
<label>Photo</label>
|
||||||
{% if employe.photo %}
|
{% if employe.photo %}
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-sm-6">
|
<div class="col">
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label>Date de naissance :</label>
|
<label>Date de naissance :</label>
|
||||||
<input type="date" class="form-control" id="date_naissance" name = 'date_naissance' value="{{ employe.date_naissance|date:'Y-m-d' }}">
|
<input type="date" class="form-control" id="date_naissance" name = 'date_naissance' value="{{ employe.date_naissance|date:'Y-m-d' }}">
|
||||||
@@ -172,9 +172,9 @@
|
|||||||
<form method="POST" action="{% url 'gestion_employe:enregistrement-document-rh' %}" enctype="multipart/form-data">
|
<form method="POST" action="{% url 'gestion_employe:enregistrement-document-rh' %}" enctype="multipart/form-data">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 col-sm-6">
|
<div class="col">
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label>Photo</label>
|
<label>photo</label>
|
||||||
{% if employe.photo %}
|
{% if employe.photo %}
|
||||||
<span>Fichier actuel : <a href="{{ employe.photo.url }}">{{employe.photo}}</a></span>
|
<span>Fichier actuel : <a href="{{ employe.photo.url }}">{{employe.photo}}</a></span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -195,7 +195,7 @@
|
|||||||
<input type="file" class="form-control" name="diplome">
|
<input type="file" class="form-control" name="diplome">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-sm-6">
|
<div class="col">
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label>Casier judiciaire</label>
|
<label>Casier judiciaire</label>
|
||||||
{% if employe.casier_judiciaire %}
|
{% if employe.casier_judiciaire %}
|
||||||
|
|||||||
Binary file not shown.
@@ -383,8 +383,8 @@ def liste_employe(request):
|
|||||||
projets = [
|
projets = [
|
||||||
", ".join([
|
", ".join([
|
||||||
a.projet.nom_projet for a in Affectation.objects.filter(
|
a.projet.nom_projet for a in Affectation.objects.filter(
|
||||||
employe=employe
|
employe=employe,
|
||||||
#, date_fin_daffectation__gte=timezone.now().date()
|
date_fin_daffectation__gte=timezone.now().date()
|
||||||
)
|
)
|
||||||
])
|
])
|
||||||
]
|
]
|
||||||
@@ -408,14 +408,14 @@ def liste_employe(request):
|
|||||||
"salaire_mensuel": contrat.salaire_mensuel,
|
"salaire_mensuel": contrat.salaire_mensuel,
|
||||||
"statut": contrat.statut,
|
"statut": contrat.statut,
|
||||||
"fichier_contrat": contrat.fichier_contrat.url if contrat.fichier_contrat else "",
|
"fichier_contrat": contrat.fichier_contrat.url if contrat.fichier_contrat else "",
|
||||||
} for contrat in Contrat.objects.filter(employe=employe)#, statut='actif')
|
} for contrat in Contrat.objects.filter(employe=employe, statut='actif')
|
||||||
]
|
]
|
||||||
|
|
||||||
affectations = [
|
affectations = [
|
||||||
{**model_to_dict(affectation), "projet": affectation.projet.nom_projet}
|
{**model_to_dict(affectation), "projet": affectation.projet.nom_projet}
|
||||||
for affectation in Affectation.objects.filter(
|
for affectation in Affectation.objects.filter(
|
||||||
employe=employe
|
employe=employe,
|
||||||
#, date_fin_daffectation__gte=timezone.now().date()
|
date_fin_daffectation__gte=timezone.now().date()
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -12,12 +12,12 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="row d-flex flex-column flex-lg-row">
|
<div class="row">
|
||||||
<div class="col text-white bg-success d-flex flex-column justify-content-center align-items-center border rounded p-4">
|
<div class="col text-white bg-success d-flex flex-column justify-content-center align-items-center border rounded p-4">
|
||||||
<span class="fs-5">Projets en cours</span>
|
<span class="fs-5">Projets en cours</span>
|
||||||
<h3>{{projet_en_cours}}</h3>
|
<h3>{{projet_en_cours}}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="col text-white bg-success d-flex flex-column justify-content-center align-items-center border rounded p-4 my-1 my-lg-0 mx-0 mx-lg-2">
|
<div class="col text-white bg-success d-flex flex-column justify-content-center align-items-center border rounded p-4 mx-2">
|
||||||
<span class="fs-5">Budget Total (GNF)</span>
|
<span class="fs-5">Budget Total (GNF)</span>
|
||||||
<h3>{{budget_total}}</h3>
|
<h3>{{budget_total}}</h3>
|
||||||
</div>
|
</div>
|
||||||
@@ -27,11 +27,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<div class="col d-flex flex-lg-row flex-column justify-content-between align-items-center mb-3">
|
<div class="col d-flex justify-content-between align-items-center mb-3">
|
||||||
<h5 class="mb-4" >La liste des projets </h5>
|
<h5 class="mb-4" >La liste des projets </h5>
|
||||||
{% if user|has_group:"ressource_humaine" %}
|
{% if user|has_group:"ressource_humaine" %}
|
||||||
<div class="d-flex flex-lg-column flex-row justify-content-between align-items-center">
|
<div>
|
||||||
<button class="btn btn-primary me-2 me-lg-0" data-bs-toggle="modal" data-bs-target="#modalProjet">
|
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modalProjet">
|
||||||
<i class="bi bi-plus-circle"></i> Ajouter un projet
|
<i class="bi bi-plus-circle"></i> Ajouter un projet
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-info" data-bs-toggle="modal" data-bs-target="#modalBailleur">
|
<button class="btn btn-info" data-bs-toggle="modal" data-bs-target="#modalBailleur">
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -2,7 +2,71 @@ const $ = (element) => document.getElementById(element);
|
|||||||
const { Schedule } = calendarjs;
|
const { Schedule } = calendarjs;
|
||||||
|
|
||||||
let dateAUtiliser = new Date().toISOString().split('T')[0];
|
let dateAUtiliser = new Date().toISOString().split('T')[0];
|
||||||
let currentReservationId = null;
|
|
||||||
|
function afficherDetailsReservation(data) {
|
||||||
|
const reservationId = data.id_reservation || data.id;
|
||||||
|
$("id_reservation_detail").value = reservationId;
|
||||||
|
$("id_reservation_refus").value = reservationId;
|
||||||
|
$("id_reservation_zoom").value = reservationId;
|
||||||
|
$("employe").value = data.employe;
|
||||||
|
$("salle").value = data.salle;
|
||||||
|
$("statut-reservation").textContent = data.statut;
|
||||||
|
$("date_evenement").value = data.date_evenement || data.date_debut;
|
||||||
|
$("heure_debut").value = data.heure_debut;
|
||||||
|
$("heure_fin").value = data.heure_fin;
|
||||||
|
$("motif_reservation").value = data.motif_reservation;
|
||||||
|
$("besoin_zoom").checked = data.besoin_zoom;
|
||||||
|
$("besoin_ordinateur").checked = data.besoin_ordinateur ?? data.besoin_ordi;
|
||||||
|
$("lien_zoom").value = data.lien_zoom || "";
|
||||||
|
$("lien_zoom_container").classList.toggle("d-none", !data.besoin_zoom);
|
||||||
|
|
||||||
|
const currentUserId = $("current-user-id").dataset.userId;
|
||||||
|
const isOwner = data.est_proprietaire === true
|
||||||
|
|| String(data.employe_id) === currentUserId;
|
||||||
|
const isPending = data.est_en_attente === true
|
||||||
|
|| data.statut === "En attente"
|
||||||
|
|| data.statut === "en_attente";
|
||||||
|
|
||||||
|
$("bouton-supprimer-reservation").classList.toggle(
|
||||||
|
"d-none",
|
||||||
|
!(isOwner && isPending)
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const id of ["refuserReservation", "refuserReservationInfo", "bouton-valider", "bouton-valider-info"]) {
|
||||||
|
const button = $(id);
|
||||||
|
if (button) {
|
||||||
|
button.style.display = isPending && !isOwner ? "inline-block" : "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function supprimerReservation(reservationId) {
|
||||||
|
if (!window.confirm("Voulez-vous vraiment supprimer cette demande de réservation en attente ?")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const form = $("formulaire-details");
|
||||||
|
const csrf = form.querySelector("[name=csrfmiddlewaretoken]").value;
|
||||||
|
const url = $("bouton-supprimer-reservation").dataset.url.replace(
|
||||||
|
"/0/",
|
||||||
|
`/${reservationId}/`
|
||||||
|
);
|
||||||
|
|
||||||
|
fetch(url, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {"X-CSRFToken": csrf},
|
||||||
|
})
|
||||||
|
.then(response => response.json().then(data => ({response, data})))
|
||||||
|
.then(({response, data}) => {
|
||||||
|
window.alert(data.message);
|
||||||
|
if (response.ok && data.success) {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
window.alert("La suppression a échoué. Veuillez réessayer.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const calendrier = Schedule(document.getElementById('planning-reservation'), {
|
const calendrier = Schedule(document.getElementById('planning-reservation'), {
|
||||||
type: 'weekdays',
|
type: 'weekdays',
|
||||||
@@ -19,31 +83,7 @@ const calendrier = Schedule(document.getElementById('planning-reservation'), {
|
|||||||
return response.json();
|
return response.json();
|
||||||
})
|
})
|
||||||
.then(data => {
|
.then(data => {
|
||||||
currentReservationId = data.id_reservation;
|
afficherDetailsReservation(data);
|
||||||
$("id_reservation_detail").value = data.id_reservation;
|
|
||||||
$("id_reservation_refus").value = data.id_reservation;
|
|
||||||
$("id_reservation_zoom").value = data.id_reservation;
|
|
||||||
$("employe").value=data.employe;
|
|
||||||
$("salle").value=data.salle;
|
|
||||||
$("statut-reservation").innerHTML=data.statut;
|
|
||||||
$("date_evenement").value=data.date_evenement;
|
|
||||||
$("heure_debut").value=data.heure_debut;
|
|
||||||
$("heure_fin").value=data.heure_fin;
|
|
||||||
$("motif_reservation").value=data.motif_reservation;
|
|
||||||
$("besoin_zoom").checked=data.besoin_zoom;
|
|
||||||
$("besoin_ordinateur").checked=data.besoin_ordinateur;
|
|
||||||
$("lien_zoom").value=data.lien_zoom;
|
|
||||||
|
|
||||||
const zoomContainer = $("lien_zoom_container");
|
|
||||||
if (!data.besoin_zoom) {
|
|
||||||
zoomContainer.classList.add("d-none");
|
|
||||||
} else {
|
|
||||||
zoomContainer.classList.remove("d-none");
|
|
||||||
}
|
|
||||||
if (data.besoin_zoom === false){
|
|
||||||
$("lien_zoom_container").className = "d-none";
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
})
|
||||||
.catch(error => console.error("Impossible de charger les détails de la réservation :", error));
|
.catch(error => console.error("Impossible de charger les détails de la réservation :", error));
|
||||||
}
|
}
|
||||||
@@ -58,6 +98,10 @@ $('semaineDate').addEventListener('change', () => {
|
|||||||
calendrier.render();
|
calendrier.render();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
$("bouton-supprimer-reservation").addEventListener("click", () => {
|
||||||
|
supprimerReservation($("id_reservation_detail").value);
|
||||||
|
});
|
||||||
|
|
||||||
evenement_defini = null
|
evenement_defini = null
|
||||||
|
|
||||||
$("liste-salle").addEventListener("change", (e) => {
|
$("liste-salle").addEventListener("change", (e) => {
|
||||||
@@ -76,39 +120,22 @@ $("liste-salle").addEventListener("change", (e) => {
|
|||||||
function chargement_evenement(){
|
function chargement_evenement(){
|
||||||
const url = $("planning-reservation").dataset.url;
|
const url = $("planning-reservation").dataset.url;
|
||||||
fetch (url)
|
fetch (url)
|
||||||
.then(response => response.json())
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Erreur HTTP ${response.status}`);
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
.then(data => {
|
.then(data => {
|
||||||
calendrier.setData(data);
|
calendrier.setData(data);
|
||||||
})
|
})
|
||||||
|
.catch(error => console.error("Impossible de charger les réservations :", error));
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
chargement_evenement()
|
chargement_evenement()
|
||||||
})
|
})
|
||||||
|
|
||||||
$("bouton-annuler").addEventListener("click", (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const csrf = document.querySelector("[name=csrfmiddlewaretoken]").value;
|
|
||||||
const url_annuler = $("formulaire-details").dataset.urlannuler;
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
fetch(
|
|
||||||
url_annuler,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"X-Requested-With": "XMTHttpRequest",
|
|
||||||
"X-CSRFToken": csrf
|
|
||||||
},
|
|
||||||
body: new FormData($("formulaire-details"))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => console.log(data))
|
|
||||||
})
|
|
||||||
|
|
||||||
if($("bouton-valider")){
|
if($("bouton-valider")){
|
||||||
$("bouton-valider").addEventListener("click", (e) => {
|
$("bouton-valider").addEventListener("click", (e) => {
|
||||||
const csrf = document.querySelector("[name=csrfmiddlewaretoken]").value;
|
const csrf = document.querySelector("[name=csrfmiddlewaretoken]").value;
|
||||||
@@ -180,40 +207,7 @@ const tableau_reservation_attente = new Tabulator("#tableau-reservation-attente"
|
|||||||
tableau_reservation_attente.on("rowClick", (row, rowData) => {
|
tableau_reservation_attente.on("rowClick", (row, rowData) => {
|
||||||
const data = rowData.getData();
|
const data = rowData.getData();
|
||||||
|
|
||||||
console.log(data);
|
afficherDetailsReservation(data);
|
||||||
|
|
||||||
if(data.besoin_zoom === false){
|
|
||||||
$("lien_zoom_container").className = 'd-none';
|
|
||||||
}
|
|
||||||
|
|
||||||
const id_user = $("current-user-id").dataset.userId;
|
|
||||||
|
|
||||||
$("id_reservation_detail").value = data.id;
|
|
||||||
$("id_reservation_refus").value = data.id;
|
|
||||||
$("id_reservation_zoom").value = data.id;
|
|
||||||
|
|
||||||
$("employe").value=data.employe;
|
|
||||||
$("salle").value=data.salle;
|
|
||||||
$("statut-reservation").innerHTML=data.statut;
|
|
||||||
$("date_evenement").value = data.date_evenement;
|
|
||||||
$("heure_debut").value=data.heure_debut;
|
|
||||||
$("heure_fin").value=data.heure_fin;
|
|
||||||
$("motif_reservation").value=data.motif_reservation;
|
|
||||||
$("besoin_zoom").checked=data.besoin_zoom;
|
|
||||||
$("besoin_ordinateur").checked=data.besoin_ordi;
|
|
||||||
$("lien_zoom").value=data.lien_zoom;
|
|
||||||
|
|
||||||
const refuserReservation = document.querySelector("#refuserReservation");
|
|
||||||
const bouton_valider = document.querySelector("#bouton-valider");
|
|
||||||
|
|
||||||
if((refuserReservation | bouton_valider) && data.statut === "En attente"){
|
|
||||||
refuserReservation.style.display = "inline-block";
|
|
||||||
bouton_valider.style.display = "inline-block";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id_user != data.employe_id){
|
|
||||||
$("bouton-annuler").className = "d-none";
|
|
||||||
}
|
|
||||||
|
|
||||||
const modal = new bootstrap.Modal($("modalDetailReservation"));
|
const modal = new bootstrap.Modal($("modalDetailReservation"));
|
||||||
bootstrap.Modal.getOrCreateInstance($("modalReservationAttente")).hide();
|
bootstrap.Modal.getOrCreateInstance($("modalReservationAttente")).hide();
|
||||||
|
|||||||
@@ -18,12 +18,12 @@
|
|||||||
<div class="col py-2 px-4">
|
<div class="col py-2 px-4">
|
||||||
<h1 class="text-center">Réservation de salle</h1>
|
<h1 class="text-center">Réservation de salle</h1>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="row d-flex flex-column flex-lg-row justify-content-around">
|
<div class="row d-flex justify-content-around">
|
||||||
<div class="form-group col col-lg-5 me-2">
|
<div class="form-group col-5 me-2">
|
||||||
<label>Selectionner le jour concerné :</label>
|
<label>Selectionner le jour concerné :</label>
|
||||||
<input type="date" class="form-control" id="semaineDate" />
|
<input type="date" class="form-control" id="semaineDate" />
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col col-lg-5 me-2">
|
<div class="form-group col-5 me-2">
|
||||||
<label>Selectionner une salle :</label>
|
<label>Selectionner une salle :</label>
|
||||||
<select class = "form-select" id="liste-salle">
|
<select class = "form-select" id="liste-salle">
|
||||||
<option value='Salle de formation'>Salle de formation</option>
|
<option value='Salle de formation'>Salle de formation</option>
|
||||||
@@ -33,9 +33,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mt-2">
|
<div class="row mt-2">
|
||||||
<div class="col d-flex flex-column flex-lg-row justify-content-center">
|
<div class="col d-flex justify-content-center">
|
||||||
<button class="btn btn-lg btn-primary me-0 me-lg-2" data-bs-toggle="modal" data-bs-target="#modalReservation">Nouvelle réservation</button>
|
<button class="btn btn-lg btn-primary me-2" data-bs-toggle="modal" data-bs-target="#modalReservation">Nouvelle réservation</button>
|
||||||
<button type="button" class="btn mt-2 mt-lg-0 btn-warning" data-bs-toggle="modal" data-bs-target="#modalReservationAttente">
|
<button type="button" class="btn btn-warning" data-bs-toggle="modal" data-bs-target="#modalReservationAttente">
|
||||||
Validation en attente <span class="badge badge-light">{{ nb_reservation_attente }}</span>
|
Validation en attente <span class="badge badge-light">{{ nb_reservation_attente }}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -55,5 +55,5 @@
|
|||||||
{% block 'js' %}
|
{% block 'js' %}
|
||||||
<script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@calendarjs/ce/dist/index.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@calendarjs/ce/dist/index.min.js"></script>
|
||||||
<script src="{% static 'gestion_salle/js/index.js' %}?v=3"></script>
|
<script src="{% static 'gestion_salle/js/index.js' %}?v=5"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form method="POST" data-urlannuler="{% url 'gestion_salle:annuler-reservation' %}" data-urlvalider="{% url 'gestion_salle:valider-reservation' %}" id="formulaire-details">
|
<form method="POST" data-urlvalider="{% url 'gestion_salle:valider-reservation' %}" id="formulaire-details">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type='' class="form-control" id="id_reservation_detail" name='id_reservation' hidden>
|
<input type='' class="form-control" id="id_reservation_detail" name='id_reservation' hidden>
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
@@ -63,7 +63,18 @@
|
|||||||
<button class="btn btn-success me-1" id="bouton-valider-info">Valider</button>
|
<button class="btn btn-success me-1" id="bouton-valider-info">Valider</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<span id="current-user-id" data-user-id="{{ user.id }}"></span>
|
<span id="current-user-id" data-user-id="{{ user.id }}"></span>
|
||||||
<button class="btn btn-danger" id="bouton-annuler">Annuler</button>
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-outline-danger d-none"
|
||||||
|
id="bouton-supprimer-reservation"
|
||||||
|
data-url="{% url 'gestion_salle:supprimer-reservation' 0 %}"
|
||||||
|
>
|
||||||
|
Supprimer ma demande
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-secondary" id="bouton-annuler" data-bs-dismiss="modal">
|
||||||
|
Fermer
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -45,5 +45,10 @@ urlpatterns = [
|
|||||||
'liste-reservation-attente',
|
'liste-reservation-attente',
|
||||||
views.liste_reservation_attente,
|
views.liste_reservation_attente,
|
||||||
name="liste-reservation-attente"
|
name="liste-reservation-attente"
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
'reservation/<int:reservation_id>/supprimer',
|
||||||
|
views.supprimer_reservation,
|
||||||
|
name="supprimer-reservation",
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
@@ -125,19 +125,25 @@ Veuillez vous connecter à la plateforme pour traiter cette demande.""",
|
|||||||
|
|
||||||
return render(request, "gestion_salle/index.html", context)
|
return render(request, "gestion_salle/index.html", context)
|
||||||
|
|
||||||
|
@login_required
|
||||||
def liste_reservation(request:HttpRequest):
|
def liste_reservation(request:HttpRequest):
|
||||||
"""Vue d'affichage des creneaux disponibles"""
|
"""Vue d'affichage des creneaux disponibles"""
|
||||||
reservations = Reservation.objects.filter(statut = "validee")
|
try:
|
||||||
|
employe = Employe.objects.get(user=request.user)
|
||||||
|
reservations = Reservation.objects.filter(
|
||||||
|
Q(statut="validee")
|
||||||
|
| Q(statut="en_attente", employe=employe)
|
||||||
|
)
|
||||||
|
except Employe.DoesNotExist:
|
||||||
|
reservations = Reservation.objects.filter(statut="validee")
|
||||||
|
|
||||||
liste_reservation = []
|
liste_reservation = []
|
||||||
|
|
||||||
for reservation in reservations:
|
for reservation in reservations:
|
||||||
color = None
|
|
||||||
if reservation.statut == "en_attente":
|
if reservation.statut == "en_attente":
|
||||||
color = "#ffc107"
|
color = "#ffc107"
|
||||||
elif reservation.statut == "validee":
|
|
||||||
color = "#198754"
|
|
||||||
else:
|
else:
|
||||||
color = "#dc3545"
|
color = "#198754"
|
||||||
|
|
||||||
liste_reservation.append({
|
liste_reservation.append({
|
||||||
"guid": reservation.pk,
|
"guid": reservation.pk,
|
||||||
@@ -146,6 +152,7 @@ def liste_reservation(request:HttpRequest):
|
|||||||
"start": reservation.heure_debut,
|
"start": reservation.heure_debut,
|
||||||
"end": reservation.heure_fin,
|
"end": reservation.heure_fin,
|
||||||
"color": color,
|
"color": color,
|
||||||
|
"statut": dict(Reservation.STATUT).get(reservation.statut),
|
||||||
})
|
})
|
||||||
return JsonResponse(liste_reservation, safe=False)
|
return JsonResponse(liste_reservation, safe=False)
|
||||||
|
|
||||||
@@ -183,6 +190,7 @@ def liste_reservation_attente(request):
|
|||||||
liste_reservation = [
|
liste_reservation = [
|
||||||
{
|
{
|
||||||
**model_to_dict(reservation),
|
**model_to_dict(reservation),
|
||||||
|
"id": reservation.pk,
|
||||||
"employe": f"{reservation.employe.user.first_name} {reservation.employe.user.last_name}",
|
"employe": f"{reservation.employe.user.first_name} {reservation.employe.user.last_name}",
|
||||||
"employe_id": reservation.employe.user.id,
|
"employe_id": reservation.employe.user.id,
|
||||||
"salle": dict(Reservation.TYPE_CHOICES).get(reservation.salle),
|
"salle": dict(Reservation.TYPE_CHOICES).get(reservation.salle),
|
||||||
@@ -193,6 +201,49 @@ def liste_reservation_attente(request):
|
|||||||
|
|
||||||
return JsonResponse(liste_reservation, safe=False)
|
return JsonResponse(liste_reservation, safe=False)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def supprimer_reservation(request: HttpRequest, reservation_id: int):
|
||||||
|
if request.method != "POST":
|
||||||
|
return JsonResponse(
|
||||||
|
{"success": False, "message": "Méthode non autorisée."},
|
||||||
|
status=405,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
employe = Employe.objects.get(user=request.user)
|
||||||
|
except Employe.DoesNotExist:
|
||||||
|
return JsonResponse(
|
||||||
|
{"success": False, "message": "Profil employé introuvable."},
|
||||||
|
status=403,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
reservation = Reservation.objects.get(
|
||||||
|
pk=reservation_id,
|
||||||
|
employe=employe,
|
||||||
|
)
|
||||||
|
except Reservation.DoesNotExist:
|
||||||
|
return JsonResponse(
|
||||||
|
{"success": False, "message": "Réservation introuvable ou accès non autorisé."},
|
||||||
|
status=404,
|
||||||
|
)
|
||||||
|
|
||||||
|
if reservation.statut != "en_attente":
|
||||||
|
return JsonResponse(
|
||||||
|
{
|
||||||
|
"success": False,
|
||||||
|
"message": "Seules les réservations en attente peuvent être supprimées.",
|
||||||
|
},
|
||||||
|
status=400,
|
||||||
|
)
|
||||||
|
|
||||||
|
reservation.delete()
|
||||||
|
return JsonResponse(
|
||||||
|
{"success": True, "message": "Votre réservation en attente a été supprimée."}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def detail_reservation(request:HttpRequest, reservation_id:int):
|
def detail_reservation(request:HttpRequest, reservation_id:int):
|
||||||
reservation = Reservation.objects.get(id=reservation_id)
|
reservation = Reservation.objects.get(id=reservation_id)
|
||||||
employe = reservation.employe.user
|
employe = reservation.employe.user
|
||||||
@@ -209,6 +260,8 @@ def detail_reservation(request:HttpRequest, reservation_id:int):
|
|||||||
'besoin_zoom': reservation.besoin_zoom,
|
'besoin_zoom': reservation.besoin_zoom,
|
||||||
'besoin_ordinateur': reservation.besoin_ordi,
|
'besoin_ordinateur': reservation.besoin_ordi,
|
||||||
'lien_zoom': reservation.lien_zoom or '',
|
'lien_zoom': reservation.lien_zoom or '',
|
||||||
|
'est_proprietaire': request.user.is_authenticated and reservation.employe.user_id == request.user.id,
|
||||||
|
'est_en_attente': reservation.statut == "en_attente",
|
||||||
}
|
}
|
||||||
|
|
||||||
return JsonResponse(reservation_json, safe=True)
|
return JsonResponse(reservation_json, safe=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user