feat: ajout de la pagination et des filtres dans le store d'activités, mise à jour des composants pour gérer l'affichage des jobs, et amélioration de la gestion des états des jobs. Intégration d'une nouvelle composante de pagination pour une navigation optimisée.

This commit is contained in:
ext.jeremy.guillot@maxicoffee.domains
2025-07-13 13:22:42 +02:00
parent b456f9304d
commit b4bfa48d00
6 changed files with 382 additions and 41 deletions

View File

@@ -2,10 +2,10 @@
<tr
class="border-b border-gray-200 hover:bg-gray-50 transition duration-150 ease-in-out"
:class="{
'bg-yellow-50': job.status === 'PENDING',
'bg-blue-50': job.status === 'IN_PROGRESS',
'bg-green-50': job.status === 'COMPLETED',
'bg-red-50': job.status === 'ERROR'
'bg-yellow-50': job.status === 'pending',
'bg-blue-50': job.status === 'in_progress',
'bg-green-50': job.status === 'completed',
'bg-red-50': job.status === 'failed'
}">
<td class="py-4 px-4 text-center">
<input type="checkbox" class="form-checkbox h-5 w-5 text-green-600" />
@@ -32,7 +32,7 @@
</div>
</td>
<td class="py-4 px-4">
<div v-if="job.status === 'IN_PROGRESS'" class="mt-2">
<div v-if="job.status === 'in_progress'" class="mt-2">
<div class="relative bg-gray-200 rounded-full h-6 overflow-hidden">
<div
class="absolute top-0 left-0 h-full bg-green-400 transition-all duration-300 ease-out"
@@ -42,7 +42,7 @@
</div>
</div>
</div>
<div v-else-if="job.status === 'COMPLETED'" class="relative bg-gray-200 rounded-full h-6 overflow-hidden">
<div v-else-if="job.status === 'completed'" class="relative bg-gray-200 rounded-full h-6 overflow-hidden">
<div
class="absolute top-0 left-0 h-full bg-green-400 transition-all duration-300 ease-out"
style="width: 100%"></div>
@@ -50,7 +50,7 @@
100%
</div>
</div>
<div v-else-if="job.status === 'ERROR'" class="relative bg-gray-200 rounded-full h-6 overflow-hidden">
<div v-else-if="job.status === 'failed'" class="relative bg-gray-200 rounded-full h-6 overflow-hidden">
<div
class="absolute top-0 left-0 h-full bg-red-400 transition-all duration-300 ease-out"
style="width: 100%"></div>
@@ -79,8 +79,8 @@
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';
import { TrashIcon } from '@heroicons/vue/24/outline';
import { defineEmits, defineProps } from 'vue';
const props = defineProps({
job: {

View File

@@ -11,7 +11,17 @@
</div>
<div v-else class="container mx-auto p-2">
<div class="bg-white overflow-hidden">
<!-- Debug pagination - À supprimer plus tard -->
<div class="bg-yellow-100 border border-yellow-400 text-yellow-700 px-4 py-3 rounded mb-4" v-if="true">
<strong>Debug Pagination:</strong>
Total: {{ activityStore.total }},
Limit: {{ activityStore.limit }},
Pages: {{ activityStore.totalPages }},
Page courante: {{ activityStore.currentPage }},
Condition: {{ activityStore.total > activityStore.limit }}
</div>
<div class="bg-white overflow-hidden shadow rounded-lg">
<div class="overflow-x-auto">
<table class="min-w-full bg-white">
<thead>
@@ -32,9 +42,13 @@
<tbody class="text-gray-700">
<template v-if="activityStore.jobs.length === 0">
<tr>
<td colspan="6" class="py-4 px-4 text-center text-gray-500"
>Aucune activité trouvée avec les filtres actuels.</td
>
<td colspan="6" class="py-8 px-4 text-center text-gray-500">
<div class="flex flex-col items-center">
<ClockIcon class="h-12 w-12 text-gray-300 mb-4" />
<p class="text-lg font-medium">Aucune activité trouvée</p>
<p class="text-sm">Aucune activité ne correspond aux filtres actuels.</p>
</div>
</td>
</tr>
</template>
<template v-else>
@@ -47,33 +61,47 @@
</tbody>
</table>
</div>
<!-- Pagination -->
<Pagination
v-if="activityStore.total > activityStore.limit"
:current-page="activityStore.currentPage"
:total-pages="activityStore.totalPages"
:total="activityStore.total"
:limit="activityStore.limit"
:has-next-page="activityStore.hasNextPage"
:has-previous-page="activityStore.hasPreviousPage"
@page-change="changePage" />
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, ref, computed } from 'vue';
import { useActivityStore } from '../../application/store/activityStore';
import JobItem from '../components/JobItem.vue';
import Toolbar from '../../../../shared/components/ui/Toolbar.vue';
import { ArrowPathIcon, TrashIcon, FunnelIcon } from '@heroicons/vue/24/outline';
import { ArrowPathIcon, ClockIcon, FunnelIcon, TrashIcon } from '@heroicons/vue/24/outline';
import { computed, onMounted, ref } from 'vue';
import Pagination from '../../../../shared/components/ui/Pagination.vue';
import Toolbar from '../../../../shared/components/ui/Toolbar.vue';
import { useActivityStore } from '../../application/store/activityStore';
import JobItem from '../components/JobItem.vue';
const activityStore = useActivityStore();
const selectedAll = ref(false);
// Statuts disponibles pour le filtre
const statusOptions = [
{ value: ['PENDING', 'IN_PROGRESS'], label: 'Actifs' },
{ value: ['PENDING', 'IN_PROGRESS', 'COMPLETED', 'ERROR'], label: 'Tous' },
{ value: ['COMPLETED'], label: 'Terminés' },
{ value: ['ERROR'], label: 'En erreur' }
{ value: ['pending', 'in_progress'], label: 'Actifs' },
{ value: ['pending', 'in_progress', 'completed', 'failed'], label: 'Tous' },
{ value: ['completed'], label: 'Terminés' },
{ value: ['failed'], label: 'En erreur' },
{ value: ['pending'], label: 'En attente' },
{ value: ['in_progress'], label: 'En cours' }
];
// Index du statut actif
// Index du statut actif (par défaut "Actifs")
const activeStatusIndex = ref(0);
// Rendre toolbarConfig computed pour que le label du dropdown soit réactif
// Configuration de la toolbar réactive
const toolbarConfig = computed(() => ({
leftSection: [
{
@@ -98,7 +126,7 @@
{
icon: TrashIcon,
type: 'button',
label: 'Supprimer',
label: 'Supprimer visibles',
onClick: deleteVisibleJobs
}
]
@@ -116,6 +144,10 @@
loadJobs();
}
function changePage(page) {
activityStore.goToPage(page);
}
function toggleSelectAll() {
selectedAll.value = !selectedAll.value;
// La logique pour sélectionner tous les jobs serait ajoutée ici
@@ -135,7 +167,12 @@
}
function deleteVisibleJobs() {
if (confirm('Voulez-vous vraiment supprimer tous les jobs affichés ?')) {
if (activityStore.jobs.length === 0) {
return;
}
const statusLabel = statusOptions[activeStatusIndex.value].label.toLowerCase();
if (confirm(`Voulez-vous vraiment supprimer tous les jobs ${statusLabel} ?`)) {
activityStore.deleteJobs({ status: activityStore.filter.status });
}
}