ajout de stats sur server.js + amélioration diverses
This commit is contained in:
parent
e87da06111
commit
ff974bd43c
@ -1,5 +1,6 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const session = require('express-session');
|
const session = require('express-session');
|
||||||
|
const FileStore = require('session-file-store')(session);
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const AnsiToHtml = require('ansi-to-html');
|
const AnsiToHtml = require('ansi-to-html');
|
||||||
@ -19,9 +20,17 @@ const port = config.port;
|
|||||||
app.use(express.urlencoded({ extended: true }));
|
app.use(express.urlencoded({ extended: true }));
|
||||||
|
|
||||||
app.use(session({
|
app.use(session({
|
||||||
|
store: new FileStore({
|
||||||
|
path: './sessions', // dossier où stocker les fichiers
|
||||||
|
ttl: 24 * 60 * 60, // durée de vie en secondes (ici 1 jour)
|
||||||
|
retries: 0
|
||||||
|
}),
|
||||||
secret: config.sessionSecret,
|
secret: config.sessionSecret,
|
||||||
resave: false,
|
resave: false,
|
||||||
saveUninitialized: false
|
saveUninitialized: false,
|
||||||
|
cookie: {
|
||||||
|
maxAge: 24 * 60 * 60 * 1000 // 1 jour en ms
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
app.use(express.static('public'));
|
app.use(express.static('public'));
|
||||||
@ -98,6 +107,16 @@ autopostRouter.get('/', async (req, res) => {
|
|||||||
const offset = (page - 1) * limit;
|
const offset = (page - 1) * limit;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const [stats] = await db.query(`
|
||||||
|
SELECT
|
||||||
|
COUNT(*) AS total,
|
||||||
|
SUM(status = 0) AS attente,
|
||||||
|
SUM(status = 1) AS termine,
|
||||||
|
SUM(status = 2) AS erreur,
|
||||||
|
SUM(status = 3) AS deja,
|
||||||
|
SUM(status = 4) AS encours
|
||||||
|
FROM \`${config.DB_TABLE}\`
|
||||||
|
`);
|
||||||
// Récupérer le nombre total d'enregistrements
|
// Récupérer le nombre total d'enregistrements
|
||||||
const [countResult] = await db.query(`SELECT COUNT(*) as total FROM \`${config.DB_TABLE}\``);
|
const [countResult] = await db.query(`SELECT COUNT(*) as total FROM \`${config.DB_TABLE}\``);
|
||||||
const totalRecords = countResult[0].total;
|
const totalRecords = countResult[0].total;
|
||||||
@ -120,13 +139,105 @@ autopostRouter.get('/', async (req, res) => {
|
|||||||
</head>
|
</head>
|
||||||
<body class="bg-slate-900 text-white font-sans p-4">
|
<body class="bg-slate-900 text-white font-sans p-4">
|
||||||
<div class="w-full px-4">
|
<div class="w-full px-4">
|
||||||
<h1 class="text-3xl font-bold mb-4">Suivi Autopost</h1>
|
<div class="mb-6">
|
||||||
<p class="mb-4">
|
<div class="flex items-center justify-between">
|
||||||
<a href="/autopost/logout" class="text-blue-400 hover:underline">Déconnexion</a>
|
<h1 class="text-2xl md:text-3xl font-extrabold tracking-tight bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-cyan-300">
|
||||||
</p>
|
Suivi Autopost
|
||||||
|
</h1>
|
||||||
|
<a href="/autopost/logout"
|
||||||
|
class="inline-flex items-center gap-2 px-3 py-2 rounded-xl bg-red-600/90 hover:bg-red-600 text-white shadow-lg shadow-red-900/20 transition">
|
||||||
|
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a2 2 0 01-2 2H6a2 2 0 01-2-2V7a2 2 0 012-2h5a2 2 0 012 2v1"/>
|
||||||
|
</svg>
|
||||||
|
Déconnexion
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<p class="mt-1 text-sm text-gray-400">Vue d’ensemble des traitements en cours et de l’état des envois.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Stat cards -->
|
||||||
|
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
|
||||||
|
<!-- En attente -->
|
||||||
|
<div class="group rounded-2xl p-3 md:p-5 bg-gradient-to-br from-cyan-500 to-cyan-400 text-black shadow-xl ring-1 ring-white/10 transition transform hover:-translate-y-0.5 hover:shadow-2xl cursor-pointer filter-card" data-status="0">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="rounded-xl bg-black/10 p-2">
|
||||||
|
<svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M12 6v6l4 2"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="text-sm/5 font-medium">En attente</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-3xl font-extrabold tabular-nums">${stats[0].attente}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Terminé -->
|
||||||
|
<div class="group rounded-2xl p-4 md:p-5 bg-gradient-to-br from-green-300 to-emerald-300 text-black shadow-xl ring-1 ring-white/10 transition transform hover:-translate-y-0.5 hover:shadow-2xl cursor-pointer filter-card" data-status="1">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="rounded-xl bg-black/10 p-2">
|
||||||
|
<svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M5 13l4 4L19 7"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="text-sm/5 font-medium">Terminé</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-3xl font-extrabold tabular-nums">${stats[0].termine}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Erreur -->
|
||||||
|
<div class="group rounded-2xl p-4 md:p-5 bg-gradient-to-br from-rose-300 to-red-300 text-black shadow-xl ring-1 ring-white/10 transition transform hover:-translate-y-0.5 hover:shadow-2xl cursor-pointer filter-card" data-status="2">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="rounded-xl bg-black/10 p-2">
|
||||||
|
<svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M12 9v3m0 4h.01M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="text-sm/5 font-medium">Erreur</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-3xl font-extrabold tabular-nums">${stats[0].erreur}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Déjà dispo -->
|
||||||
|
<div class="group rounded-2xl p-4 md:p-5 bg-gradient-to-br from-pink-300 to-fuchsia-300 text-black shadow-xl ring-1 ring-white/10 transition transform hover:-translate-y-0.5 hover:shadow-2xl cursor-pointer filter-card" data-status="3">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="rounded-xl bg-black/10 p-2">
|
||||||
|
<svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M8 7h8M8 11h8M8 15h6"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="text-sm/5 font-medium">Déjà dispo</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-3xl font-extrabold tabular-nums">${stats[0].deja}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Bouton réinitialiser -->
|
||||||
|
<div class="mb-4 text-center">
|
||||||
|
<button id="showAll"
|
||||||
|
class="hidden px-5 py-2 rounded-xl bg-gradient-to-br from-gray-600 to-gray-800 text-white font-semibold shadow-lg hover:from-gray-500 hover:to-gray-700 transition transform hover:-translate-y-0.5">
|
||||||
|
Tout afficher
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Search -->
|
||||||
|
<div class="mb-4">
|
||||||
|
<label for="searchInput" class="sr-only">Rechercher</label>
|
||||||
|
<div class="relative">
|
||||||
|
<span class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
||||||
|
<svg class="w-5 h-5 text-gray-400" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M21 21l-4.35-4.35M10 18a8 8 0 1 1 0-16 8 8 0 0 1 0 16z"/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input id="searchInput" type="text" placeholder="Rechercher…"
|
||||||
|
class="w-full pl-10 pr-3 py-2 rounded-xl bg-gray-800/80 border border-gray-700 focus:border-blue-500 focus:ring-4 focus:ring-blue-500/20 outline-none transition placeholder:text-gray-400" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<input type="text" id="searchInput" placeholder="Rechercher..."
|
|
||||||
class="p-2 mb-4 border border-gray-300 rounded w-full"/>
|
|
||||||
<nav aria-label="Page navigation" class="mb-4">
|
<nav aria-label="Page navigation" class="mb-4">
|
||||||
<ul class="inline-flex items-center -space-x-px">
|
<ul class="inline-flex items-center -space-x-px">
|
||||||
<li>
|
<li>
|
||||||
@ -147,16 +258,16 @@ autopostRouter.get('/', async (req, res) => {
|
|||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="min-w-full bg-gray-800">
|
<table class="min-w-full border border-gray-700 shadow-lg rounded-lg overflow-hidden">
|
||||||
<thead>
|
<thead class="bg-gray-900 text-gray-300 uppercase text-sm">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="px-4 py-2 border border-gray-700 whitespace-nowrap">Name</th>
|
<th class="px-4 py-2">Name</th>
|
||||||
<th class="px-4 py-2 border border-gray-700 whitespace-nowrap">Status</th>
|
<th class="px-4 py-2">Status</th>
|
||||||
<th class="px-4 py-2 border border-gray-700">ID</th>
|
<th class="px-4 py-2">ID</th>
|
||||||
<th class="px-4 py-2 border border-gray-700 whitespace-nowrap">Actions</th>
|
<th class="px-4 py-2">Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody class="divide-y divide-gray-700">
|
||||||
`;
|
`;
|
||||||
|
|
||||||
rows.forEach(row => {
|
rows.forEach(row => {
|
||||||
@ -258,168 +369,13 @@ autopostRouter.get('/', async (req, res) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function updateTable(rows) {
|
function updateTable(rows) {
|
||||||
let tbody = $("table tbody");
|
var tbody = $("table tbody");
|
||||||
tbody.empty();
|
tbody.empty();
|
||||||
rows.forEach(function(row) {
|
rows.forEach(function(row) {
|
||||||
let statusText = '';
|
var statusText = '';
|
||||||
let statusClass = '';
|
var statusClass = '';
|
||||||
switch (parseInt(row.status)) {
|
switch (parseInt(row.status)) {
|
||||||
case 0:
|
|
||||||
statusText = 'EN ATTENTE';
|
|
||||||
statusClass = 'bg-cyan-500 text-black font-bold';
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
statusText = 'ENVOI TERMINÉ';
|
|
||||||
statusClass = 'bg-green-300 text-black font-bold';
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
statusText = 'ERREUR';
|
|
||||||
statusClass = 'bg-red-300 text-black font-bold';
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
statusText = 'DEJA DISPONIBLE';
|
|
||||||
statusClass = 'bg-pink-300 text-black font-bold';
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
statusText = 'EN COURS';
|
|
||||||
statusClass = 'bg-yellow-300 text-black font-bold';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
statusText = 'INCONNU';
|
|
||||||
}
|
|
||||||
|
|
||||||
let logLink = parseInt(row.status) === 1 || parseInt(row.status) === 2
|
|
||||||
? ' | <a href="#" class="log-link text-blue-400 hover:underline" data-filename="'+row.nom+'">Log</a>'
|
|
||||||
: '';
|
|
||||||
let mediainfoLink = parseInt(row.status) === 0 || parseInt(row.status) === 1 || parseInt(row.status) === 2
|
|
||||||
? ' | <a href="#" class="mediainfo-link text-blue-400 hover:underline" data-filename="'+row.nom+'">Mediainfo</a>'
|
|
||||||
: '';
|
|
||||||
let dlLink = parseInt(row.status) === 1
|
|
||||||
? ' | <a href="/autopost/dl?name='+encodeURIComponent(row.nom)+'" class="dl-link text-blue-400 hover:underline">DL</a>'
|
|
||||||
: '';
|
|
||||||
let tr = \`
|
|
||||||
<tr id="row-\${row.id}" class="odd:bg-gray-800 even:bg-gray-700">
|
|
||||||
<td class="px-4 py-2 border border-gray-700 whitespace-nowrap">\${row.nom}</td>
|
|
||||||
<td class="px-4 py-2 border border-gray-700 status-text whitespace-nowrap \${statusClass}">\${statusText}</td>
|
|
||||||
<td class="px-4 py-2 border border-gray-700">\${row.id}</td>
|
|
||||||
<td class="px-4 py-2 border border-gray-700">
|
|
||||||
<a href="#" class="edit-link text-blue-400 hover:underline" data-id="\${row.id}" data-status="\${row.status}">Editer</a> |
|
|
||||||
<a href="#" class="delete-link text-blue-400 hover:underline" data-id="\${row.id}">Supprimer</a>\${logLink}\${mediainfoLink}\${dlLink}
|
|
||||||
</td>
|
|
||||||
</tr>\`;
|
|
||||||
tbody.append(tr);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$(document).ready(function(){
|
|
||||||
$("#searchInput").on("keyup", function() {
|
|
||||||
let q = $(this).val();
|
|
||||||
$.ajax({
|
|
||||||
url: '/autopost/search',
|
|
||||||
type: 'GET',
|
|
||||||
data: { q: q },
|
|
||||||
dataType: 'json',
|
|
||||||
success: function(data) {
|
|
||||||
updateTable(data);
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
alert("Erreur lors de la recherche.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on("click", ".edit-link", function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
let releaseId = $(this).data('id');
|
|
||||||
let currentStatus = $(this).data('status');
|
|
||||||
$('#releaseId').val(releaseId);
|
|
||||||
$('#modalReleaseId').text(releaseId);
|
|
||||||
$('#statusSelect').val(currentStatus);
|
|
||||||
$('#editModal').removeClass('hidden').fadeIn();
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on("click", ".delete-link", function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
if (confirm("Êtes-vous sûr de vouloir supprimer cet enregistrement ?")) {
|
|
||||||
let releaseId = $(this).data('id');
|
|
||||||
$.ajax({
|
|
||||||
url: '/autopost/delete/' + releaseId,
|
|
||||||
type: 'POST',
|
|
||||||
success: function(data) {
|
|
||||||
$('#row-' + releaseId).fadeOut('slow', function(){
|
|
||||||
$(this).remove();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
alert("Erreur lors de la suppression.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on("click", ".log-link", function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
let filename = $(this).data("filename");
|
|
||||||
$.ajax({
|
|
||||||
url: '/autopost/log',
|
|
||||||
type: 'GET',
|
|
||||||
data: { name: filename },
|
|
||||||
dataType: 'json',
|
|
||||||
success: function(data) {
|
|
||||||
$("#logContent").html(data.content);
|
|
||||||
$("#logModal").removeClass('hidden').fadeIn();
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
alert("Erreur lors du chargement du fichier log.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on("click", ".mediainfo-link", function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
let filename = $(this).data("filename");
|
|
||||||
$.ajax({
|
|
||||||
url: '/autopost/mediainfo',
|
|
||||||
type: 'GET',
|
|
||||||
data: { name: filename },
|
|
||||||
dataType: 'json',
|
|
||||||
success: function(data) {
|
|
||||||
$("#mediainfoContent").text(data.content);
|
|
||||||
$("#mediainfoModal").removeClass('hidden').fadeIn();
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
alert("Erreur lors du chargement du fichier mediainfo.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.close').click(function(){
|
|
||||||
$(this).closest('.fixed').fadeOut(function(){
|
|
||||||
$(this).addClass('hidden');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.fixed').click(function(e) {
|
|
||||||
if (e.target === this) {
|
|
||||||
$(this).fadeOut(function(){
|
|
||||||
$(this).addClass('hidden');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#editForm').submit(function(e){
|
|
||||||
e.preventDefault();
|
|
||||||
let releaseId = $('#releaseId').val();
|
|
||||||
let newStatus = $('#statusSelect').val();
|
|
||||||
$.ajax({
|
|
||||||
url: '/autopost/edit/' + releaseId,
|
|
||||||
type: 'POST',
|
|
||||||
data: { status: newStatus },
|
|
||||||
success: function(data) {
|
|
||||||
let statusText = '';
|
|
||||||
let statusClass = '';
|
|
||||||
switch(parseInt(newStatus)) {
|
|
||||||
case 0:
|
case 0:
|
||||||
statusText = 'EN ATTENTE';
|
statusText = 'EN ATTENTE';
|
||||||
statusClass = 'bg-cyan-500 text-black font-bold';
|
statusClass = 'bg-cyan-500 text-black font-bold';
|
||||||
@ -443,23 +399,229 @@ autopostRouter.get('/', async (req, res) => {
|
|||||||
default:
|
default:
|
||||||
statusText = 'INCONNU';
|
statusText = 'INCONNU';
|
||||||
}
|
}
|
||||||
let row = $('#row-' + releaseId);
|
|
||||||
// Mise à jour uniquement de la cellule status
|
var logLink = (parseInt(row.status) === 1 || parseInt(row.status) === 2)
|
||||||
row.find('.status-text')
|
? ' | <a href="#" class="log-link text-blue-400 hover:underline" data-filename="'+row.nom+'">Log</a>'
|
||||||
.removeClass('bg-cyan-500 bg-green-300 bg-red-300 bg-pink-300')
|
: '';
|
||||||
.addClass(statusClass)
|
var mediainfoLink = (parseInt(row.status) === 0 || parseInt(row.status) === 1 || parseInt(row.status) === 2)
|
||||||
.text(statusText);
|
? ' | <a href="#" class="mediainfo-link text-blue-400 hover:underline" data-filename="'+row.nom+'">Mediainfo</a>'
|
||||||
$('#editModal').fadeOut(function(){
|
: '';
|
||||||
|
var dlLink = (parseInt(row.status) === 1)
|
||||||
|
? ' | <a href="/autopost/dl?name='+encodeURIComponent(row.nom)+'" class="dl-link text-blue-400 hover:underline">DL</a>'
|
||||||
|
: '';
|
||||||
|
|
||||||
|
var tr = '<tr id="row-'+row.id+'" data-status="'+row.status+'" class="odd:bg-gray-800 even:bg-gray-700">'+
|
||||||
|
'<td class="px-4 py-2 border border-gray-700 whitespace-nowrap">'+row.nom+'</td>'+
|
||||||
|
'<td class="px-4 py-2 border border-gray-700 status-text whitespace-nowrap '+statusClass+'">'+statusText+'</td>'+
|
||||||
|
'<td class="px-4 py-2 border border-gray-700">'+row.id+'</td>'+
|
||||||
|
'<td class="px-4 py-2 border border-gray-700">'+
|
||||||
|
'<a href="#" class="edit-link text-blue-400 hover:underline" data-id="'+row.id+'" data-status="'+row.status+'">Editer</a> | '+
|
||||||
|
'<a href="#" class="delete-link text-blue-400 hover:underline" data-id="'+row.id+'">Supprimer</a>'+
|
||||||
|
logLink+mediainfoLink+dlLink+
|
||||||
|
'</td>'+
|
||||||
|
'</tr>';
|
||||||
|
tbody.append(tr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filtrage combiné avec recherche
|
||||||
|
var currentFilter = null; // null => pas de filtre actif
|
||||||
|
|
||||||
|
function applyFilterAndSearch() {
|
||||||
|
var q = ($("#searchInput").val() || "").toLowerCase();
|
||||||
|
$("table tbody tr").each(function() {
|
||||||
|
var $tr = $(this);
|
||||||
|
var name = $tr.find("td:first").text().toLowerCase();
|
||||||
|
var status = parseInt($tr.data("status"), 10);
|
||||||
|
|
||||||
|
var matchFilter = (currentFilter === null) || (status === currentFilter);
|
||||||
|
var matchSearch = !q || name.indexOf(q) !== -1;
|
||||||
|
|
||||||
|
$tr.toggle(matchFilter && matchSearch);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
|
||||||
|
// Recherche AJAX
|
||||||
|
$("#searchInput").on("keyup", function() {
|
||||||
|
var q = $(this).val();
|
||||||
|
$.ajax({
|
||||||
|
url: '/autopost/search',
|
||||||
|
type: 'GET',
|
||||||
|
data: { q: q },
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(data) {
|
||||||
|
updateTable(data);
|
||||||
|
applyFilterAndSearch(); // conserve filtre actif
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
alert("Erreur lors de la recherche.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function toggleShowAllButton() {
|
||||||
|
if (currentFilter === null) {
|
||||||
|
$('#showAll').addClass('hidden');
|
||||||
|
} else {
|
||||||
|
$('#showAll').removeClass('hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filtrage par clic sur une card
|
||||||
|
$(document).on("click", ".filter-card", function() {
|
||||||
|
currentFilter = parseInt($(this).data("status"), 10);
|
||||||
|
$(".filter-card").removeClass("ring-4 ring-white/40");
|
||||||
|
$(this).addClass("ring-4 ring-white/40");
|
||||||
|
applyFilterAndSearch();
|
||||||
|
toggleShowAllButton();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Bouton tout afficher
|
||||||
|
$(document).on("click", "#showAll", function() {
|
||||||
|
currentFilter = null;
|
||||||
|
$(".filter-card").removeClass("ring-4 ring-white/40");
|
||||||
|
applyFilterAndSearch();
|
||||||
|
toggleShowAllButton();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Edition
|
||||||
|
$(document).on("click", ".edit-link", function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var releaseId = $(this).data('id');
|
||||||
|
var currentStatus = $(this).data('status');
|
||||||
|
$('#releaseId').val(releaseId);
|
||||||
|
$('#modalReleaseId').text(releaseId);
|
||||||
|
$('#statusSelect').val(currentStatus);
|
||||||
|
$('#editModal').removeClass('hidden').fadeIn();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Suppression
|
||||||
|
$(document).on("click", ".delete-link", function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (confirm("Êtes-vous sûr de vouloir supprimer cet enregistrement ?")) {
|
||||||
|
var releaseId = $(this).data('id');
|
||||||
|
$.ajax({
|
||||||
|
url: '/autopost/delete/' + releaseId,
|
||||||
|
type: 'POST',
|
||||||
|
success: function(data) {
|
||||||
|
$('#row-' + releaseId).fadeOut('slow', function(){
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
alert("Erreur lors de la suppression.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Affichage log
|
||||||
|
$(document).on("click", ".log-link", function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var filename = $(this).data("filename");
|
||||||
|
$.ajax({
|
||||||
|
url: '/autopost/log',
|
||||||
|
type: 'GET',
|
||||||
|
data: { name: filename },
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(data) {
|
||||||
|
$("#logContent").html(data.content);
|
||||||
|
$("#logModal").removeClass('hidden').fadeIn();
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
alert("Erreur lors du chargement du fichier log.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Affichage mediainfo
|
||||||
|
$(document).on("click", ".mediainfo-link", function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var filename = $(this).data("filename");
|
||||||
|
$.ajax({
|
||||||
|
url: '/autopost/mediainfo',
|
||||||
|
type: 'GET',
|
||||||
|
data: { name: filename },
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(data) {
|
||||||
|
$("#mediainfoContent").text(data.content);
|
||||||
|
$("#mediainfoModal").removeClass('hidden').fadeIn();
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
alert("Erreur lors du chargement du fichier mediainfo.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fermeture modales
|
||||||
|
$('.close').click(function(){
|
||||||
|
$(this).closest('.fixed').fadeOut(function(){
|
||||||
$(this).addClass('hidden');
|
$(this).addClass('hidden');
|
||||||
});
|
});
|
||||||
},
|
});
|
||||||
error: function() {
|
|
||||||
alert("Erreur lors de la mise à jour.");
|
$('.fixed').click(function(e) {
|
||||||
}
|
if (e.target === this) {
|
||||||
|
$(this).fadeOut(function(){
|
||||||
|
$(this).addClass('hidden');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Edition formulaire
|
||||||
|
$('#editForm').submit(function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
var releaseId = $('#releaseId').val();
|
||||||
|
var newStatus = $('#statusSelect').val();
|
||||||
|
$.ajax({
|
||||||
|
url: '/autopost/edit/' + releaseId,
|
||||||
|
type: 'POST',
|
||||||
|
data: { status: newStatus },
|
||||||
|
success: function(data) {
|
||||||
|
var statusText = '';
|
||||||
|
var statusClass = '';
|
||||||
|
switch(parseInt(newStatus)) {
|
||||||
|
case 0:
|
||||||
|
statusText = 'EN ATTENTE';
|
||||||
|
statusClass = 'bg-cyan-500 text-black font-bold';
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
statusText = 'ENVOI TERMINÉ';
|
||||||
|
statusClass = 'bg-green-300 text-black font-bold';
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
statusText = 'ERREUR';
|
||||||
|
statusClass = 'bg-red-300 text-black font-bold';
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
statusText = 'DEJA DISPONIBLE';
|
||||||
|
statusClass = 'bg-pink-300 text-black font-bold';
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
statusText = 'EN COURS';
|
||||||
|
statusClass = 'bg-yellow-300 text-black font-bold';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
statusText = 'INCONNU';
|
||||||
|
}
|
||||||
|
var row = $('#row-' + releaseId);
|
||||||
|
row.find('.status-text')
|
||||||
|
.removeClass('bg-cyan-500 bg-green-300 bg-red-300 bg-pink-300 bg-yellow-300')
|
||||||
|
.addClass(statusClass)
|
||||||
|
.text(statusText);
|
||||||
|
$('#editModal').fadeOut(function(){
|
||||||
|
$(this).addClass('hidden');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
alert("Erreur lors de la mise à jour.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
</script>
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`;
|
`;
|
||||||
|
|||||||
@ -363,7 +363,7 @@ export NVM_DIR="$HOME/.nvm"
|
|||||||
# Vérification des modules npm nécessaires
|
# Vérification des modules npm nécessaires
|
||||||
log "Vérification des modules npm requis..."
|
log "Vérification des modules npm requis..."
|
||||||
|
|
||||||
modules=("express" "express-session" "sqlite3" "ansi-to-html" "@tailwindcss/browser" "autoprefixer" "jquery" "mysql2")
|
modules=("express" "express-session" "sqlite3" "ansi-to-html" "@tailwindcss/browser" "autoprefixer" "jquery" "mysql2" "session-file-store")
|
||||||
missing_modules=()
|
missing_modules=()
|
||||||
|
|
||||||
for module in "${modules[@]}"; do
|
for module in "${modules[@]}"; do
|
||||||
|
|||||||
@ -209,7 +209,7 @@ export NVM_DIR="$HOME/.nvm"
|
|||||||
# Vérification des modules npm nécessaires
|
# Vérification des modules npm nécessaires
|
||||||
log "Vérification des modules npm requis..."
|
log "Vérification des modules npm requis..."
|
||||||
|
|
||||||
modules=("express" "express-session" "sqlite3" "ansi-to-html" "@tailwindcss/browser" "jquery" "mysql2")
|
modules=("express" "express-session" "sqlite3" "ansi-to-html" "@tailwindcss/browser" "jquery" "mysql2" "session-file-store")
|
||||||
missing_modules=()
|
missing_modules=()
|
||||||
|
|
||||||
for module in "${modules[@]}"; do
|
for module in "${modules[@]}"; do
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user