runflare / templates /index.html
Sada8888's picture
Create index.html
c325a1d verified
Raw
History Blame Contribute Delete
17.6 kB
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>داشبورد هوشمند مدیریت گیت‌هاب اکشنز</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;600;800&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Vazirmatn', system-ui, -apple-system, sans-serif;
background-color: #0f172a;
color: #f1f5f9;
}
</style>
</head>
<body class="min-h-screen py-10 px-4">
<div class="max-w-6xl w-full mx-auto bg-slate-900 border border-slate-800 rounded-2xl shadow-2xl p-6 md:p-8">
<!-- Header -->
<header class="text-center mb-8 border-b border-slate-800 pb-6 flex flex-col md:flex-row md:justify-between md:items-center">
<div class="text-right">
<h1 class="text-3xl font-extrabold text-blue-500 mb-2">داشبورد مدیریت گیت‌هاب اکشنز</h1>
<p class="text-slate-400 text-sm">مانیتورینگ، پاک‌سازی و مدیریت فرآیندها به صورت آنی</p>
</div>
<div class="mt-4 md:mt-0 flex gap-3 flex-wrap">
<a href="/fluxpro" class="bg-indigo-600 hover:bg-indigo-700 text-white font-semibold py-2 px-4 rounded-lg text-sm transition-colors">ابزار Flux Pro</a>
<a href="/flux2" class="bg-teal-600 hover:bg-teal-700 text-white font-semibold py-2 px-4 rounded-lg text-sm transition-colors">ابزار FLUX.2</a>
</div>
</header>
<!-- Stats Grid -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
<div class="bg-slate-800/40 p-6 rounded-xl border border-slate-800 flex flex-col items-center shadow-lg">
<span class="text-xs font-semibold text-slate-400 mb-1">اکشن‌های در حال کار</span>
<span id="activeCount" class="text-3xl font-bold text-yellow-500">۰</span>
</div>
<div class="bg-slate-800/40 p-6 rounded-xl border border-slate-800 flex flex-col items-center shadow-lg">
<span class="text-xs font-semibold text-slate-400 mb-1">اکشن‌های غیرفعال امروز</span>
<span id="inactiveCount" class="text-3xl font-bold text-blue-500">۰</span>
</div>
<div class="bg-slate-800/40 p-6 rounded-xl border border-slate-800 flex flex-col items-center shadow-lg">
<span class="text-xs font-semibold text-slate-400 mb-1">کارهای موفق امروز</span>
<span id="completedCount" class="text-3xl font-bold text-green-500">۰</span>
</div>
</div>
<!-- Action Control Buttons -->
<div class="bg-slate-800/20 border border-slate-800/80 p-6 rounded-xl mb-8">
<h3 class="text-lg font-bold text-slate-300 mb-4 text-right">عملیات کنترلی</h3>
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4">
<button onclick="loadActiveActions()" class="bg-yellow-600/20 border border-yellow-500/30 text-yellow-400 hover:bg-yellow-600/30 font-semibold py-2.5 px-4 rounded-lg text-sm transition-all">
دیدن اکشن‌های در حال کار
</button>
<button onclick="loadInactiveToday()" class="bg-blue-600/20 border border-blue-500/30 text-blue-400 hover:bg-blue-600/30 font-semibold py-2.5 px-4 rounded-lg text-sm transition-all">
دیدن اکشن‌های غیر فعال امروز
</button>
<button onclick="loadCompletedTodayCount()" class="bg-green-600/20 border border-green-500/30 text-green-400 hover:bg-green-600/30 font-semibold py-2.5 px-4 rounded-lg text-sm transition-all">
تعداد کارهای انجام شده امروز
</button>
<button onclick="deleteInactive()" class="bg-red-600/20 border border-red-500/30 text-red-400 hover:bg-red-600/30 font-semibold py-2.5 px-4 rounded-lg text-sm transition-all">
حذف تمام اکشن‌های غیرفعال
</button>
<button onclick="deleteFailedCompleted()" class="bg-rose-600/20 border border-rose-500/30 text-rose-400 hover:bg-rose-600/30 font-semibold py-2.5 px-4 rounded-lg text-sm transition-all">
حذف تمام تکمیل شده و خطا زده
</button>
<button onclick="cancelDeleteActive()" class="bg-orange-600/20 border border-orange-500/30 text-orange-400 hover:bg-orange-600/30 font-semibold py-2.5 px-4 rounded-lg text-sm transition-all">
غیرفعال کردن اکشن‌های فعال و حذف آن‌ها
</button>
</div>
</div>
<!-- Table for Displaying List -->
<div id="displayContainer" class="hidden border border-slate-800 bg-slate-950/40 rounded-2xl p-6">
<div class="flex justify-between items-center mb-4">
<h3 id="tableTitle" class="text-lg font-bold text-slate-300">لیست فرآیندها</h3>
<span id="tableLoading" class="hidden text-sm text-blue-400 animate-pulse">در حال بروزرسانی...</span>
</div>
<div class="overflow-x-auto">
<table class="w-full text-right text-sm text-slate-300">
<thead class="bg-slate-800 text-xs text-slate-400">
<tr>
<th class="p-3 rounded-r-lg">شناسه اکشن</th>
<th class="p-3">نام اکشن</th>
<th class="p-3">وضعیت</th>
<th class="p-3">نتیجه</th>
<th class="p-3">زمان شروع</th>
<th class="p-3 rounded-l-lg text-left">لینک گیت‌هاب</th>
</tr>
</thead>
<tbody id="runsListTable">
<!-- Dynamic Rows -->
</tbody>
</table>
</div>
</div>
<!-- Alert messages -->
<div id="statusAlert" class="hidden mt-6 bg-slate-800 border border-slate-700 text-slate-300 text-sm rounded-xl p-4 text-right shadow-md"></div>
</div>
<script>
window.addEventListener('load', () => {
updateStats();
});
async function updateStats() {
try {
const resActive = await fetch('/api/actions/active');
const dataActive = await resActive.json();
if (dataActive.status === 'success') {
document.getElementById('activeCount').textContent = dataActive.actions.length;
}
const resInactive = await fetch('/api/actions/inactive-today');
const dataInactive = await resInactive.json();
if (dataInactive.status === 'success') {
document.getElementById('inactiveCount').textContent = dataInactive.actions.length;
}
const resCompleted = await fetch('/api/actions/completed-today-count');
const dataCompleted = await resCompleted.json();
if (dataCompleted.status === 'success') {
document.getElementById('completedCount').textContent = dataCompleted.count;
}
} catch (e) {
console.error('Error updating dashboard stats:', e);
}
}
function showAlert(msg, isSuccess = true) {
const alert = document.getElementById('statusAlert');
alert.textContent = msg;
alert.className = isSuccess
? 'mt-6 bg-emerald-950/40 border border-emerald-900 text-emerald-300 text-sm rounded-xl p-4 text-right shadow-md'
: 'mt-6 bg-rose-950/40 border border-rose-900 text-rose-300 text-sm rounded-xl p-4 text-right shadow-md';
alert.classList.remove('hidden');
setTimeout(() => { alert.classList.add('hidden'); }, 5000);
}
async function loadActiveActions() {
const container = document.getElementById('displayContainer');
const tbody = document.getElementById('runsListTable');
const title = document.getElementById('tableTitle');
const loading = document.getElementById('tableLoading');
container.classList.remove('hidden');
loading.classList.remove('hidden');
tbody.innerHTML = '';
title.textContent = 'اکشن‌های در حال کار (Queued / In Progress)';
try {
const res = await fetch('/api/actions/active');
const data = await res.json();
loading.classList.add('hidden');
if (data.status === 'success' && data.actions.length > 0) {
data.actions.forEach(action => {
const row = `
<tr class="border-b border-slate-800/50 hover:bg-slate-800/30">
<td class="p-3 font-mono">${action.id}</td>
<td class="p-3 font-semibold text-slate-200">${action.name}</td>
<td class="p-3"><span class="px-2 py-1 text-xs font-semibold rounded bg-yellow-950/40 text-yellow-400 border border-yellow-900">${action.status}</span></td>
<td class="p-3 text-slate-400">نامعلوم</td>
<td class="p-3 text-xs text-slate-400">${new Date(action.created_at).toLocaleString('fa-IR')}</td>
<td class="p-3 text-left"><a href="${action.html_url}" target="_blank" class="text-blue-400 hover:underline">دیدن در گیت‌هاب</a></td>
</tr>
`;
tbody.insertAdjacentHTML('beforeend', row);
});
} else {
tbody.innerHTML = '<tr><td colspan="6" class="p-4 text-center text-slate-500">هیچ اکشن فعال در حال کارهای شما نیست.</td></tr>';
}
} catch (e) {
loading.classList.add('hidden');
showAlert('خطا در دریافت اطلاعات!', false);
}
}
async function loadInactiveToday() {
const container = document.getElementById('displayContainer');
const tbody = document.getElementById('runsListTable');
const title = document.getElementById('tableTitle');
const loading = document.getElementById('tableLoading');
container.classList.remove('hidden');
loading.classList.remove('hidden');
tbody.innerHTML = '';
title.textContent = 'اکشن‌های غیر فعال امروز (Completed)';
try {
const res = await fetch('/api/actions/inactive-today');
const data = await res.json();
loading.classList.add('hidden');
if (data.status === 'success' && data.actions.length > 0) {
data.actions.forEach(action => {
let badgeColor = action.conclusion === 'success' ? 'bg-emerald-950/40 text-emerald-400 border-emerald-900' : 'bg-rose-950/40 text-rose-400 border-rose-900';
const row = `
<tr class="border-b border-slate-800/50 hover:bg-slate-800/30">
<td class="p-3 font-mono">${action.id}</td>
<td class="p-3 font-semibold text-slate-200">${action.name}</td>
<td class="p-3"><span class="px-2 py-1 text-xs font-semibold rounded bg-blue-950/40 text-blue-400 border border-blue-900">${action.status}</span></td>
<td class="p-3"><span class="px-2 py-1 text-xs font-semibold rounded border ${badgeColor}">${action.conclusion || 'نامعلوم'}</span></td>
<td class="p-3 text-xs text-slate-400">${new Date(action.created_at).toLocaleString('fa-IR')}</td>
<td class="p-3 text-left"><a href="${action.html_url}" target="_blank" class="text-blue-400 hover:underline">دیدن در گیت‌هاب</a></td>
</tr>
`;
tbody.insertAdjacentHTML('beforeend', row);
});
} else {
tbody.innerHTML = '<tr><td colspan="6" class="p-4 text-center text-slate-500">هیچ اکشن غیرفعال‌شده‌ای برای امروز ثبت نشده است.</td></tr>';
}
} catch (e) {
loading.classList.add('hidden');
showAlert('خطا در دریافت اطلاعات!', false);
}
}
async function loadCompletedTodayCount() {
try {
const res = await fetch('/api/actions/completed-today-count');
const data = await res.json();
if (data.status === 'success') {
showAlert(`تعداد کارهای با موفقیت انجام شده امروز: ${data.count} عدد`, true);
updateStats();
}
} catch (e) {
showAlert('خطا در دریافت اطلاعات آمار امروز!', false);
}
}
async function deleteInactive() {
if (!confirm('آیا مطمئن هستید که می‌خواهید تمام اکشن‌های غیرفعال را حذف کنید؟ این عمل غیر قابل بازگشت است.')) return;
showAlert('در حال ارسال درخواست پاک‌سازی اکشن‌های غیرفعال از گیت‌هاب...', true);
try {
const res = await fetch('/api/actions/delete-inactive', { method: 'POST' });
const data = await res.json();
if (data.status === 'success') {
showAlert(`عملیات موفقیت‌آمیز بود! تعداد ${data.deleted_count} اکشن غیرفعال با موفقیت حذف شد.`, true);
updateStats();
document.getElementById('displayContainer').classList.add('hidden');
} else {
showAlert('خطایی در انجام فرآیند حذف رخ داد.', false);
}
} catch (e) {
showAlert('خطای ارتباط با سرور بک‌اند!', false);
}
}
async function deleteFailedCompleted() {
if (!confirm('آیا مطمئن هستید که می‌خواهید تمام اکشن‌های تکمیل‌شده، خطا زده و کنسل شده را به صورت کامل حذف کنید؟')) return;
showAlert('در حال ارسال درخواست پاک‌سازی اکشن‌های تکمیل شده و خطا زده از گیت‌هاب...', true);
try {
const res = await fetch('/api/actions/delete-failed-completed', { method: 'POST' });
const data = await res.json();
if (data.status === 'success') {
showAlert(`عملیات موفقیت‌آمیز بود! تعداد ${data.deleted_count} اکشن تکمیل شده یا خطا زده با موفقیت حذف گردید.`, true);
updateStats();
document.getElementById('displayContainer').classList.add('hidden');
} else {
showAlert('خطایی در انجام فرآیند حذف رخ داد.', false);
}
} catch (e) {
showAlert('خطای ارتباط با سرور بک‌اند!', false);
}
}
async function cancelDeleteActive() {
if (!confirm('آیا مطمئن هستید که می‌خواهید تمام اکشن‌های فعال در حال اجرا را لغو (متوقف) و به طور کامل حذف کنید؟')) return;
showAlert('در حال ارسال درخواست لغو و حذف اکشن‌های فعال به گیت‌هاب...', true);
try {
const res = await fetch('/api/actions/cancel-delete-active', { method: 'POST' });
const data = await res.json();
if (data.status === 'success') {
showAlert(`عملیات با موفقیت انجام شد! تعداد ${data.cancelled_count} اکشن فعال لغو شد و ${data.deleted_count} اکشن متوقف شده با موفقیت حذف گردید.`, true);
updateStats();
document.getElementById('displayContainer').classList.add('hidden');
} else {
showAlert('خطایی در انجام فرآیند لغو و حذف رخ داد.', false);
}
} catch (e) {
showAlert('خطای ارتباط با سرور بک‌اند!', false);
}
}
</script>
</body>
</html>