samfred2 commited on
Commit
3dc3878
·
verified ·
1 Parent(s): e01001b

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +105 -65
templates/index.html CHANGED
@@ -3,89 +3,129 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Movie Downloader & Uploader</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
 
 
 
 
 
 
 
 
 
 
 
 
8
  </head>
9
- <body class="bg-gray-100 min-h-screen flex items-center justify-center">
10
- <div class="bg-white p-8 rounded-lg shadow-md w-full max-w-md">
11
- <h1 class="text-2xl font-bold mb-6 text-center text-blue-600">Movie Transfer Tool</h1>
12
- <form id="downloadForm" class="space-y-4">
13
- <div>
14
- <label for="url" class="block text-sm font-medium text-gray-700">DownloadWella URL</label>
15
- <input type="url" id="url" name="url" required
16
- class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
17
- placeholder="https://downloadwella.com/...">
18
- </div>
19
- <button type="submit" id="submitBtn"
20
- class="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500">
21
- Start Process
22
- </button>
23
  </form>
24
- <div id="status" class="mt-6 hidden">
25
- <h2 class="text-sm font-semibold text-gray-600 uppercase tracking-wider">Status</h2>
26
- <div id="statusList" class="mt-2 text-sm text-gray-500 space-y-1">
27
- <!-- Status messages will appear here -->
 
 
 
 
 
 
 
 
28
  </div>
29
  </div>
30
  </div>
31
 
32
  <script>
33
- const form = document.getElementById('downloadForm');
34
- const statusDiv = document.getElementById('status');
35
- const statusList = document.getElementById('statusList');
36
- const submitBtn = document.getElementById('submitBtn');
 
 
 
37
 
38
- function addStatus(message, isError = false) {
39
- const p = document.createElement('p');
40
- p.textContent = message;
41
- if (isError) p.classList.add('text-red-500', 'font-bold');
42
- statusList.appendChild(p);
43
- statusDiv.classList.remove('hidden');
44
- }
45
 
46
- form.onsubmit = async (e) => {
47
- e.preventDefault();
48
- const url = document.getElementById('url').value;
49
-
50
- submitBtn.disabled = true;
51
- submitBtn.classList.add('opacity-50', 'cursor-not-allowed');
52
- statusList.innerHTML = '';
53
- addStatus('Initiating process...');
54
 
55
  try {
56
- const response = await fetch('/process', {
57
  method: 'POST',
58
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
59
- body: new URLSearchParams({ 'url': url })
60
  });
 
 
 
 
 
 
 
 
 
 
61
 
62
- const reader = response.body.getReader();
63
- const decoder = new TextDecoder();
64
-
65
- while (true) {
66
- const { value, done } = await reader.read();
67
- if (done) break;
68
-
69
- const text = decoder.decode(value);
70
- const lines = text.split('\n');
71
- for (const line of lines) {
72
- if (line.trim()) {
73
- try {
74
- const data = JSON.parse(line);
75
- addStatus(data.message, data.error);
76
- } catch (e) {
77
- // Not JSON, skip
78
- }
79
- }
80
- }
81
  }
 
 
82
  } catch (error) {
83
- addStatus('Network error: ' + error.message, true);
84
- } finally {
85
- submitBtn.disabled = false;
86
- submitBtn.classList.remove('opacity-50', 'cursor-not-allowed');
87
  }
88
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  </script>
90
  </body>
91
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Downloadwella to Hugging Face Frame Extractor</title>
7
+ <style>
8
+ body { font-family: sans-serif; margin: 20px; background-color: #f4f4f4; color: #333; }
9
+ .container { max-width: 800px; margin: auto; background: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
10
+ h1 { color: #0056b3; }
11
+ form { margin-top: 20px; display: flex; flex-direction: column; gap: 10px; }
12
+ input[type="text"] { padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 16px; }
13
+ button { padding: 10px 15px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; }
14
+ button:hover { background-color: #0056b3; }
15
+ .status-box { background-color: #e9ecef; border: 1px solid #ced4da; padding: 15px; border-radius: 4px; margin-top: 20px; }
16
+ .log-entry { margin-bottom: 5px; border-bottom: 1px dotted #ccc; padding-bottom: 3px; }
17
+ .error { color: red; font-weight: bold; }
18
+ .success { color: green; font-weight: bold; }
19
+ </style>
20
  </head>
21
+ <body>
22
+ <div class="container">
23
+ <h1>Downloadwella to Hugging Face Frame Extractor</h1>
24
+ <p>Enter a Downloadwella URL to download the video, extract frames, and upload them as a zip to Hugging Face.</p>
25
+
26
+ <form id="processForm">
27
+ <input type="text" id="videoUrl" name="video_url" placeholder="Enter Downloadwella URL (e.g., https://downloadwella.com/some-video-id)" required>
28
+ <button type="submit">Start Processing</button>
 
 
 
 
 
 
29
  </form>
30
+
31
+ <div class="status-box">
32
+ <h2>Processing Status</h2>
33
+ <p><strong>Is Running:</strong> <span id="isRunning">{{ status.is_running }}</span></p>
34
+ <p><strong>Current Action:</strong> <span id="currentAction">{{ status.current_action }}</span></p>
35
+ <p><strong>Last Processed URL:</strong> <span id="lastProcessedUrl">{{ status.last_processed_url if status.last_processed_url else 'N/A' }}</span></p>
36
+ <p><strong>Processed Count:</strong> <span id="processedCount">{{ status.processed_count }}</span></p>
37
+ <h3>Logs:</h3>
38
+ <div id="logs" style="max-height: 300px; overflow-y: scroll; background-color: #fff; padding: 10px; border-radius: 4px;">
39
+ {% for log in status.logs %}
40
+ <div class="log-entry">{{ log }}</div>
41
+ {% endfor %}
42
  </div>
43
  </div>
44
  </div>
45
 
46
  <script>
47
+ const processForm = document.getElementById('processForm');
48
+ const videoUrlInput = document.getElementById('videoUrl');
49
+ const isRunningSpan = document.getElementById('isRunning');
50
+ const currentActionSpan = document.getElementById('currentAction');
51
+ const lastProcessedUrlSpan = document.getElementById('lastProcessedUrl');
52
+ const processedCountSpan = document.getElementById('processedCount');
53
+ const logsDiv = document.getElementById('logs');
54
 
55
+ processForm.addEventListener('submit', async (event) => {
56
+ event.preventDefault();
57
+ const videoUrl = videoUrlInput.value;
58
+ if (!videoUrl) return;
 
 
 
59
 
60
+ logsDiv.innerHTML = ''; // Clear previous logs
61
+ addLog('Initiating processing...');
 
 
 
 
 
 
62
 
63
  try {
64
+ const response = await fetch('/start', {
65
  method: 'POST',
66
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
67
+ body: `video_url=${encodeURIComponent(videoUrl)}`
68
  });
69
+ const data = await response.json();
70
+ addLog(data.message);
71
+ if (data.message === "Processor started") {
72
+ // Start polling for status updates
73
+ pollStatus();
74
+ }
75
+ } catch (error) {
76
+ addLog(`Error starting process: ${error}`, true);
77
+ }
78
+ });
79
 
80
+ async function fetchStatus() {
81
+ try {
82
+ const response = await fetch('/stats');
83
+ const status = await response.json();
84
+ isRunningSpan.textContent = status.is_running;
85
+ currentActionSpan.textContent = status.current_action;
86
+ lastProcessedUrlSpan.textContent = status.last_processed_url || 'N/A';
87
+ processedCountSpan.textContent = status.processed_count;
88
+
89
+ // Only update logs if there are new entries or status changed
90
+ if (status.logs.length !== logsDiv.children.length) {
91
+ logsDiv.innerHTML = '';
92
+ status.logs.forEach(log => addLog(log));
 
 
 
 
 
 
93
  }
94
+
95
+ return status.is_running;
96
  } catch (error) {
97
+ addLog(`Error fetching status: ${error}`, true);
98
+ return false;
 
 
99
  }
100
+ }
101
+
102
+ function addLog(message, isError = false) {
103
+ const logEntry = document.createElement('div');
104
+ logEntry.classList.add('log-entry');
105
+ if (isError) {
106
+ logEntry.classList.add('error');
107
+ }
108
+ logEntry.textContent = message;
109
+ logsDiv.appendChild(logEntry);
110
+ logsDiv.scrollTop = logsDiv.scrollHeight; // Auto-scroll to bottom
111
+ }
112
+
113
+ let pollingInterval;
114
+ function pollStatus() {
115
+ if (pollingInterval) clearInterval(pollingInterval);
116
+ pollingInterval = setInterval(async () => {
117
+ const running = await fetchStatus();
118
+ if (!running && currentActionSpan.textContent !== "Idle" && currentActionSpan.textContent !== "Error") {
119
+ addLog("Processing finished or stopped.");
120
+ clearInterval(pollingInterval);
121
+ }
122
+ }, 3000); // Poll every 3 seconds
123
+ }
124
+
125
+ // Initial status fetch on page load
126
+ fetchStatus();
127
+ pollStatus(); // Start polling immediately
128
+
129
  </script>
130
  </body>
131
  </html>