Ezmary commited on
Commit
f260174
·
verified ·
1 Parent(s): 864df03

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +114 -78
templates/index.html CHANGED
@@ -182,7 +182,7 @@
182
  gap: 8px;
183
  align-items: center;
184
  margin-top: 10px;
185
- justify-content: flex-end;
186
  border-top: 1px solid #f1f5f9;
187
  padding-top: 10px;
188
  }
@@ -199,11 +199,6 @@
199
  }
200
  .btn-action-view:hover { background: #3182ce; color: white; }
201
 
202
- /* استایل سیستم حذف */
203
- .delete-wrapper {
204
- display: flex;
205
- align-items: center;
206
- }
207
  .btn-trash {
208
  background: #fff5f5;
209
  color: #e53e3e;
@@ -214,22 +209,6 @@
214
  }
215
  .btn-trash:hover { background: #e53e3e; color: white; border-color: #e53e3e; }
216
 
217
- .confirm-box {
218
- display: flex;
219
- gap: 5px;
220
- animation: slideInLeft 0.3s ease;
221
- }
222
- @keyframes slideInLeft {
223
- from { opacity: 0; transform: translateX(-10px); }
224
- to { opacity: 1; transform: translateX(0); }
225
- }
226
- .btn-yes {
227
- background: #e53e3e; color: white; border: none; padding: 5px 12px; border-radius: 6px; font-size: 0.8rem;
228
- }
229
- .btn-no {
230
- background: #edf2f7; color: #4a5568; border: none; padding: 5px 12px; border-radius: 6px; font-size: 0.8rem;
231
- }
232
-
233
  .subtitle-desc {
234
  color: #718096;
235
  font-size: 0.95rem;
@@ -239,11 +218,80 @@
239
  }
240
 
241
  .badge-status { font-size: 0.75rem; padding: 4px 10px; border-radius: 20px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
 
 
 
 
 
 
 
 
 
 
 
243
  </style>
244
  </head>
245
  <body>
246
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  <div class="container py-5">
248
  <!-- هدر و توضیحات -->
249
  <div class="text-center mb-4">
@@ -333,7 +381,7 @@
333
  <div class="main-card h-100 history-card">
334
  <div class="d-flex justify-content-between align-items-center mb-4">
335
  <h5 class="fw-bold mb-0"><i class="fas fa-history text-secondary me-2"></i>سوابق درخواست‌ها</h5>
336
- <button onclick="clearHistory()" class="btn btn-sm text-secondary" title="پاکسازی کل"><i class="fas fa-trash-alt"></i></button>
337
  </div>
338
 
339
  <div id="historyList">
@@ -350,6 +398,9 @@
350
  const CIRCUMFERENCE = 2 * Math.PI * 35;
351
  let timerInterval = null;
352
  let pollingInterval = null;
 
 
 
353
 
354
  // --- UI Helpers ---
355
  function fileSelect(input, textId, zoneId) {
@@ -382,19 +433,44 @@
382
  }
383
  }
384
 
385
- function removeJob(id) {
386
- const jobs = getJobs();
387
- delete jobs[id];
388
- localStorage.setItem('sada_jobs_v2', JSON.stringify(jobs));
389
- renderHistory();
 
 
 
 
 
 
 
 
 
390
  }
391
 
392
- function clearHistory() {
393
- if(confirm('آیا مطمئن هستید تمام سوابق پاک شوند؟')) {
 
 
 
394
  localStorage.removeItem('sada_jobs_v2');
395
- renderHistory();
 
 
 
 
 
 
 
 
 
 
396
  }
397
- }
 
 
 
398
 
399
  // --- رندر لیست تاریخچه ---
400
  function renderHistory() {
@@ -447,78 +523,43 @@
447
  </div>
448
 
449
  <div class="action-btn-group">
450
- ${actionButtons}
451
-
452
- <!-- سیستم حذف -->
453
- <div class="delete-wrapper" id="del-wrap-${job.job_id}">
454
- <button onclick="askDelete('${job.job_id}')" class="btn-trash" title="حذف">
455
- <i class="fas fa-trash"></i>
456
- </button>
457
- </div>
458
- <div class="confirm-box" id="confirm-wrap-${job.job_id}" style="display:none">
459
- <button onclick="doDelete('${job.job_id}')" class="btn-yes">تایید</button>
460
- <button onclick="cancelDelete('${job.job_id}')" class="btn-no">انصراف</button>
461
- </div>
462
  </div>
463
  `;
464
  list.appendChild(el);
465
  });
466
  }
467
 
468
- // --- لاجیک حذف ---
469
- function askDelete(id) {
470
- document.getElementById(`del-wrap-${id}`).style.display = 'none';
471
- document.getElementById(`confirm-wrap-${id}`).style.display = 'flex';
472
- }
473
-
474
- function cancelDelete(id) {
475
- document.getElementById(`confirm-wrap-${id}`).style.display = 'none';
476
- document.getElementById(`del-wrap-${id}`).style.display = 'flex';
477
- }
478
-
479
- function doDelete(id) {
480
- // اگر فایلی که در حال پخش است حذف شود، پلیر ریست شود
481
- const currentTracking = document.getElementById('audioPlayer').getAttribute('data-job-id');
482
- if (currentTracking === id) {
483
- document.getElementById('livePanel').style.display = 'none';
484
- document.getElementById('uploadForm').reset();
485
- }
486
- removeJob(id);
487
- }
488
-
489
  // --- مشاهده و پخش (لود کردن در پنل بالا) ---
490
  function playJob(id) {
491
  const jobs = getJobs();
492
  const job = jobs[id];
493
  if (!job || !job.filename) return alert("فایل پیدا نشد");
494
 
495
- // اسکرول به بالا
496
  window.scrollTo({ top: 0, behavior: 'smooth' });
497
 
498
- // نمایش پنل
499
  const panel = document.getElementById('livePanel');
500
  panel.style.display = 'block';
501
 
502
- // تنظیم وضعیت به "تکمیل شده"
503
  document.getElementById('statusTitle').innerText = 'مشاهده جزئیات';
504
  document.getElementById('statusDesc').innerText = 'فایل صوتی آماده پخش است';
505
  document.getElementById('progressBar').style.width = '100%';
506
  document.getElementById('progressText').innerText = '100%';
507
  document.getElementById('resultBox').style.display = 'block';
508
 
509
- // دا��ره کامل
510
  const circle = document.getElementById('timerCircle');
511
  circle.style.strokeDasharray = CIRCUMFERENCE;
512
  circle.style.strokeDashoffset = 0;
513
 
514
- // تنظیم پلیر
515
  const uniqueUrl = `/download/${job.filename}?t=${new Date().getTime()}`;
516
  const player = document.getElementById('audioPlayer');
517
  player.src = uniqueUrl;
518
- player.setAttribute('data-job-id', id); // برای شناسایی
519
  player.load();
520
 
521
- // تنظیم دکمه دانلود
522
  document.getElementById('downloadBtn').href = uniqueUrl;
523
  }
524
 
@@ -561,12 +602,10 @@
561
  const req = await fetch('/upload', { method: 'POST', body: fd });
562
  const res = await req.json();
563
 
564
- // ذخیره
565
  res.date = new Date().toLocaleString('fa-IR');
566
  res.progress = 0;
567
  saveJob(res);
568
 
569
- // ریست فرم
570
  document.getElementById('uploadForm').reset();
571
  document.getElementById('srcText').innerText = 'انتخاب فایل...';
572
  document.getElementById('refText').innerText = 'انتخاب فایل...';
@@ -576,7 +615,6 @@
576
  btn.innerHTML = 'شروع پردازش هوشمند';
577
  btn.disabled = false;
578
 
579
- // شروع پیگیری
580
  trackJob(res.job_id);
581
 
582
  } catch (err) {
@@ -594,7 +632,6 @@
594
 
595
  window.scrollTo({ top: 0, behavior: 'smooth' });
596
 
597
- // نمایش پنل زنده
598
  document.getElementById('livePanel').style.display = 'block';
599
  document.getElementById('resultBox').style.display = 'none';
600
  document.getElementById('statusTitle').innerText = 'در حال پردازش...';
@@ -639,7 +676,7 @@
639
  clearInterval(pollingInterval);
640
  clearInterval(timerInterval);
641
  document.getElementById('statusTitle').innerText = 'خطا در پردازش';
642
- document.getElementById('statusDesc').innerText = 'لطفاً مجدد تلاش کنید یا فایل دیگری تست کنید';
643
  document.getElementById('progressBar').classList.add('bg-danger');
644
  }
645
 
@@ -650,7 +687,6 @@
650
  pollingInterval = setInterval(check, 4000);
651
  }
652
 
653
- // رندر اولیه
654
  renderHistory();
655
  </script>
656
 
 
182
  gap: 8px;
183
  align-items: center;
184
  margin-top: 10px;
185
+ justify-content: space-between; /* پخش شده در عرض */
186
  border-top: 1px solid #f1f5f9;
187
  padding-top: 10px;
188
  }
 
199
  }
200
  .btn-action-view:hover { background: #3182ce; color: white; }
201
 
 
 
 
 
 
202
  .btn-trash {
203
  background: #fff5f5;
204
  color: #e53e3e;
 
209
  }
210
  .btn-trash:hover { background: #e53e3e; color: white; border-color: #e53e3e; }
211
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  .subtitle-desc {
213
  color: #718096;
214
  font-size: 0.95rem;
 
218
  }
219
 
220
  .badge-status { font-size: 0.75rem; padding: 4px 10px; border-radius: 20px; }
221
+
222
+ /* --- استایل مودال سفارشی (وسط صفحه) --- */
223
+ .custom-modal-overlay {
224
+ position: fixed;
225
+ top: 0; left: 0; width: 100%; height: 100%;
226
+ background: rgba(0, 0, 0, 0.5);
227
+ backdrop-filter: blur(5px);
228
+ z-index: 9999;
229
+ display: none; /* پیش‌فرض مخفی */
230
+ justify-content: center;
231
+ align-items: center;
232
+ padding: 20px;
233
+ }
234
+
235
+ .custom-modal-box {
236
+ background: white;
237
+ border-radius: 24px;
238
+ padding: 30px;
239
+ width: 100%;
240
+ max-width: 400px;
241
+ text-align: center;
242
+ box-shadow: 0 20px 60px rgba(0,0,0,0.2);
243
+ animation: popIn 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
244
+ }
245
+
246
+ @keyframes popIn {
247
+ from { opacity: 0; transform: scale(0.8); }
248
+ to { opacity: 1; transform: scale(1); }
249
+ }
250
+
251
+ .modal-icon-danger {
252
+ width: 70px; height: 70px;
253
+ background: #fff5f5;
254
+ color: #e53e3e;
255
+ border-radius: 50%;
256
+ display: flex; align-items: center; justify-content: center;
257
+ font-size: 2rem;
258
+ margin: 0 auto 15px;
259
+ }
260
+
261
+ .modal-btns {
262
+ display: flex; gap: 10px; justify-content: center; margin-top: 25px;
263
+ }
264
 
265
+ .btn-modal-yes {
266
+ background: #e53e3e; color: white; border: none; padding: 10px 25px; border-radius: 12px; font-weight: bold; width: 100px; transition: 0.2s;
267
+ }
268
+ .btn-modal-yes:hover { background: #c53030; transform: translateY(-2px); }
269
+
270
+ .btn-modal-no {
271
+ background: #edf2f7; color: #4a5568; border: none; padding: 10px 25px; border-radius: 12px; font-weight: bold; width: 100px; transition: 0.2s;
272
+ }
273
+ .btn-modal-no:hover { background: #e2e8f0; color: #2d3748; }
274
+
275
  </style>
276
  </head>
277
  <body>
278
 
279
+ <!-- مودال حذف سفارشی -->
280
+ <div id="deleteModal" class="custom-modal-overlay">
281
+ <div class="custom-modal-box">
282
+ <div class="modal-icon-danger">
283
+ <i class="fas fa-trash-alt"></i>
284
+ </div>
285
+ <h5 class="fw-bold mb-2">تایید حذف</h5>
286
+ <p class="text-muted mb-0" id="deleteModalMsg">آیا از حذف این مورد اطمینان دارید؟</p>
287
+
288
+ <div class="modal-btns">
289
+ <button class="btn-modal-no" onclick="closeDeleteModal()">انصراف</button>
290
+ <button class="btn-modal-yes" id="confirmDeleteBtn">تایید</button>
291
+ </div>
292
+ </div>
293
+ </div>
294
+
295
  <div class="container py-5">
296
  <!-- هدر و توضیحات -->
297
  <div class="text-center mb-4">
 
381
  <div class="main-card h-100 history-card">
382
  <div class="d-flex justify-content-between align-items-center mb-4">
383
  <h5 class="fw-bold mb-0"><i class="fas fa-history text-secondary me-2"></i>سوابق درخواست‌ها</h5>
384
+ <button onclick="openDeleteModal('ALL')" class="btn btn-sm text-secondary" title="پاکسازی کل"><i class="fas fa-trash-alt"></i></button>
385
  </div>
386
 
387
  <div id="historyList">
 
398
  const CIRCUMFERENCE = 2 * Math.PI * 35;
399
  let timerInterval = null;
400
  let pollingInterval = null;
401
+
402
+ // متغیر برای نگهداری شناسه آیتمی که قرار است حذف شود
403
+ let itemToDelete = null;
404
 
405
  // --- UI Helpers ---
406
  function fileSelect(input, textId, zoneId) {
 
433
  }
434
  }
435
 
436
+ // --- سیستم حذف (تکی و کلی) ---
437
+ function openDeleteModal(id) {
438
+ itemToDelete = id;
439
+ const msg = (id === 'ALL')
440
+ ? 'آیا مطمئن هستید که می‌خواهید کل تاریخچه را پاک کنید؟'
441
+ : 'آیا از حذف این فایل صوتی اطمینان دارید؟';
442
+
443
+ document.getElementById('deleteModalMsg').innerText = msg;
444
+ document.getElementById('deleteModal').style.display = 'flex';
445
+ }
446
+
447
+ function closeDeleteModal() {
448
+ document.getElementById('deleteModal').style.display = 'none';
449
+ itemToDelete = null;
450
  }
451
 
452
+ // اتصال دکمه تایید مودال به تابع انجام حذف
453
+ document.getElementById('confirmDeleteBtn').addEventListener('click', () => {
454
+ if (!itemToDelete) return;
455
+
456
+ if (itemToDelete === 'ALL') {
457
  localStorage.removeItem('sada_jobs_v2');
458
+ } else {
459
+ const jobs = getJobs();
460
+ delete jobs[itemToDelete];
461
+ localStorage.setItem('sada_jobs_v2', JSON.stringify(jobs));
462
+
463
+ // اگر فایلی که در حال پخش است حذف شود، پلیر ریست شود
464
+ const currentTracking = document.getElementById('audioPlayer').getAttribute('data-job-id');
465
+ if (currentTracking === itemToDelete) {
466
+ document.getElementById('livePanel').style.display = 'none';
467
+ document.getElementById('uploadForm').reset();
468
+ }
469
  }
470
+
471
+ renderHistory();
472
+ closeDeleteModal();
473
+ });
474
 
475
  // --- رندر لیست تاریخچه ---
476
  function renderHistory() {
 
523
  </div>
524
 
525
  <div class="action-btn-group">
526
+ <div>${actionButtons}</div>
527
+ <button onclick="openDeleteModal('${job.job_id}')" class="btn-trash" title="حذف">
528
+ <i class="fas fa-trash"></i>
529
+ </button>
 
 
 
 
 
 
 
 
530
  </div>
531
  `;
532
  list.appendChild(el);
533
  });
534
  }
535
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
536
  // --- مشاهده و پخش (لود کردن در پنل بالا) ---
537
  function playJob(id) {
538
  const jobs = getJobs();
539
  const job = jobs[id];
540
  if (!job || !job.filename) return alert("فایل پیدا نشد");
541
 
 
542
  window.scrollTo({ top: 0, behavior: 'smooth' });
543
 
 
544
  const panel = document.getElementById('livePanel');
545
  panel.style.display = 'block';
546
 
 
547
  document.getElementById('statusTitle').innerText = 'مشاهده جزئیات';
548
  document.getElementById('statusDesc').innerText = 'فایل صوتی آماده پخش است';
549
  document.getElementById('progressBar').style.width = '100%';
550
  document.getElementById('progressText').innerText = '100%';
551
  document.getElementById('resultBox').style.display = 'block';
552
 
 
553
  const circle = document.getElementById('timerCircle');
554
  circle.style.strokeDasharray = CIRCUMFERENCE;
555
  circle.style.strokeDashoffset = 0;
556
 
 
557
  const uniqueUrl = `/download/${job.filename}?t=${new Date().getTime()}`;
558
  const player = document.getElementById('audioPlayer');
559
  player.src = uniqueUrl;
560
+ player.setAttribute('data-job-id', id);
561
  player.load();
562
 
 
563
  document.getElementById('downloadBtn').href = uniqueUrl;
564
  }
565
 
 
602
  const req = await fetch('/upload', { method: 'POST', body: fd });
603
  const res = await req.json();
604
 
 
605
  res.date = new Date().toLocaleString('fa-IR');
606
  res.progress = 0;
607
  saveJob(res);
608
 
 
609
  document.getElementById('uploadForm').reset();
610
  document.getElementById('srcText').innerText = 'انتخاب فایل...';
611
  document.getElementById('refText').innerText = 'انتخاب فایل...';
 
615
  btn.innerHTML = 'شروع پردازش هوشمند';
616
  btn.disabled = false;
617
 
 
618
  trackJob(res.job_id);
619
 
620
  } catch (err) {
 
632
 
633
  window.scrollTo({ top: 0, behavior: 'smooth' });
634
 
 
635
  document.getElementById('livePanel').style.display = 'block';
636
  document.getElementById('resultBox').style.display = 'none';
637
  document.getElementById('statusTitle').innerText = 'در حال پردازش...';
 
676
  clearInterval(pollingInterval);
677
  clearInterval(timerInterval);
678
  document.getElementById('statusTitle').innerText = 'خطا در پردازش';
679
+ document.getElementById('statusDesc').innerText = 'لطفاً مجدد تلاش کنید';
680
  document.getElementById('progressBar').classList.add('bg-danger');
681
  }
682
 
 
687
  pollingInterval = setInterval(check, 4000);
688
  }
689
 
 
690
  renderHistory();
691
  </script>
692