Compare commits
2 Commits
main
...
feature/su
| 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
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import Group
|
||||
from gestion_employe.models import Departement, Employe
|
||||
from simple_sso.sso_client.client import Client
|
||||
|
||||
from gestion_employe.models import Departement, Employe
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
class SIRHClient(Client):
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
{% include 'parts/menu_application.html' %}
|
||||
<div class="row flex-nowrap">
|
||||
{% include 'parts/menu_principal.html' %}
|
||||
<div class="col p-1 p-sm-4">
|
||||
<div class="col p-4">
|
||||
{% block 'contenu' %} {% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
{% load static %}
|
||||
{% load tags_personnaliser %}
|
||||
|
||||
<nav class="navbar d-none d-lg-block navbar-expand-lg bg-body-tertiary">
|
||||
<nav class="navbar 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>
|
||||
<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">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" aria-current="page" href="{{ SIRH_LIEN }}">SIRH</a>
|
||||
@@ -20,80 +21,4 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
</nav>
|
||||
@@ -1,7 +1,7 @@
|
||||
{% load static %}
|
||||
{% 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">
|
||||
{% if user.employe.photo %}
|
||||
<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;">
|
||||
<i class="bi bi-calendar-check"></i> Réservation
|
||||
</a>
|
||||
{% comment %} {% url 'deconnexion' %} {% endcomment %}
|
||||
<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
|
||||
</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 %}
|
||||
{% 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="card-header fw-bold">
|
||||
<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>
|
||||
</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">
|
||||
<i class="bi bi-hourglass-split me-2"></i> Congés en attente
|
||||
</div>
|
||||
@@ -36,7 +36,7 @@
|
||||
</div>
|
||||
|
||||
<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>
|
||||
<button class='btn btn-primary' id="bouton-demande-conge">Demande de congé</button>
|
||||
</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é")
|
||||
certificat = models.FileField(upload_to='documents/formations/', blank=True, null=True, verbose_name="Certificat (PDF/Image)")
|
||||
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"},
|
||||
],
|
||||
pagination: true,
|
||||
paginationSize: 10
|
||||
// responsiveLayout : "hide"
|
||||
paginationSize: 10,
|
||||
responsiveLayout : "hide"
|
||||
})
|
||||
|
||||
fetch(url_liste_employe)
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
{% endfor %}
|
||||
{% 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">
|
||||
<span class="fs-5">Nombre d'employés</span>
|
||||
<h3>{{ nombre_employes }}</h3>
|
||||
</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>
|
||||
<h3>{{ nombre_cps }}</h3>
|
||||
</div>
|
||||
@@ -30,7 +30,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
<i class="bi bi-people"></i>
|
||||
La liste des employés
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{% load static %}
|
||||
{% block 'titre_page' %} Gestion des employés - Mon profil {% endblock %}
|
||||
{% 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">
|
||||
<i class="bi bi-pencil-square me-2"></i> Les informations de mon profil
|
||||
</h5>
|
||||
@@ -41,7 +41,7 @@
|
||||
<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' %}">
|
||||
{% csrf_token %}
|
||||
<div class="col-12 col-sm-6">
|
||||
<div class="col">
|
||||
<div class="form-group mb-2">
|
||||
<label>Photo</label>
|
||||
{% if employe.photo %}
|
||||
@@ -70,7 +70,7 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<div class="col">
|
||||
<div class="form-group mb-2">
|
||||
<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' }}">
|
||||
@@ -172,9 +172,9 @@
|
||||
<form method="POST" action="{% url 'gestion_employe:enregistrement-document-rh' %}" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6">
|
||||
<div class="col">
|
||||
<div class="form-group mb-2">
|
||||
<label>Photo</label>
|
||||
<label>photo</label>
|
||||
{% if employe.photo %}
|
||||
<span>Fichier actuel : <a href="{{ employe.photo.url }}">{{employe.photo}}</a></span>
|
||||
{% endif %}
|
||||
@@ -195,7 +195,7 @@
|
||||
<input type="file" class="form-control" name="diplome">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<div class="col">
|
||||
<div class="form-group mb-2">
|
||||
<label>Casier judiciaire</label>
|
||||
{% if employe.casier_judiciaire %}
|
||||
|
||||
Binary file not shown.
@@ -383,8 +383,8 @@ def liste_employe(request):
|
||||
projets = [
|
||||
", ".join([
|
||||
a.projet.nom_projet for a in Affectation.objects.filter(
|
||||
employe=employe
|
||||
#, date_fin_daffectation__gte=timezone.now().date()
|
||||
employe=employe,
|
||||
date_fin_daffectation__gte=timezone.now().date()
|
||||
)
|
||||
])
|
||||
]
|
||||
@@ -408,14 +408,14 @@ def liste_employe(request):
|
||||
"salaire_mensuel": contrat.salaire_mensuel,
|
||||
"statut": contrat.statut,
|
||||
"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 = [
|
||||
{**model_to_dict(affectation), "projet": affectation.projet.nom_projet}
|
||||
for affectation in Affectation.objects.filter(
|
||||
employe=employe
|
||||
#, date_fin_daffectation__gte=timezone.now().date()
|
||||
employe=employe,
|
||||
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>
|
||||
{% endfor %}
|
||||
{% 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">
|
||||
<span class="fs-5">Projets en cours</span>
|
||||
<h3>{{projet_en_cours}}</h3>
|
||||
</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>
|
||||
<h3>{{budget_total}}</h3>
|
||||
</div>
|
||||
@@ -27,11 +27,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
{% if user|has_group:"ressource_humaine" %}
|
||||
<div class="d-flex flex-lg-column flex-row justify-content-between align-items-center">
|
||||
<button class="btn btn-primary me-2 me-lg-0" data-bs-toggle="modal" data-bs-target="#modalProjet">
|
||||
<div>
|
||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modalProjet">
|
||||
<i class="bi bi-plus-circle"></i> Ajouter un projet
|
||||
</button>
|
||||
<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;
|
||||
|
||||
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'), {
|
||||
type: 'weekdays',
|
||||
@@ -19,31 +83,7 @@ const calendrier = Schedule(document.getElementById('planning-reservation'), {
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
currentReservationId = data.id_reservation;
|
||||
$("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";
|
||||
}
|
||||
|
||||
afficherDetailsReservation(data);
|
||||
})
|
||||
.catch(error => console.error("Impossible de charger les détails de la réservation :", error));
|
||||
}
|
||||
@@ -58,6 +98,10 @@ $('semaineDate').addEventListener('change', () => {
|
||||
calendrier.render();
|
||||
})
|
||||
|
||||
$("bouton-supprimer-reservation").addEventListener("click", () => {
|
||||
supprimerReservation($("id_reservation_detail").value);
|
||||
});
|
||||
|
||||
evenement_defini = null
|
||||
|
||||
$("liste-salle").addEventListener("change", (e) => {
|
||||
@@ -76,39 +120,22 @@ $("liste-salle").addEventListener("change", (e) => {
|
||||
function chargement_evenement(){
|
||||
const url = $("planning-reservation").dataset.url;
|
||||
fetch (url)
|
||||
.then(response => response.json())
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`Erreur HTTP ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
calendrier.setData(data);
|
||||
})
|
||||
.catch(error => console.error("Impossible de charger les réservations :", error));
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
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")){
|
||||
$("bouton-valider").addEventListener("click", (e) => {
|
||||
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) => {
|
||||
const data = rowData.getData();
|
||||
|
||||
console.log(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";
|
||||
}
|
||||
afficherDetailsReservation(data);
|
||||
|
||||
const modal = new bootstrap.Modal($("modalDetailReservation"));
|
||||
bootstrap.Modal.getOrCreateInstance($("modalReservationAttente")).hide();
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
<div class="col py-2 px-4">
|
||||
<h1 class="text-center">Réservation de salle</h1>
|
||||
<hr>
|
||||
<div class="row d-flex flex-column flex-lg-row justify-content-around">
|
||||
<div class="form-group col col-lg-5 me-2">
|
||||
<div class="row d-flex justify-content-around">
|
||||
<div class="form-group col-5 me-2">
|
||||
<label>Selectionner le jour concerné :</label>
|
||||
<input type="date" class="form-control" id="semaineDate" />
|
||||
</div>
|
||||
<div class="form-group col col-lg-5 me-2">
|
||||
<div class="form-group col-5 me-2">
|
||||
<label>Selectionner une salle :</label>
|
||||
<select class = "form-select" id="liste-salle">
|
||||
<option value='Salle de formation'>Salle de formation</option>
|
||||
@@ -33,9 +33,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-2">
|
||||
<div class="col d-flex flex-column flex-lg-row 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 type="button" class="btn mt-2 mt-lg-0 btn-warning" data-bs-toggle="modal" data-bs-target="#modalReservationAttente">
|
||||
<div class="col d-flex justify-content-center">
|
||||
<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 btn-warning" data-bs-toggle="modal" data-bs-target="#modalReservationAttente">
|
||||
Validation en attente <span class="badge badge-light">{{ nb_reservation_attente }}</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -55,5 +55,5 @@
|
||||
{% block 'js' %}
|
||||
<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="{% static 'gestion_salle/js/index.js' %}?v=3"></script>
|
||||
<script src="{% static 'gestion_salle/js/index.js' %}?v=5"></script>
|
||||
{% endblock %}
|
||||
@@ -10,7 +10,7 @@
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<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 %}
|
||||
<input type='' class="form-control" id="id_reservation_detail" name='id_reservation' hidden>
|
||||
<div class="form-group mb-2">
|
||||
@@ -63,7 +63,18 @@
|
||||
<button class="btn btn-success me-1" id="bouton-valider-info">Valider</button>
|
||||
{% endif %}
|
||||
<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>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -45,5 +45,10 @@ urlpatterns = [
|
||||
'liste-reservation-attente',
|
||||
views.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)
|
||||
|
||||
@login_required
|
||||
def liste_reservation(request:HttpRequest):
|
||||
"""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 = []
|
||||
|
||||
for reservation in reservations:
|
||||
color = None
|
||||
if reservation.statut == "en_attente":
|
||||
color = "#ffc107"
|
||||
elif reservation.statut == "validee":
|
||||
color = "#198754"
|
||||
else:
|
||||
color = "#dc3545"
|
||||
color = "#198754"
|
||||
|
||||
liste_reservation.append({
|
||||
"guid": reservation.pk,
|
||||
@@ -146,6 +152,7 @@ def liste_reservation(request:HttpRequest):
|
||||
"start": reservation.heure_debut,
|
||||
"end": reservation.heure_fin,
|
||||
"color": color,
|
||||
"statut": dict(Reservation.STATUT).get(reservation.statut),
|
||||
})
|
||||
return JsonResponse(liste_reservation, safe=False)
|
||||
|
||||
@@ -183,6 +190,7 @@ def liste_reservation_attente(request):
|
||||
liste_reservation = [
|
||||
{
|
||||
**model_to_dict(reservation),
|
||||
"id": reservation.pk,
|
||||
"employe": f"{reservation.employe.user.first_name} {reservation.employe.user.last_name}",
|
||||
"employe_id": reservation.employe.user.id,
|
||||
"salle": dict(Reservation.TYPE_CHOICES).get(reservation.salle),
|
||||
@@ -193,6 +201,49 @@ def liste_reservation_attente(request):
|
||||
|
||||
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):
|
||||
reservation = Reservation.objects.get(id=reservation_id)
|
||||
employe = reservation.employe.user
|
||||
@@ -209,6 +260,8 @@ def detail_reservation(request:HttpRequest, reservation_id:int):
|
||||
'besoin_zoom': reservation.besoin_zoom,
|
||||
'besoin_ordinateur': reservation.besoin_ordi,
|
||||
'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)
|
||||
|
||||
Reference in New Issue
Block a user