Réalisation finale
This commit is contained in:
40
templates/assistant_ia/edit.html.twig
Normal file
40
templates/assistant_ia/edit.html.twig
Normal file
@@ -0,0 +1,40 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Modifier Assistant IA - {{ assistant_ia.nom }}{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Modifier Assistant IA</h1>
|
||||
<div>
|
||||
<a href="{{ path('app_assistant_ia_show', {'id': assistant_ia.id}) }}" class="btn btn-info">
|
||||
<i class="fas fa-eye"></i> Voir
|
||||
</a>
|
||||
<a href="{{ path('app_assistant_ia_index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Retour à la liste
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{{ form_start(form) }}
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.nom) }}
|
||||
{{ form_widget(form.nom) }}
|
||||
{{ form_errors(form.nom) }}
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-save"></i> Enregistrer
|
||||
</button>
|
||||
<a href="{{ path('app_assistant_ia_index') }}" class="btn btn-secondary">Annuler</a>
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
62
templates/assistant_ia/index.html.twig
Normal file
62
templates/assistant_ia/index.html.twig
Normal file
@@ -0,0 +1,62 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Assistants IA{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Assistants IA</h1>
|
||||
<a href="{{ path('app_assistant_ia_new') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus"></i> Nouvel Assistant IA
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Nom</th>
|
||||
<th>Nombre de contributions</th>
|
||||
<th>Moyenne pertinence</th>
|
||||
<th>Moyenne temps</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for assistant_ia in assistant_ias %}
|
||||
<tr>
|
||||
<td>{{ assistant_ia.id }}</td>
|
||||
<td>{{ assistant_ia.nom }}</td>
|
||||
<td>{{ assistant_ia.nombreContributions }}</td>
|
||||
<td>
|
||||
{% if assistant_ia.moyennePertinence %}
|
||||
{{ assistant_ia.moyennePertinence }}/5
|
||||
{% else %}
|
||||
<span class="text-muted">Non évalué</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if assistant_ia.moyenneTemps %}
|
||||
{{ assistant_ia.moyenneTemps }}/5
|
||||
{% else %}
|
||||
<span class="text-muted">Non évalué</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ path('app_assistant_ia_show', {'id': assistant_ia.id}) }}" class="btn btn-sm btn-info">
|
||||
<i class="fas fa-eye"></i> Voir
|
||||
</a>
|
||||
<a href="{{ path('app_assistant_ia_edit', {'id': assistant_ia.id}) }}" class="btn btn-sm btn-warning">
|
||||
<i class="fas fa-edit"></i> Modifier
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="6" class="text-center">Aucun assistant IA trouvé</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
35
templates/assistant_ia/new.html.twig
Normal file
35
templates/assistant_ia/new.html.twig
Normal file
@@ -0,0 +1,35 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Nouvel Assistant IA{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Nouvel Assistant IA</h1>
|
||||
<a href="{{ path('app_assistant_ia_index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Retour à la liste
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{{ form_start(form) }}
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.nom) }}
|
||||
{{ form_widget(form.nom) }}
|
||||
{{ form_errors(form.nom) }}
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-save"></i> Créer
|
||||
</button>
|
||||
<a href="{{ path('app_assistant_ia_index') }}" class="btn btn-secondary">Annuler</a>
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
116
templates/assistant_ia/show.html.twig
Normal file
116
templates/assistant_ia/show.html.twig
Normal file
@@ -0,0 +1,116 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Assistant IA - {{ assistant_ia.nom }}{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>{{ assistant_ia.nom }}</h1>
|
||||
<div>
|
||||
<a href="{{ path('app_assistant_ia_edit', {'id': assistant_ia.id}) }}" class="btn btn-warning">
|
||||
<i class="fas fa-edit"></i> Modifier
|
||||
</a>
|
||||
<a href="{{ path('app_assistant_ia_index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Retour à la liste
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Informations générales</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p><strong>ID :</strong> {{ assistant_ia.id }}</p>
|
||||
<p><strong>Nom :</strong> {{ assistant_ia.nom }}</p>
|
||||
<p><strong>Nombre de contributions :</strong> {{ assistant_ia.nombreContributions }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Statistiques</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p><strong>Moyenne pertinence :</strong>
|
||||
{% if assistant_ia.moyennePertinence %}
|
||||
{{ assistant_ia.moyennePertinence }}/5
|
||||
{% else %}
|
||||
<span class="text-muted">Non évalué</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
<p><strong>Moyenne temps :</strong>
|
||||
{% if assistant_ia.moyenneTemps %}
|
||||
{{ assistant_ia.moyenneTemps }}/5
|
||||
{% else %}
|
||||
<span class="text-muted">Non évalué</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if assistant_ia.contribIas|length > 0 %}
|
||||
<div class="row mt-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Contributions IA</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Contribution</th>
|
||||
<th>Pertinence</th>
|
||||
<th>Temps</th>
|
||||
<th>Moyenne</th>
|
||||
<th>Commentaire</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for contrib_ia in assistant_ia.contribIas %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{ path('app_contribution_show', {'id': contrib_ia.contribution.id}) }}">
|
||||
{{ contrib_ia.contribution }}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{% if contrib_ia.evaluationPertinence %}
|
||||
{{ contrib_ia.libellePertinence }}
|
||||
{% else %}
|
||||
<span class="text-muted">Non évalué</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if contrib_ia.evaluationTemps %}
|
||||
{{ contrib_ia.libelleTemps }}
|
||||
{% else %}
|
||||
<span class="text-muted">Non évalué</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if contrib_ia.moyenneEvaluation %}
|
||||
{{ contrib_ia.moyenneEvaluation }}/5
|
||||
{% else %}
|
||||
<span class="text-muted">Non évalué</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ contrib_ia.commentaire|default('') }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -2,8 +2,65 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{% block title %}Welcome!{% endblock %}</title>
|
||||
<title>{% block title %}Gestion de Projet IA{% endblock %}</title>
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text><text y=%221.3em%22 x=%220.2em%22 font-size=%2276%22 fill=%22%23fff%22>sf</text></svg>">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
|
||||
<style>
|
||||
.editable-cell {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.editable-cell:hover {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.editable-cell.editing {
|
||||
background-color: #e3f2fd;
|
||||
border: 2px solid #2196f3;
|
||||
}
|
||||
|
||||
.inline-edit-input {
|
||||
border: none;
|
||||
background: transparent;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.inline-edit-input:focus {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.lock-message {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
font-size: 0.8rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.editable-cell.locked {
|
||||
background-color: #fff3cd;
|
||||
border: 1px solid #ffeaa7;
|
||||
}
|
||||
|
||||
.editable-cell.locked::after {
|
||||
content: "🔒";
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
</style>
|
||||
{% block stylesheets %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -12,6 +69,82 @@
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
{% block body %}{% endblock %}
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="{{ path('app_home') }}">Gestion Projet IA</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ path('app_membre_index') }}">Membres</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ path('app_projet_index') }}">Projets</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ path('app_contribution_index') }}">Contributions</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ path('app_assistant_ia_index') }}">Assistants IA</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ path('app_contrib_ia_index') }}">Contributions IA</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ path('app_lock_stats') }}">Verrous</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
{% if app.user %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Bonjour, {{ app.user.prenom }} </a>
|
||||
</li>
|
||||
{% if is_granted('ROLE_ADMIN') %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ path('app_membre_index') }}">Gestion utilisateurs</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ path('app_logout') }}">Déconnexion</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ path('app_login') }}">Connexion</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container mt-4">
|
||||
{% for type, messages in app.flashes %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ type == 'error' ? 'danger' : type }} alert-dismissible fade show" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
{% block body %}{% endblock %}
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="/js/inline-editing.js"></script>
|
||||
<script>
|
||||
// Test de débogage
|
||||
console.log('Script de base chargé');
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
console.log('DOM chargé, vérification de l\'édition inline...');
|
||||
if (window.inlineEditing) {
|
||||
console.log('✅ InlineEditing initialisé avec succès');
|
||||
} else {
|
||||
console.error('❌ InlineEditing non initialisé');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
69
templates/contrib_ia/edit.html.twig
Normal file
69
templates/contrib_ia/edit.html.twig
Normal file
@@ -0,0 +1,69 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Modifier Contribution IA{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Modifier Contribution IA</h1>
|
||||
<div>
|
||||
<a href="{{ path('app_contrib_ia_show', {'id': contrib_ia.id}) }}" class="btn btn-info">
|
||||
<i class="fas fa-eye"></i> Voir
|
||||
</a>
|
||||
<a href="{{ path('app_contrib_ia_index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Retour à la liste
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{{ form_start(form) }}
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.assistantIa) }}
|
||||
{{ form_widget(form.assistantIa) }}
|
||||
{{ form_errors(form.assistantIa) }}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.contribution) }}
|
||||
{{ form_widget(form.contribution) }}
|
||||
{{ form_errors(form.contribution) }}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.evaluationPertinence) }}
|
||||
{{ form_widget(form.evaluationPertinence) }}
|
||||
{{ form_errors(form.evaluationPertinence) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.evaluationTemps) }}
|
||||
{{ form_widget(form.evaluationTemps) }}
|
||||
{{ form_errors(form.evaluationTemps) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.commentaire) }}
|
||||
{{ form_widget(form.commentaire) }}
|
||||
{{ form_errors(form.commentaire) }}
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-save"></i> Enregistrer
|
||||
</button>
|
||||
<a href="{{ path('app_contrib_ia_index') }}" class="btn btn-secondary">Annuler</a>
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
70
templates/contrib_ia/index.html.twig
Normal file
70
templates/contrib_ia/index.html.twig
Normal file
@@ -0,0 +1,70 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Contributions IA{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Contributions IA</h1>
|
||||
<a href="{{ path('app_contrib_ia_new') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus"></i> Nouvelle Contribution IA
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Assistant IA</th>
|
||||
<th>Contribution</th>
|
||||
<th>Pertinence</th>
|
||||
<th>Temps</th>
|
||||
<th>Moyenne</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for contrib_ia in contrib_ias %}
|
||||
<tr>
|
||||
<td>{{ contrib_ia.id }}</td>
|
||||
<td>{{ contrib_ia.assistantIa.nom }}</td>
|
||||
<td>{{ contrib_ia.contribution }}</td>
|
||||
<td>
|
||||
{% if contrib_ia.evaluationPertinence %}
|
||||
{{ contrib_ia.libellePertinence }}
|
||||
{% else %}
|
||||
<span class="text-muted">Non évalué</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if contrib_ia.evaluationTemps %}
|
||||
{{ contrib_ia.libelleTemps }}
|
||||
{% else %}
|
||||
<span class="text-muted">Non évalué</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if contrib_ia.moyenneEvaluation %}
|
||||
{{ contrib_ia.moyenneEvaluation }}/5
|
||||
{% else %}
|
||||
<span class="text-muted">Non évalué</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ path('app_contrib_ia_show', {'id': contrib_ia.id}) }}" class="btn btn-sm btn-info">
|
||||
<i class="fas fa-eye"></i> Voir
|
||||
</a>
|
||||
<a href="{{ path('app_contrib_ia_edit', {'id': contrib_ia.id}) }}" class="btn btn-sm btn-warning">
|
||||
<i class="fas fa-edit"></i> Modifier
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="7" class="text-center">Aucune contribution IA trouvée</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
64
templates/contrib_ia/new.html.twig
Normal file
64
templates/contrib_ia/new.html.twig
Normal file
@@ -0,0 +1,64 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Nouvelle Contribution IA{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Nouvelle Contribution IA</h1>
|
||||
<a href="{{ path('app_contrib_ia_index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Retour à la liste
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{{ form_start(form) }}
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.assistantIa) }}
|
||||
{{ form_widget(form.assistantIa) }}
|
||||
{{ form_errors(form.assistantIa) }}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.contribution) }}
|
||||
{{ form_widget(form.contribution) }}
|
||||
{{ form_errors(form.contribution) }}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.evaluationPertinence) }}
|
||||
{{ form_widget(form.evaluationPertinence) }}
|
||||
{{ form_errors(form.evaluationPertinence) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.evaluationTemps) }}
|
||||
{{ form_widget(form.evaluationTemps) }}
|
||||
{{ form_errors(form.evaluationTemps) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.commentaire) }}
|
||||
{{ form_widget(form.commentaire) }}
|
||||
{{ form_errors(form.commentaire) }}
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-save"></i> Créer
|
||||
</button>
|
||||
<a href="{{ path('app_contrib_ia_index') }}" class="btn btn-secondary">Annuler</a>
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
86
templates/contrib_ia/show.html.twig
Normal file
86
templates/contrib_ia/show.html.twig
Normal file
@@ -0,0 +1,86 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Contribution IA - {{ contrib_ia.assistantIa.nom }}{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Contribution IA</h1>
|
||||
<div>
|
||||
<a href="{{ path('app_contrib_ia_edit', {'id': contrib_ia.id}) }}" class="btn btn-warning">
|
||||
<i class="fas fa-edit"></i> Modifier
|
||||
</a>
|
||||
<a href="{{ path('app_contrib_ia_index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Retour à la liste
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Informations générales</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p><strong>ID :</strong> {{ contrib_ia.id }}</p>
|
||||
<p><strong>Assistant IA :</strong>
|
||||
<a href="{{ path('app_assistant_ia_show', {'id': contrib_ia.assistantIa.id}) }}">
|
||||
{{ contrib_ia.assistantIa.nom }}
|
||||
</a>
|
||||
</p>
|
||||
<p><strong>Contribution :</strong>
|
||||
<a href="{{ path('app_contribution_show', {'id': contrib_ia.contribution.id}) }}">
|
||||
{{ contrib_ia.contribution }}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Évaluations</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p><strong>Pertinence :</strong>
|
||||
{% if contrib_ia.evaluationPertinence %}
|
||||
{{ contrib_ia.libellePertinence }} ({{ contrib_ia.evaluationPertinence }}/5)
|
||||
{% else %}
|
||||
<span class="text-muted">Non évalué</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
<p><strong>Temps :</strong>
|
||||
{% if contrib_ia.evaluationTemps %}
|
||||
{{ contrib_ia.libelleTemps }} ({{ contrib_ia.evaluationTemps }}/5)
|
||||
{% else %}
|
||||
<span class="text-muted">Non évalué</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
<p><strong>Moyenne :</strong>
|
||||
{% if contrib_ia.moyenneEvaluation %}
|
||||
{{ contrib_ia.moyenneEvaluation }}/5
|
||||
{% else %}
|
||||
<span class="text-muted">Non évalué</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if contrib_ia.commentaire %}
|
||||
<div class="row mt-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Commentaire</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>{{ contrib_ia.commentaire }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
64
templates/contribution/edit.html.twig
Normal file
64
templates/contribution/edit.html.twig
Normal file
@@ -0,0 +1,64 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Modifier Contribution{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Modifier Contribution</h1>
|
||||
<div>
|
||||
<a href="{{ path('app_contribution_show', {'id': contribution.id}) }}" class="btn btn-info">
|
||||
<i class="fas fa-eye"></i> Voir
|
||||
</a>
|
||||
<a href="{{ path('app_contribution_index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Retour à la liste
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{{ form_start(form) }}
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.membre) }}
|
||||
{{ form_widget(form.membre) }}
|
||||
{{ form_errors(form.membre) }}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.projet) }}
|
||||
{{ form_widget(form.projet) }}
|
||||
{{ form_errors(form.projet) }}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.dateContribution) }}
|
||||
{{ form_widget(form.dateContribution) }}
|
||||
{{ form_errors(form.dateContribution) }}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.duree) }}
|
||||
{{ form_widget(form.duree) }}
|
||||
{{ form_errors(form.duree) }}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.commentaire) }}
|
||||
{{ form_widget(form.commentaire) }}
|
||||
{{ form_errors(form.commentaire) }}
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-save"></i> Enregistrer
|
||||
</button>
|
||||
<a href="{{ path('app_contribution_index') }}" class="btn btn-secondary">Annuler</a>
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
52
templates/contribution/index.html.twig
Normal file
52
templates/contribution/index.html.twig
Normal file
@@ -0,0 +1,52 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Contributions{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Contributions</h1>
|
||||
<a href="{{ path('app_contribution_new') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus"></i> Nouvelle Contribution
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Membre</th>
|
||||
<th>Projet</th>
|
||||
<th>Date</th>
|
||||
<th>Durée</th>
|
||||
<th>Commentaire</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for contribution in contributions %}
|
||||
<tr>
|
||||
<td>{{ contribution.id }}</td>
|
||||
<td>{{ contribution.membre }}</td>
|
||||
<td>{{ contribution.projet.nom }}</td>
|
||||
<td>{{ contribution.dateContribution|date('d/m/Y') }}</td>
|
||||
<td>{{ contribution.dureeFormatee }}</td>
|
||||
<td>{{ contribution.commentaire|default('')|slice(0, 50) }}{% if contribution.commentaire|length > 50 %}...{% endif %}</td>
|
||||
<td>
|
||||
<a href="{{ path('app_contribution_show', {'id': contribution.id}) }}" class="btn btn-sm btn-info">
|
||||
<i class="fas fa-eye"></i> Voir
|
||||
</a>
|
||||
<a href="{{ path('app_contribution_edit', {'id': contribution.id}) }}" class="btn btn-sm btn-warning">
|
||||
<i class="fas fa-edit"></i> Modifier
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="7" class="text-center">Aucune contribution trouvée</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
59
templates/contribution/new.html.twig
Normal file
59
templates/contribution/new.html.twig
Normal file
@@ -0,0 +1,59 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Nouvelle Contribution{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Nouvelle Contribution</h1>
|
||||
<a href="{{ path('app_contribution_index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Retour à la liste
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{{ form_start(form) }}
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.membre) }}
|
||||
{{ form_widget(form.membre) }}
|
||||
{{ form_errors(form.membre) }}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.projet) }}
|
||||
{{ form_widget(form.projet) }}
|
||||
{{ form_errors(form.projet) }}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.dateContribution) }}
|
||||
{{ form_widget(form.dateContribution) }}
|
||||
{{ form_errors(form.dateContribution) }}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.duree) }}
|
||||
{{ form_widget(form.duree) }}
|
||||
{{ form_errors(form.duree) }}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.commentaire) }}
|
||||
{{ form_widget(form.commentaire) }}
|
||||
{{ form_errors(form.commentaire) }}
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-save"></i> Créer
|
||||
</button>
|
||||
<a href="{{ path('app_contribution_index') }}" class="btn btn-secondary">Annuler</a>
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
117
templates/contribution/show.html.twig
Normal file
117
templates/contribution/show.html.twig
Normal file
@@ -0,0 +1,117 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Contribution - {{ contribution.membre }}{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Contribution</h1>
|
||||
<div>
|
||||
<a href="{{ path('app_contribution_edit', {'id': contribution.id}) }}" class="btn btn-warning">
|
||||
<i class="fas fa-edit"></i> Modifier
|
||||
</a>
|
||||
<a href="{{ path('app_contribution_index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Retour à la liste
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Informations générales</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p><strong>ID :</strong> {{ contribution.id }}</p>
|
||||
<p><strong>Membre :</strong>
|
||||
<a href="{{ path('app_membre_show', {'id': contribution.membre.id}) }}">
|
||||
{{ contribution.membre }}
|
||||
</a>
|
||||
</p>
|
||||
<p><strong>Projet :</strong>
|
||||
<a href="{{ path('app_projet_show', {'id': contribution.projet.id}) }}">
|
||||
{{ contribution.projet.nom }}
|
||||
</a>
|
||||
</p>
|
||||
<p><strong>Date :</strong> {{ contribution.dateContribution|date('d/m/Y') }}</p>
|
||||
<p><strong>Durée :</strong> {{ contribution.dureeFormatee }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Commentaire</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if contribution.commentaire %}
|
||||
<p>{{ contribution.commentaire }}</p>
|
||||
{% else %}
|
||||
<p class="text-muted">Aucun commentaire</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if contribution.contribIas|length > 0 %}
|
||||
<div class="row mt-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Évaluations IA</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Assistant IA</th>
|
||||
<th>Pertinence</th>
|
||||
<th>Temps</th>
|
||||
<th>Moyenne</th>
|
||||
<th>Commentaire</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for contrib_ia in contribution.contribIas %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{ path('app_assistant_ia_show', {'id': contrib_ia.assistantIa.id}) }}">
|
||||
{{ contrib_ia.assistantIa.nom }}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{% if contrib_ia.evaluationPertinence %}
|
||||
{{ contrib_ia.libellePertinence }}
|
||||
{% else %}
|
||||
<span class="text-muted">Non évalué</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if contrib_ia.evaluationTemps %}
|
||||
{{ contrib_ia.libelleTemps }}
|
||||
{% else %}
|
||||
<span class="text-muted">Non évalué</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if contrib_ia.moyenneEvaluation %}
|
||||
{{ contrib_ia.moyenneEvaluation }}/5
|
||||
{% else %}
|
||||
<span class="text-muted">Non évalué</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ contrib_ia.commentaire|default('') }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
74
templates/home/index.html.twig
Normal file
74
templates/home/index.html.twig
Normal file
@@ -0,0 +1,74 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Accueil - Gestion de Projet IA{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h1 class="mb-4">Gestion de Projet IA</h1>
|
||||
<p class="lead">Bienvenue dans votre système de gestion de projet avec intelligence artificielle.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-5">
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">
|
||||
<i class="fas fa-users"></i> Membres
|
||||
</h5>
|
||||
<p class="card-text">Gérez les membres de votre équipe et leurs informations.</p>
|
||||
<a href="{{ path('app_membre_index') }}" class="btn btn-primary">Voir les membres</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">
|
||||
<i class="fas fa-project-diagram"></i> Projets
|
||||
</h5>
|
||||
<p class="card-text">Créez et gérez vos projets avec leurs statuts et dates.</p>
|
||||
<a href="{{ path('app_projet_index') }}" class="btn btn-primary">Voir les projets</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">
|
||||
<i class="fas fa-tasks"></i> Contributions
|
||||
</h5>
|
||||
<p class="card-text">Suivez les contributions des membres aux projets.</p>
|
||||
<a href="{{ path('app_contribution_index') }}" class="btn btn-primary">Voir les contributions</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">
|
||||
<i class="fas fa-robot"></i> Assistants IA
|
||||
</h5>
|
||||
<p class="card-text">Configurez et gérez vos assistants d'intelligence artificielle.</p>
|
||||
<a href="{{ path('app_assistant_ia_index') }}" class="btn btn-primary">Voir les assistants IA</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">
|
||||
<i class="fas fa-brain"></i> Contributions IA
|
||||
</h5>
|
||||
<p class="card-text">Évaluez les contributions des assistants IA.</p>
|
||||
<a href="{{ path('app_contrib_ia_index') }}" class="btn btn-primary">Voir les contributions IA</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
14
templates/lock/_lock_info.html.twig
Normal file
14
templates/lock/_lock_info.html.twig
Normal file
@@ -0,0 +1,14 @@
|
||||
<div class="lock-info" id="lock-info-{{ entityType }}-{{ entityId }}">
|
||||
<div class="alert alert-info d-flex align-items-center">
|
||||
<i class="fas fa-lock me-2"></i>
|
||||
<div>
|
||||
<strong>Élément verrouillé</strong>
|
||||
<small class="d-block text-muted">
|
||||
Modifié par {{ lockInfo.userId }} depuis {{ lockInfo.lockedAt }}
|
||||
{% if lockInfo.expiresAt %}
|
||||
- Expire à {{ lockInfo.expiresAt }}
|
||||
{% endif %}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
124
templates/lock/stats.html.twig
Normal file
124
templates/lock/stats.html.twig
Normal file
@@ -0,0 +1,124 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Statistiques des Verrous{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Statistiques des Verrous</h1>
|
||||
<div>
|
||||
<button class="btn btn-warning" onclick="cleanupLocks()">
|
||||
<i class="fas fa-broom"></i> Nettoyer les verrous expirés
|
||||
</button>
|
||||
<button class="btn btn-danger" onclick="releaseAllLocks()">
|
||||
<i class="fas fa-unlock"></i> Libérer tous mes verrous
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Actions rapides</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="d-grid gap-2">
|
||||
<button class="btn btn-outline-primary" onclick="refreshStats()">
|
||||
<i class="fas fa-sync"></i> Actualiser les statistiques
|
||||
</button>
|
||||
<button class="btn btn-outline-info" onclick="showUserLocks()">
|
||||
<i class="fas fa-list"></i> Mes verrous actifs
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Informations système</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p><strong>Verrous actifs :</strong> <span id="active-locks-count">-</span></p>
|
||||
<p><strong>Dernière vérification :</strong> <span id="last-check">-</span></p>
|
||||
<p><strong>Verrous expirés :</strong> <span id="expired-locks-count">-</span></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Verrous actifs</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="locks-list">
|
||||
<p class="text-muted">Chargement...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function refreshStats() {
|
||||
// Implémentation pour actualiser les statistiques
|
||||
console.log('Actualisation des statistiques...');
|
||||
}
|
||||
|
||||
function cleanupLocks() {
|
||||
fetch('/lock/cleanup', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.removedLocks > 0) {
|
||||
alert(`${data.removedLocks} verrous expirés ont été supprimés.`);
|
||||
} else {
|
||||
alert('Aucun verrou expiré trouvé.');
|
||||
}
|
||||
refreshStats();
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Erreur:', error);
|
||||
alert('Erreur lors du nettoyage des verrous.');
|
||||
});
|
||||
}
|
||||
|
||||
function releaseAllLocks() {
|
||||
if (confirm('Êtes-vous sûr de vouloir libérer tous vos verrous ?')) {
|
||||
fetch('/lock/release-all', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
alert(`${data.removedLocks} verrous ont été libérés.`);
|
||||
refreshStats();
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Erreur:', error);
|
||||
alert('Erreur lors de la libération des verrous.');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function showUserLocks() {
|
||||
// Implémentation pour afficher les verrous de l'utilisateur
|
||||
console.log('Affichage des verrous de l\'utilisateur...');
|
||||
}
|
||||
|
||||
// Actualiser les statistiques au chargement de la page
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
refreshStats();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
6
templates/membre/_delete_form.html.twig
Normal file
6
templates/membre/_delete_form.html.twig
Normal file
@@ -0,0 +1,6 @@
|
||||
<form method="post" action="{{ path('app_membre_delete', {'id': membre.id}) }}" onsubmit="return confirm('Êtes-vous sûr de vouloir supprimer ce membre ?');">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ membre.id) }}">
|
||||
<button class="btn btn-danger">
|
||||
<i class="fas fa-trash"></i> Supprimer
|
||||
</button>
|
||||
</form>
|
||||
26
templates/membre/_form.html.twig
Normal file
26
templates/membre/_form.html.twig
Normal file
@@ -0,0 +1,26 @@
|
||||
{{ form_start(form) }}
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.nom) }}
|
||||
{{ form_widget(form.nom) }}
|
||||
{{ form_errors(form.nom) }}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.prenom) }}
|
||||
{{ form_widget(form.prenom) }}
|
||||
{{ form_errors(form.prenom) }}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.email) }}
|
||||
{{ form_widget(form.email) }}
|
||||
{{ form_errors(form.email) }}
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-save"></i> {{ button_label|default('Enregistrer') }}
|
||||
</button>
|
||||
<a href="{{ path('app_membre_index') }}" class="btn btn-secondary">Annuler</a>
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
27
templates/membre/edit.html.twig
Normal file
27
templates/membre/edit.html.twig
Normal file
@@ -0,0 +1,27 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Modifier Membre - {{ membre }}{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Modifier Membre</h1>
|
||||
<div>
|
||||
<a href="{{ path('app_membre_show', {'id': membre.id}) }}" class="btn btn-info">
|
||||
<i class="fas fa-eye"></i> Voir
|
||||
</a>
|
||||
<a href="{{ path('app_membre_index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Retour à la liste
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{{ include('membre/_form.html.twig', {'button_label': 'Enregistrer'}) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
169
templates/membre/index.html.twig
Normal file
169
templates/membre/index.html.twig
Normal file
@@ -0,0 +1,169 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Membres{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Membres</h1>
|
||||
<a href="{{ path('app_membre_new') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus"></i> Nouveau Membre
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info">
|
||||
<strong>Édition inline :</strong> Cliquez sur les cellules nom, prénom ou email pour les modifier directement.
|
||||
<br><small>Les modifications sont enregistrées automatiquement. Vérifiez la console (F12) pour les logs.</small>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Nom</th>
|
||||
<th>Prénom</th>
|
||||
<th>Email</th>
|
||||
<th>Contributions</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for membre in membres %}
|
||||
<tr data-membre-id="{{ membre.id }}">
|
||||
<td>{{ membre.id }}</td>
|
||||
<td class="editable-cell"
|
||||
data-entity-type="Membre"
|
||||
data-entity-id="{{ membre.id }}"
|
||||
data-field="nom"
|
||||
title="Cliquez pour modifier">
|
||||
{{ membre.nom|default('') }}
|
||||
</td>
|
||||
<td class="editable-cell"
|
||||
data-entity-type="Membre"
|
||||
data-entity-id="{{ membre.id }}"
|
||||
data-field="prenom"
|
||||
title="Cliquez pour modifier">
|
||||
{{ membre.prenom|default('') }}
|
||||
</td>
|
||||
<td class="editable-cell"
|
||||
data-entity-type="Membre"
|
||||
data-entity-id="{{ membre.id }}"
|
||||
data-field="email"
|
||||
title="Cliquez pour modifier">
|
||||
{{ membre.email|default('') }}
|
||||
</td>
|
||||
<td>{{ membre.contributions|length }}</td>
|
||||
<td>
|
||||
<a href="{{ path('app_membre_show', {'id': membre.id}) }}" class="btn btn-sm btn-info">
|
||||
<i class="fas fa-eye"></i> Voir
|
||||
</a>
|
||||
<a href="{{ path('app_membre_edit', {'id': membre.id}) }}" class="btn btn-sm btn-warning">
|
||||
<i class="fas fa-edit"></i> Modifier
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="6" class="text-center">Aucun membre trouvé</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% block javascripts %}
|
||||
{{ parent() }}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const editableCells = document.querySelectorAll('.editable-cell');
|
||||
|
||||
editableCells.forEach(cell => {
|
||||
cell.addEventListener('click', function() {
|
||||
// Ne rien faire si la cellule est déjà en mode édition
|
||||
if (cell.querySelector('input')) return;
|
||||
|
||||
const currentValue = cell.textContent.trim();
|
||||
const field = cell.dataset.field;
|
||||
const entityId = cell.dataset.entityId;
|
||||
const entityType = cell.dataset.entityType;
|
||||
|
||||
// Créer un input pour l'édition
|
||||
const input = document.createElement('input');
|
||||
input.type = field === 'email' ? 'email' : 'text';
|
||||
input.value = currentValue;
|
||||
input.classList.add('form-control', 'form-control-sm');
|
||||
|
||||
// Style pour l'input
|
||||
input.style.width = '100%';
|
||||
input.style.boxSizing = 'border-box';
|
||||
|
||||
// Remplacer le contenu de la cellule par l'input
|
||||
cell.innerHTML = '';
|
||||
cell.appendChild(input);
|
||||
input.focus();
|
||||
|
||||
// Gestion de la sauvegarde
|
||||
const saveChanges = async () => {
|
||||
const newValue = input.value.trim();
|
||||
|
||||
// Ne rien faire si la valeur n'a pas changé
|
||||
if (newValue === currentValue) {
|
||||
cell.textContent = currentValue;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Envoyer la requête AJAX
|
||||
const response = await fetch('{{ path('app_membre_update_field') }}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
id: entityId,
|
||||
field: field,
|
||||
value: newValue
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
cell.textContent = newValue;
|
||||
cell.classList.add('bg-success', 'text-white');
|
||||
setTimeout(() => {
|
||||
cell.classList.remove('bg-success', 'text-white');
|
||||
}, 1000);
|
||||
} else {
|
||||
throw new Error(data.message || 'Erreur lors de la mise à jour');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erreur:', error);
|
||||
cell.textContent = currentValue;
|
||||
alert('Erreur lors de la sauvegarde: ' + error.message);
|
||||
}
|
||||
};
|
||||
|
||||
// Sauvegarder lors de la perte de focus
|
||||
input.addEventListener('blur', saveChanges);
|
||||
|
||||
// Sauvegarder avec la touche Entrée
|
||||
input.addEventListener('keypress', function(e) {
|
||||
if (e.key === 'Enter') {
|
||||
input.blur();
|
||||
}
|
||||
});
|
||||
|
||||
// Annuler avec la touche Échap
|
||||
input.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
cell.textContent = currentValue;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
22
templates/membre/new.html.twig
Normal file
22
templates/membre/new.html.twig
Normal file
@@ -0,0 +1,22 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Nouveau Membre{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Nouveau Membre</h1>
|
||||
<a href="{{ path('app_membre_index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Retour à la liste
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{{ include('membre/_form.html.twig') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
92
templates/membre/show.html.twig
Normal file
92
templates/membre/show.html.twig
Normal file
@@ -0,0 +1,92 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Membre - {{ membre }}{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>{{ membre }}</h1>
|
||||
<div>
|
||||
<a href="{{ path('app_membre_edit', {'id': membre.id}) }}" class="btn btn-warning">
|
||||
<i class="fas fa-edit"></i> Modifier
|
||||
</a>
|
||||
<a href="{{ path('app_membre_index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Retour à la liste
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Informations générales</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p><strong>ID :</strong> {{ membre.id }}</p>
|
||||
<p><strong>Nom :</strong> {{ membre.nom }}</p>
|
||||
<p><strong>Prénom :</strong> {{ membre.prenom }}</p>
|
||||
<p><strong>Email :</strong> {{ membre.email }}</p>
|
||||
<p><strong>Nombre de contributions :</strong> {{ membre.contributions|length }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if membre.contributions|length > 0 %}
|
||||
<div class="row mt-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Contributions ({{ membre.contributions|length }})</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Projet</th>
|
||||
<th>Date</th>
|
||||
<th>Durée</th>
|
||||
<th>Commentaire</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for contribution in membre.contributions %}
|
||||
<tr>
|
||||
<td>{{ contribution.projet.nom }}</td>
|
||||
<td>{{ contribution.dateContribution|date('d/m/Y') }}</td>
|
||||
<td>{{ contribution.dureeFormatee }}</td>
|
||||
<td>{{ contribution.commentaire|default('')|slice(0, 30) }}{% if contribution.commentaire|length > 30 %}...{% endif %}</td>
|
||||
<td>
|
||||
<a href="{{ path('app_contribution_show', {'id': contribution.id}) }}" class="btn btn-sm btn-info">
|
||||
<i class="fas fa-eye"></i> Voir
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="row mt-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Actions</h5>
|
||||
<div class="d-flex gap-2">
|
||||
<a href="{{ path('app_membre_edit', {'id': membre.id}) }}" class="btn btn-warning">
|
||||
<i class="fas fa-edit"></i> Modifier
|
||||
</a>
|
||||
{{ include('membre/_delete_form.html.twig') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
69
templates/projet/edit.html.twig
Normal file
69
templates/projet/edit.html.twig
Normal file
@@ -0,0 +1,69 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Modifier Projet - {{ projet.nom }}{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Modifier Projet</h1>
|
||||
<div>
|
||||
<a href="{{ path('app_projet_show', {'id': projet.id}) }}" class="btn btn-info">
|
||||
<i class="fas fa-eye"></i> Voir
|
||||
</a>
|
||||
<a href="{{ path('app_projet_index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Retour à la liste
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{{ form_start(form) }}
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.nom) }}
|
||||
{{ form_widget(form.nom) }}
|
||||
{{ form_errors(form.nom) }}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.commentaire) }}
|
||||
{{ form_widget(form.commentaire) }}
|
||||
{{ form_errors(form.commentaire) }}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.dateLancement) }}
|
||||
{{ form_widget(form.dateLancement) }}
|
||||
{{ form_errors(form.dateLancement) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.dateCloture) }}
|
||||
{{ form_widget(form.dateCloture) }}
|
||||
{{ form_errors(form.dateCloture) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.statut) }}
|
||||
{{ form_widget(form.statut) }}
|
||||
{{ form_errors(form.statut) }}
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-save"></i> Enregistrer
|
||||
</button>
|
||||
<a href="{{ path('app_projet_index') }}" class="btn btn-secondary">Annuler</a>
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
64
templates/projet/index.html.twig
Normal file
64
templates/projet/index.html.twig
Normal file
@@ -0,0 +1,64 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Projets{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Projets</h1>
|
||||
<a href="{{ path('app_projet_new') }}" class="btn btn-success">
|
||||
<i class="fas fa-plus"></i> Nouveau Projet
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Nom</th>
|
||||
<th>Statut</th>
|
||||
<th>Date lancement</th>
|
||||
<th>Date clôture</th>
|
||||
<th>Commentaire</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for projet in projets %}
|
||||
<tr>
|
||||
<td>{{ projet.id }}</td>
|
||||
<td>{{ projet.nom }}</td>
|
||||
<td>
|
||||
{% set statutClass = {
|
||||
'en_attente': 'warning',
|
||||
'en_cours': 'info',
|
||||
'termine': 'success',
|
||||
'annule': 'danger'
|
||||
} %}
|
||||
<span class="badge bg-{{ statutClass[projet.statut]|default('secondary') }}">
|
||||
{% for label, value in projet.getStatutChoices() %}
|
||||
{% if value == projet.statut %}{{ label }}{% endif %}
|
||||
{% endfor %}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ projet.dateLancement ? projet.dateLancement|date('d/m/Y') : '-' }}</td>
|
||||
<td>{{ projet.dateCloture ? projet.dateCloture|date('d/m/Y') : '-' }}</td>
|
||||
<td>{{ projet.commentaire|default('')|slice(0, 50) }}{% if projet.commentaire|length > 50 %}...{% endif %}</td>
|
||||
<td>
|
||||
<a href="{{ path('app_projet_show', {'id': projet.id}) }}" class="btn btn-sm btn-info">
|
||||
<i class="fas fa-eye"></i> Voir
|
||||
</a>
|
||||
<a href="{{ path('app_projet_edit', {'id': projet.id}) }}" class="btn btn-sm btn-warning">
|
||||
<i class="fas fa-edit"></i> Modifier
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="7" class="text-center">Aucun projet trouvé</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
64
templates/projet/new.html.twig
Normal file
64
templates/projet/new.html.twig
Normal file
@@ -0,0 +1,64 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Nouveau Projet{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>Nouveau Projet</h1>
|
||||
<a href="{{ path('app_projet_index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Retour à la liste
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{{ form_start(form) }}
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.nom) }}
|
||||
{{ form_widget(form.nom) }}
|
||||
{{ form_errors(form.nom) }}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.commentaire) }}
|
||||
{{ form_widget(form.commentaire) }}
|
||||
{{ form_errors(form.commentaire) }}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.dateLancement) }}
|
||||
{{ form_widget(form.dateLancement) }}
|
||||
{{ form_errors(form.dateLancement) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.dateCloture) }}
|
||||
{{ form_widget(form.dateCloture) }}
|
||||
{{ form_errors(form.dateCloture) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{{ form_label(form.statut) }}
|
||||
{{ form_widget(form.statut) }}
|
||||
{{ form_errors(form.statut) }}
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-save"></i> Créer
|
||||
</button>
|
||||
<a href="{{ path('app_projet_index') }}" class="btn btn-secondary">Annuler</a>
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
103
templates/projet/show.html.twig
Normal file
103
templates/projet/show.html.twig
Normal file
@@ -0,0 +1,103 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Projet - {{ projet.nom }}{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>{{ projet.nom }}</h1>
|
||||
<div>
|
||||
<a href="{{ path('app_projet_edit', {'id': projet.id}) }}" class="btn btn-warning">
|
||||
<i class="fas fa-edit"></i> Modifier
|
||||
</a>
|
||||
<a href="{{ path('app_projet_index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Retour à la liste
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Informations générales</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p><strong>ID :</strong> {{ projet.id }}</p>
|
||||
<p><strong>Nom :</strong> {{ projet.nom }}</p>
|
||||
<p><strong>Statut :</strong>
|
||||
{% set statutClass = {
|
||||
'en_attente': 'warning',
|
||||
'en_cours': 'info',
|
||||
'termine': 'success',
|
||||
'annule': 'danger'
|
||||
} %}
|
||||
<span class="badge bg-{{ statutClass[projet.statut]|default('secondary') }}">
|
||||
{% for label, value in projet.getStatutChoices() %}
|
||||
{% if value == projet.statut %}{{ label }}{% endif %}
|
||||
{% endfor %}
|
||||
</span>
|
||||
</p>
|
||||
<p><strong>Date de lancement :</strong> {{ projet.dateLancement ? projet.dateLancement|date('d/m/Y') : 'Non définie' }}</p>
|
||||
<p><strong>Date de clôture :</strong> {{ projet.dateCloture ? projet.dateCloture|date('d/m/Y') : 'Non définie' }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Commentaire</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if projet.commentaire %}
|
||||
<p>{{ projet.commentaire }}</p>
|
||||
{% else %}
|
||||
<p class="text-muted">Aucun commentaire</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if projet.contributions|length > 0 %}
|
||||
<div class="row mt-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Contributions ({{ projet.contributions|length }})</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Membre</th>
|
||||
<th>Date</th>
|
||||
<th>Durée</th>
|
||||
<th>Commentaire</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for contribution in projet.contributions %}
|
||||
<tr>
|
||||
<td>{{ contribution.membre }}</td>
|
||||
<td>{{ contribution.dateContribution|date('d/m/Y') }}</td>
|
||||
<td>{{ contribution.dureeFormatee }}</td>
|
||||
<td>{{ contribution.commentaire|default('')|slice(0, 30) }}{% if contribution.commentaire|length > 30 %}...{% endif %}</td>
|
||||
<td>
|
||||
<a href="{{ path('app_contribution_show', {'id': contribution.id}) }}" class="btn btn-sm btn-info">
|
||||
<i class="fas fa-eye"></i> Voir
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
30
templates/security/login.html.twig
Normal file
30
templates/security/login.html.twig
Normal file
@@ -0,0 +1,30 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Connexion{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="row justify-content-center mt-5">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title">Connexion</h3>
|
||||
{% if error %}
|
||||
<div class="alert alert-danger">{{ error.messageKey|trans(error.messageData, 'security') }}</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="{{ path('app_login') }}">
|
||||
<div class="mb-3">
|
||||
<label for="inputEmail" class="form-label">Email</label>
|
||||
<input type="email" value="{{ last_username }}" name="email" id="inputEmail" class="form-control" required autofocus>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="inputPassword" class="form-label">Mot de passe</label>
|
||||
<input type="password" name="password" id="inputPassword" class="form-control" required>
|
||||
</div>
|
||||
<button class="btn btn-primary" type="submit">Se connecter</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
90
templates/test.html.twig
Normal file
90
templates/test.html.twig
Normal file
@@ -0,0 +1,90 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test Édition Inline</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
.editable-cell {
|
||||
cursor: pointer;
|
||||
background-color: #f8f9fa;
|
||||
padding: 8px;
|
||||
border: 1px solid #dee2e6;
|
||||
}
|
||||
.editable-cell:hover {
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
.editable-cell.editing {
|
||||
background-color: #e3f2fd;
|
||||
border: 2px solid #2196f3;
|
||||
}
|
||||
.inline-edit-input {
|
||||
border: none;
|
||||
background: transparent;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-4">
|
||||
<h1>Test d'Édition Inline</h1>
|
||||
|
||||
<div class="alert alert-info">
|
||||
<strong>Instructions :</strong> Cliquez sur les cellules pour les modifier.
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nom</th>
|
||||
<th>Prénom</th>
|
||||
<th>Email</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="editable-cell" data-entity-type="Membre" data-entity-id="1" data-field="nom">
|
||||
Jean
|
||||
</td>
|
||||
<td class="editable-cell" data-entity-type="Membre" data-entity-id="1" data-field="prenom">
|
||||
Dupont
|
||||
</td>
|
||||
<td class="editable-cell" data-entity-type="Membre" data-entity-id="1" data-field="email">
|
||||
jean.dupont@example.com
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div id="debug-info" class="mt-4">
|
||||
<h3>Informations de Débogage</h3>
|
||||
<div id="debug-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/js/test-inline.js"></script>
|
||||
<script>
|
||||
// Test de débogage
|
||||
console.log('Page de test chargée');
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
console.log('DOM chargé');
|
||||
|
||||
if (window.inlineEditing) {
|
||||
console.log('✅ InlineEditing initialisé');
|
||||
document.getElementById('debug-content').innerHTML = '<div class="alert alert-success">✅ JavaScript chargé et initialisé</div>';
|
||||
} else {
|
||||
console.error('❌ InlineEditing non initialisé');
|
||||
document.getElementById('debug-content').innerHTML = '<div class="alert alert-danger">❌ JavaScript non chargé</div>';
|
||||
}
|
||||
});
|
||||
|
||||
// Test des clics
|
||||
document.addEventListener('click', function(e) {
|
||||
if (e.target.classList.contains('editable-cell')) {
|
||||
console.log('Clic sur cellule éditables:', e.target);
|
||||
document.getElementById('debug-content').innerHTML += '<div class="alert alert-info">Clic détecté sur: ' + e.target.textContent + '</div>';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user