feat(system): implémenter la page Logs des erreurs de scraping
- Nouveau domaine `system` avec `logsStore` (Pinia) filtré sur status=failed&type=scraping_job, tri, pagination et suppression - Composant `LogItem` : affiche titre manga, chapitre, date, durée, domaine source (lien vers page d'édition), badge type scraping, slug utilisé, message d'erreur expandable - Page `LogsPage` : toolbar avec badge total, dropdown tri, rafraîchir, tout supprimer ; charge les ContentSources pour enrichir l'affichage - Route /system/logs branchée sur LogsPage - ApiJobRepository : ajout du paramètre `type` dans getJobs - Job entity : ajout des champs startedAt et completedAt
This commit is contained in:
parent
36f873aaca
commit
670e3f5315
93
assets/vue/app/domain/system/application/store/logsStore.js
Normal file
93
assets/vue/app/domain/system/application/store/logsStore.js
Normal file
@@ -0,0 +1,93 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { ApiJobRepository } from '../../../activity/infrastructure/api/ApiJobRepository';
|
||||
|
||||
const jobRepository = new ApiJobRepository();
|
||||
|
||||
export const useLogsStore = defineStore('logs', {
|
||||
state: () => ({
|
||||
logs: [],
|
||||
loading: false,
|
||||
error: null,
|
||||
currentPage: 1,
|
||||
totalPages: 0,
|
||||
total: 0,
|
||||
limit: 50,
|
||||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
sortBy: 'createdAt',
|
||||
sortOrder: 'DESC',
|
||||
}),
|
||||
|
||||
getters: {
|
||||
isLoading: state => state.loading,
|
||||
hasError: state => !!state.error,
|
||||
},
|
||||
|
||||
actions: {
|
||||
async loadLogs(page = null) {
|
||||
this.loading = true;
|
||||
this.error = null;
|
||||
|
||||
try {
|
||||
const collection = await jobRepository.getJobs({
|
||||
page: page || this.currentPage,
|
||||
limit: this.limit,
|
||||
sortBy: this.sortBy,
|
||||
sortOrder: this.sortOrder,
|
||||
status: ['failed'],
|
||||
type: 'scraping_job',
|
||||
});
|
||||
|
||||
this.logs = collection.items;
|
||||
this.currentPage = collection.page;
|
||||
this.total = collection.total;
|
||||
this.hasNextPage = collection.hasNextPage;
|
||||
this.hasPreviousPage = collection.hasPreviousPage;
|
||||
this.totalPages = Math.ceil(this.total / this.limit);
|
||||
} catch (error) {
|
||||
this.error = error.message;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
async goToPage(page) {
|
||||
if (page >= 1 && page <= this.totalPages && page !== this.currentPage) {
|
||||
this.currentPage = page;
|
||||
await this.loadLogs(page);
|
||||
}
|
||||
},
|
||||
|
||||
async updateSort(sortBy, sortOrder) {
|
||||
this.sortBy = sortBy;
|
||||
this.sortOrder = sortOrder;
|
||||
this.currentPage = 1;
|
||||
await this.loadLogs(1);
|
||||
},
|
||||
|
||||
async deleteLog(id) {
|
||||
try {
|
||||
await jobRepository.deleteJob(id);
|
||||
this.logs = this.logs.filter(log => log.id !== id);
|
||||
this.total = Math.max(0, this.total - 1);
|
||||
this.totalPages = Math.ceil(this.total / this.limit);
|
||||
} catch (error) {
|
||||
this.error = error.message;
|
||||
}
|
||||
},
|
||||
|
||||
async deleteAllLogs() {
|
||||
this.loading = true;
|
||||
this.error = null;
|
||||
|
||||
try {
|
||||
await jobRepository.deleteJobs({ status: 'failed', type: 'scraping_job' });
|
||||
await this.loadLogs(1);
|
||||
} catch (error) {
|
||||
this.error = error.message;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user