Fred808 commited on
Commit
45d270d
·
verified ·
1 Parent(s): b2dbfc2

Upload 6 files

Browse files
static/css/readme ADDED
File without changes
static/css/style.css ADDED
@@ -0,0 +1,378 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Reset and base styles */
2
+ * {
3
+ margin: 0;
4
+ padding: 0;
5
+ box-sizing: border-box;
6
+ }
7
+
8
+ body {
9
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
10
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
11
+ min-height: 100vh;
12
+ color: #333;
13
+ line-height: 1.6;
14
+ }
15
+
16
+ .container {
17
+ max-width: 1200px;
18
+ margin: 0 auto;
19
+ padding: 20px;
20
+ min-height: 100vh;
21
+ display: flex;
22
+ flex-direction: column;
23
+ }
24
+
25
+ /* Header styles */
26
+ .header {
27
+ text-align: center;
28
+ margin-bottom: 40px;
29
+ padding: 40px 0;
30
+ }
31
+
32
+ .header-content {
33
+ background: rgba(255, 255, 255, 0.1);
34
+ backdrop-filter: blur(10px);
35
+ border-radius: 20px;
36
+ padding: 40px;
37
+ border: 1px solid rgba(255, 255, 255, 0.2);
38
+ }
39
+
40
+ .logo {
41
+ display: flex;
42
+ align-items: center;
43
+ justify-content: center;
44
+ gap: 15px;
45
+ margin-bottom: 15px;
46
+ }
47
+
48
+ .logo i {
49
+ font-size: 2.5rem;
50
+ color: #fff;
51
+ background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
52
+ -webkit-background-clip: text;
53
+ -webkit-text-fill-color: transparent;
54
+ background-clip: text;
55
+ }
56
+
57
+ .logo h1 {
58
+ font-size: 2.5rem;
59
+ font-weight: 700;
60
+ color: #fff;
61
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
62
+ }
63
+
64
+ .subtitle {
65
+ font-size: 1.1rem;
66
+ color: rgba(255, 255, 255, 0.9);
67
+ font-weight: 400;
68
+ }
69
+
70
+ /* Main content */
71
+ .main-content {
72
+ flex: 1;
73
+ display: flex;
74
+ justify-content: center;
75
+ align-items: flex-start;
76
+ }
77
+
78
+ .upload-card {
79
+ background: #fff;
80
+ border-radius: 20px;
81
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
82
+ padding: 40px;
83
+ width: 100%;
84
+ max-width: 600px;
85
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
86
+ }
87
+
88
+ .upload-card:hover {
89
+ transform: translateY(-5px);
90
+ box-shadow: 0 25px 50px rgba(0, 0, 0, 0.15);
91
+ }
92
+
93
+ .card-header {
94
+ text-align: center;
95
+ margin-bottom: 30px;
96
+ }
97
+
98
+ .card-header h2 {
99
+ font-size: 1.8rem;
100
+ font-weight: 600;
101
+ color: #2d3748;
102
+ margin-bottom: 10px;
103
+ display: flex;
104
+ align-items: center;
105
+ justify-content: center;
106
+ gap: 10px;
107
+ }
108
+
109
+ .card-header h2 i {
110
+ color: #667eea;
111
+ }
112
+
113
+ .card-header p {
114
+ color: #718096;
115
+ font-size: 1rem;
116
+ }
117
+
118
+ /* Form styles */
119
+ .upload-form {
120
+ margin-bottom: 30px;
121
+ }
122
+
123
+ .input-group {
124
+ margin-bottom: 25px;
125
+ }
126
+
127
+ .input-group label {
128
+ display: block;
129
+ font-weight: 500;
130
+ color: #2d3748;
131
+ margin-bottom: 8px;
132
+ font-size: 0.95rem;
133
+ }
134
+
135
+ .input-group textarea {
136
+ width: 100%;
137
+ padding: 15px;
138
+ border: 2px solid #e2e8f0;
139
+ border-radius: 12px;
140
+ font-size: 1rem;
141
+ font-family: inherit;
142
+ resize: vertical;
143
+ transition: border-color 0.3s ease, box-shadow 0.3s ease;
144
+ background: #f7fafc;
145
+ }
146
+
147
+ .input-group textarea:focus {
148
+ outline: none;
149
+ border-color: #667eea;
150
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
151
+ background: #fff;
152
+ }
153
+
154
+ .input-hint {
155
+ margin-top: 8px;
156
+ font-size: 0.85rem;
157
+ color: #718096;
158
+ display: flex;
159
+ align-items: center;
160
+ gap: 5px;
161
+ }
162
+
163
+ .input-hint i {
164
+ color: #667eea;
165
+ }
166
+
167
+ /* Button styles */
168
+ .upload-btn {
169
+ width: 100%;
170
+ padding: 15px 30px;
171
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
172
+ color: #fff;
173
+ border: none;
174
+ border-radius: 12px;
175
+ font-size: 1.1rem;
176
+ font-weight: 600;
177
+ cursor: pointer;
178
+ transition: all 0.3s ease;
179
+ position: relative;
180
+ overflow: hidden;
181
+ }
182
+
183
+ .upload-btn:hover {
184
+ transform: translateY(-2px);
185
+ box-shadow: 0 10px 25px rgba(102, 126, 234, 0.3);
186
+ }
187
+
188
+ .upload-btn:active {
189
+ transform: translateY(0);
190
+ }
191
+
192
+ .upload-btn:disabled {
193
+ opacity: 0.7;
194
+ cursor: not-allowed;
195
+ transform: none;
196
+ }
197
+
198
+ .btn-text {
199
+ display: flex;
200
+ align-items: center;
201
+ justify-content: center;
202
+ gap: 10px;
203
+ }
204
+
205
+ .loading-spinner {
206
+ display: flex;
207
+ align-items: center;
208
+ justify-content: center;
209
+ gap: 10px;
210
+ }
211
+
212
+ /* Results section */
213
+ .results-section {
214
+ margin-top: 30px;
215
+ padding-top: 30px;
216
+ border-top: 2px solid #e2e8f0;
217
+ }
218
+
219
+ .results-header {
220
+ display: flex;
221
+ justify-content: space-between;
222
+ align-items: center;
223
+ margin-bottom: 20px;
224
+ }
225
+
226
+ .results-header h3 {
227
+ font-size: 1.3rem;
228
+ font-weight: 600;
229
+ color: #2d3748;
230
+ display: flex;
231
+ align-items: center;
232
+ gap: 10px;
233
+ }
234
+
235
+ .results-header h3 i {
236
+ color: #667eea;
237
+ }
238
+
239
+ .clear-btn {
240
+ padding: 8px 16px;
241
+ background: #e53e3e;
242
+ color: #fff;
243
+ border: none;
244
+ border-radius: 8px;
245
+ font-size: 0.9rem;
246
+ cursor: pointer;
247
+ transition: background 0.3s ease;
248
+ display: flex;
249
+ align-items: center;
250
+ gap: 5px;
251
+ }
252
+
253
+ .clear-btn:hover {
254
+ background: #c53030;
255
+ }
256
+
257
+ .results-content {
258
+ background: #f7fafc;
259
+ border: 2px solid #e2e8f0;
260
+ border-radius: 12px;
261
+ padding: 20px;
262
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
263
+ font-size: 0.9rem;
264
+ line-height: 1.6;
265
+ white-space: pre-wrap;
266
+ max-height: 400px;
267
+ overflow-y: auto;
268
+ }
269
+
270
+ .results-content:empty::before {
271
+ content: "No results yet...";
272
+ color: #a0aec0;
273
+ font-style: italic;
274
+ }
275
+
276
+ /* Result status styling */
277
+ .results-content .success {
278
+ color: #38a169;
279
+ }
280
+
281
+ .results-content .error {
282
+ color: #e53e3e;
283
+ }
284
+
285
+ .results-content .warning {
286
+ color: #d69e2e;
287
+ }
288
+
289
+ /* Footer */
290
+ .footer {
291
+ text-align: center;
292
+ padding: 20px 0;
293
+ margin-top: 40px;
294
+ color: rgba(255, 255, 255, 0.8);
295
+ font-size: 0.9rem;
296
+ }
297
+
298
+ /* Responsive design */
299
+ @media (max-width: 768px) {
300
+ .container {
301
+ padding: 15px;
302
+ }
303
+
304
+ .header-content {
305
+ padding: 30px 20px;
306
+ }
307
+
308
+ .logo h1 {
309
+ font-size: 2rem;
310
+ }
311
+
312
+ .upload-card {
313
+ padding: 30px 20px;
314
+ }
315
+
316
+ .results-header {
317
+ flex-direction: column;
318
+ gap: 15px;
319
+ align-items: stretch;
320
+ }
321
+
322
+ .clear-btn {
323
+ align-self: flex-end;
324
+ }
325
+ }
326
+
327
+ @media (max-width: 480px) {
328
+ .logo {
329
+ flex-direction: column;
330
+ gap: 10px;
331
+ }
332
+
333
+ .logo h1 {
334
+ font-size: 1.8rem;
335
+ }
336
+
337
+ .card-header h2 {
338
+ font-size: 1.5rem;
339
+ flex-direction: column;
340
+ gap: 5px;
341
+ }
342
+ }
343
+
344
+ /* Animation for results appearing */
345
+ @keyframes fadeInUp {
346
+ from {
347
+ opacity: 0;
348
+ transform: translateY(20px);
349
+ }
350
+ to {
351
+ opacity: 1;
352
+ transform: translateY(0);
353
+ }
354
+ }
355
+
356
+ .results-section {
357
+ animation: fadeInUp 0.5s ease;
358
+ }
359
+
360
+ /* Custom scrollbar for results */
361
+ .results-content::-webkit-scrollbar {
362
+ width: 8px;
363
+ }
364
+
365
+ .results-content::-webkit-scrollbar-track {
366
+ background: #e2e8f0;
367
+ border-radius: 4px;
368
+ }
369
+
370
+ .results-content::-webkit-scrollbar-thumb {
371
+ background: #cbd5e0;
372
+ border-radius: 4px;
373
+ }
374
+
375
+ .results-content::-webkit-scrollbar-thumb:hover {
376
+ background: #a0aec0;
377
+ }
378
+
static/js/readme.md ADDED
File without changes
static/js/script.js ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ document.addEventListener('DOMContentLoaded', function() {
2
+ const uploadForm = document.getElementById('uploadForm');
3
+ const uploadBtn = document.getElementById('uploadBtn');
4
+ const btnText = uploadBtn.querySelector('.btn-text');
5
+ const loadingSpinner = uploadBtn.querySelector('.loading-spinner');
6
+ const resultsSection = document.getElementById('resultsSection');
7
+ const resultsContent = document.getElementById('resultsContent');
8
+ const clearBtn = document.getElementById('clearBtn');
9
+ const filenamesInput = document.getElementById('filenames');
10
+
11
+ // Form submission handler
12
+ uploadForm.addEventListener('submit', async function(e) {
13
+ e.preventDefault();
14
+
15
+ const filenames = filenamesInput.value.trim();
16
+ if (!filenames) {
17
+ alert('Please enter at least one filename');
18
+ return;
19
+ }
20
+
21
+ // Show loading state
22
+ setLoadingState(true);
23
+
24
+ try {
25
+ const formData = new FormData();
26
+ formData.append('filenames', filenames);
27
+
28
+ const response = await fetch('/upload', {
29
+ method: 'POST',
30
+ body: formData
31
+ });
32
+
33
+ if (!response.ok) {
34
+ throw new Error(`HTTP error! status: ${response.status}`);
35
+ }
36
+
37
+ const results = await response.text();
38
+ displayResults(results);
39
+
40
+ } catch (error) {
41
+ console.error('Upload error:', error);
42
+ displayResults(`❌ Error: ${error.message}`);
43
+ } finally {
44
+ setLoadingState(false);
45
+ }
46
+ });
47
+
48
+ // Clear results handler
49
+ clearBtn.addEventListener('click', function() {
50
+ resultsContent.textContent = '';
51
+ resultsSection.style.display = 'none';
52
+ });
53
+
54
+ // Auto-resize textarea
55
+ filenamesInput.addEventListener('input', function() {
56
+ this.style.height = 'auto';
57
+ this.style.height = Math.min(this.scrollHeight, 200) + 'px';
58
+ });
59
+
60
+ // Functions
61
+ function setLoadingState(isLoading) {
62
+ uploadBtn.disabled = isLoading;
63
+
64
+ if (isLoading) {
65
+ btnText.style.display = 'none';
66
+ loadingSpinner.style.display = 'flex';
67
+ } else {
68
+ btnText.style.display = 'flex';
69
+ loadingSpinner.style.display = 'none';
70
+ }
71
+ }
72
+
73
+ function displayResults(results) {
74
+ // Format results with proper styling
75
+ const formattedResults = formatResults(results);
76
+ resultsContent.innerHTML = formattedResults;
77
+ resultsSection.style.display = 'block';
78
+
79
+ // Scroll to results
80
+ resultsSection.scrollIntoView({
81
+ behavior: 'smooth',
82
+ block: 'start'
83
+ });
84
+ }
85
+
86
+ function formatResults(results) {
87
+ if (!results) return '<span class="error">No results received</span>';
88
+
89
+ return results.split('\n').map(line => {
90
+ line = line.trim();
91
+ if (!line) return '';
92
+
93
+ if (line.startsWith('✅')) {
94
+ return `<div class="success">${escapeHtml(line)}</div>`;
95
+ } else if (line.startsWith('❌')) {
96
+ return `<div class="error">${escapeHtml(line)}</div>`;
97
+ } else if (line.startsWith('⏩')) {
98
+ return `<div class="warning">${escapeHtml(line)}</div>`;
99
+ } else {
100
+ return `<div>${escapeHtml(line)}</div>`;
101
+ }
102
+ }).join('');
103
+ }
104
+
105
+ function escapeHtml(text) {
106
+ const div = document.createElement('div');
107
+ div.textContent = text;
108
+ return div.innerHTML;
109
+ }
110
+
111
+ // Add some interactive effects
112
+ const uploadCard = document.querySelector('.upload-card');
113
+
114
+ // Add subtle hover effect to form elements
115
+ const formElements = document.querySelectorAll('input, textarea, button');
116
+ formElements.forEach(element => {
117
+ element.addEventListener('focus', function() {
118
+ uploadCard.style.transform = 'translateY(-2px)';
119
+ });
120
+
121
+ element.addEventListener('blur', function() {
122
+ uploadCard.style.transform = 'translateY(-5px)';
123
+ });
124
+ });
125
+
126
+ // Add keyboard shortcuts
127
+ document.addEventListener('keydown', function(e) {
128
+ // Ctrl/Cmd + Enter to submit form
129
+ if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
130
+ e.preventDefault();
131
+ uploadForm.dispatchEvent(new Event('submit'));
132
+ }
133
+
134
+ // Escape to clear results
135
+ if (e.key === 'Escape' && resultsSection.style.display !== 'none') {
136
+ clearBtn.click();
137
+ }
138
+ });
139
+
140
+ // Add tooltip for keyboard shortcuts
141
+ const tooltip = document.createElement('div');
142
+ tooltip.innerHTML = `
143
+ <div style="position: fixed; bottom: 20px; right: 20px; background: rgba(0,0,0,0.8); color: white; padding: 10px; border-radius: 8px; font-size: 0.8rem; z-index: 1000;">
144
+ <div><kbd>Ctrl+Enter</kbd> Submit form</div>
145
+ <div><kbd>Esc</kbd> Clear results</div>
146
+ </div>
147
+ `;
148
+
149
+ // Show tooltip on first visit
150
+ setTimeout(() => {
151
+ document.body.appendChild(tooltip);
152
+ setTimeout(() => {
153
+ tooltip.style.opacity = '0';
154
+ tooltip.style.transition = 'opacity 0.5s';
155
+ setTimeout(() => tooltip.remove(), 500);
156
+ }, 3000);
157
+ }, 1000);
158
+ });
159
+
templates/index.html ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Hugging Face Uploader</title>
7
+ <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
8
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
10
+ </head>
11
+ <body>
12
+ <div class="container">
13
+ <header class="header">
14
+ <div class="header-content">
15
+ <div class="logo">
16
+ <i class="fas fa-cloud-upload-alt"></i>
17
+ <h1>Hugging Face Uploader</h1>
18
+ </div>
19
+ <p class="subtitle">Upload files from Telegram to Hugging Face datasets</p>
20
+ </div>
21
+ </header>
22
+
23
+ <main class="main-content">
24
+ <div class="upload-card">
25
+ <div class="card-header">
26
+ <h2><i class="fas fa-file-upload"></i> File Upload</h2>
27
+ <p>Enter filenames to search and upload from Telegram channel</p>
28
+ </div>
29
+
30
+ <form id="uploadForm" class="upload-form">
31
+ <div class="input-group">
32
+ <label for="filenames">Filenames (comma or newline separated)</label>
33
+ <textarea
34
+ id="filenames"
35
+ name="filenames"
36
+ placeholder="e.g.&#10;report.pdf&#10;summary.docx&#10;meeting_notes.txt"
37
+ rows="6"
38
+ required
39
+ ></textarea>
40
+ <div class="input-hint">
41
+ <i class="fas fa-info-circle"></i>
42
+ Separate multiple filenames with commas or new lines
43
+ </div>
44
+ </div>
45
+
46
+ <button type="submit" class="upload-btn" id="uploadBtn">
47
+ <span class="btn-text">
48
+ <i class="fas fa-upload"></i>
49
+ Start Upload
50
+ </span>
51
+ <div class="loading-spinner" style="display: none;">
52
+ <i class="fas fa-spinner fa-spin"></i>
53
+ Processing...
54
+ </div>
55
+ </button>
56
+ </form>
57
+
58
+ <div class="results-section" id="resultsSection" style="display: none;">
59
+ <div class="results-header">
60
+ <h3><i class="fas fa-list-check"></i> Upload Results</h3>
61
+ <button class="clear-btn" id="clearBtn">
62
+ <i class="fas fa-trash"></i>
63
+ Clear
64
+ </button>
65
+ </div>
66
+ <div class="results-content" id="resultsContent"></div>
67
+ </div>
68
+ </div>
69
+ </main>
70
+
71
+ <footer class="footer">
72
+ <p>&copy; 2024 Hugging Face Uploader. Built with Flask.</p>
73
+ </footer>
74
+ </div>
75
+
76
+ <script src="{{ url_for('static', filename='js/script.js') }}"></script>
77
+ </body>
78
+ </html>
79
+
templates/readme.md ADDED
@@ -0,0 +1 @@
 
 
1
+ markit