Eluza133 commited on
Commit
c3ce9d1
·
verified ·
1 Parent(s): 09b4841

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +54 -293
app.py CHANGED
@@ -14,11 +14,10 @@ import string
14
  app = Flask(__name__)
15
  app.secret_key = os.getenv("FLASK_SECRET_KEY", "supersecretkey")
16
  DATA_FILE = 'cloud_data.json'
17
- REPO_ID = "Eluza133/Z1e1u"
18
  HF_TOKEN_WRITE = os.getenv("HF_TOKEN")
19
  HF_TOKEN_READ = os.getenv("HF_TOKEN_READ") or HF_TOKEN_WRITE
20
  ADMIN_PASSWORD = "87132morflot"
21
- MAX_STORAGE_GB = 500
22
 
23
  cache = Cache(app, config={'CACHE_TYPE': 'simple'})
24
  logging.basicConfig(level=logging.INFO)
@@ -35,20 +34,6 @@ def load_data():
35
  return {'users': {}, 'files': {}}
36
  data.setdefault('users', {})
37
  data.setdefault('files', {})
38
- for token, user_data in data['users'].items():
39
- if 'folders' not in user_data:
40
- files = user_data.get('files', [])
41
- user_data['folders'] = {
42
- 'root': {
43
- 'name': 'root',
44
- 'files': files,
45
- 'subfolders': {}
46
- }
47
- }
48
- if 'files' in user_data:
49
- del user_data['files']
50
- if 'storage_used' not in user_data:
51
- user_data['storage_used'] = 0
52
  logging.info("Данные успешно загружены")
53
  return data
54
  except Exception as e:
@@ -101,7 +86,7 @@ def download_db_from_hf():
101
  def periodic_backup():
102
  while True:
103
  upload_db_to_hf()
104
- time.sleep(1800)
105
 
106
  # Генерация 13-значного токена
107
  def generate_token():
@@ -164,7 +149,7 @@ h1 {
164
  -webkit-background-clip: text;
165
  color: transparent;
166
  }
167
- input, textarea, select {
168
  width: 100%;
169
  padding: 14px;
170
  margin: 12px 0;
@@ -175,10 +160,10 @@ input, textarea, select {
175
  font-size: 1.1em;
176
  box-shadow: inset 0 3px 10px rgba(0, 0, 0, 0.1);
177
  }
178
- body.dark input, body.dark textarea, body.dark select {
179
  color: var(--text-dark);
180
  }
181
- input:focus, textarea:focus, select:focus {
182
  outline: none;
183
  box-shadow: 0 0 0 4px var(--primary);
184
  }
@@ -207,22 +192,6 @@ input:focus, textarea:focus, select:focus {
207
  .download-btn:hover {
208
  background: #00b8c5;
209
  }
210
- .edit-btn {
211
- background: var(--accent);
212
- padding: 8px 16px;
213
- font-size: 0.9em;
214
- }
215
- .edit-btn:hover {
216
- background: #7a4de3;
217
- }
218
- .delete-btn {
219
- background: #ff3b30;
220
- padding: 8px 16px;
221
- font-size: 0.9em;
222
- }
223
- .delete-btn:hover {
224
- background: #e02a20;
225
- }
226
  .flash {
227
  color: var(--secondary);
228
  text-align: center;
@@ -230,11 +199,11 @@ input:focus, textarea:focus, select:focus {
230
  }
231
  .file-grid {
232
  display: grid;
233
- grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
234
  gap: 20px;
235
  margin-top: 20px;
236
  }
237
- .folder-item, .file-item {
238
  background: var(--card-bg);
239
  padding: 15px;
240
  border-radius: 16px;
@@ -242,18 +211,12 @@ input:focus, textarea:focus, select:focus {
242
  text-align: center;
243
  transition: var(--transition);
244
  }
245
- body.dark .folder-item, body.dark .file-item {
246
  background: var(--card-bg-dark);
247
  }
248
- .folder-item:hover, .file-item:hover {
249
  transform: translateY(-5px);
250
  }
251
- .folder-item {
252
- background: rgba(139, 92, 246, 0.1);
253
- }
254
- body.dark .folder-item {
255
- background: rgba(139, 92, 246, 0.2);
256
- }
257
  .file-preview {
258
  max-width: 100%;
259
  max-height: 200px;
@@ -262,15 +225,15 @@ body.dark .folder-item {
262
  margin-bottom: 10px;
263
  loading: lazy;
264
  }
265
- .folder-item p, .file-item p {
266
  font-size: 0.9em;
267
  margin: 5px 0;
268
  }
269
- .folder-item a, .file-item a {
270
  color: var(--primary);
271
  text-decoration: none;
272
  }
273
- .folder-item a:hover, .file-item a:hover {
274
  color: var(--accent);
275
  }
276
  .modal {
@@ -292,53 +255,6 @@ body.dark .folder-item {
292
  border-radius: 20px;
293
  box-shadow: var(--shadow);
294
  }
295
- .upload-progress, .storage-indicator {
296
- width: 100%;
297
- margin: 20px 0;
298
- }
299
- .upload-progress {
300
- display: none;
301
- }
302
- .progress-bar-container, .storage-bar-container {
303
- width: 100%;
304
- height: 20px;
305
- background: var(--glass-bg);
306
- border-radius: 10px;
307
- overflow: hidden;
308
- position: relative;
309
- }
310
- .progress-bar, .storage-bar {
311
- height: 100%;
312
- width: 0%;
313
- background: linear-gradient(90deg, var(--primary), var(--accent));
314
- transition: width 0.3s ease;
315
- }
316
- .progress-text, .storage-text {
317
- position: absolute;
318
- width: 100%;
319
- text-align: center;
320
- font-size: 0.9em;
321
- color: var(--text-light);
322
- top: 50%;
323
- transform: translateY(-50%);
324
- }
325
- body.dark .progress-text, body.dark .storage-text {
326
- color: var(--text-dark);
327
- }
328
- @media (max-width: 768px) {
329
- .file-grid {
330
- grid-template-columns: repeat(2, 1fr);
331
- }
332
- }
333
- @media (max-width: 480px) {
334
- .file-grid {
335
- grid-template-columns: 1fr;
336
- }
337
- .btn {
338
- padding: 12px 20px;
339
- font-size: 1em;
340
- }
341
- }
342
  '''
343
 
344
  # Регистрация через /admhosto
@@ -351,8 +267,7 @@ def register():
351
  data = load_data()
352
  data['users'][token] = {
353
  'created_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
354
- 'folders': {'root': {'name': 'root', 'files': [], 'subfolders': {}}},
355
- 'storage_used': 0
356
  }
357
  save_data(data)
358
  flash(f'Ваш токен: {token}. Сохраните его!')
@@ -398,7 +313,6 @@ def login():
398
  data = load_data()
399
  if token in data['users'] and len(token) == 13:
400
  session['token'] = token
401
- # Сохранение токена в localStorage перенесено в JavaScript
402
  return redirect(url_for('dashboard'))
403
  else:
404
  flash('Неверный токен! Токен должен быть 13 символов.')
@@ -423,36 +337,20 @@ def login():
423
  {% endfor %}
424
  {% endif %}
425
  {% endwith %}
426
- <form method="POST" id="login-form">
427
  <input type="text" name="token" placeholder="Введите ваш токен" required>
428
  <button type="submit" class="btn">Войти</button>
429
  </form>
430
  <p style="margin-top: 20px;">Нет токена? <a href="{{ url_for('register') }}">Зарегистрируйтесь</a></p>
431
  </div>
432
- <script>
433
- document.getElementById('login-form').onsubmit = function(e) {
434
- const token = e.target.querySelector('input[name="token"]').value;
435
- localStorage.setItem('token', token);
436
- };
437
- </script>
438
  </body>
439
  </html>
440
  '''
441
  return render_template_string(html)
442
 
443
- # Функция для получения папки по пути
444
- def get_folder(data, token, folder_path):
445
- current = data['users'][token]['folders']
446
- if folder_path == 'root':
447
- return current['root']
448
- for folder_name in folder_path.split('/')[1:]:
449
- current = current['subfolders'][folder_name]
450
- return current
451
-
452
  # Личный dashboard
453
  @app.route('/dashboard', methods=['GET', 'POST'])
454
- @app.route('/dashboard/<path:folder_path>', methods=['GET', 'POST'])
455
- def dashboard(folder_path='root'):
456
  if 'token' not in session:
457
  flash('Пожалуйста, войдите!')
458
  return redirect(url_for('login'))
@@ -464,82 +362,40 @@ def dashboard(folder_path='root'):
464
  flash('Токен недействителен!')
465
  return redirect(url_for('login'))
466
 
467
- current_folder = get_folder(data, token, folder_path)
468
- storage_used = data['users'][token]['storage_used']
469
- max_storage_bytes = MAX_STORAGE_GB * 1024 * 1024 * 1024
470
- storage_percent = (storage_used / max_storage_bytes) * 100 if max_storage_bytes > 0 else 0
471
- storage_used_gb = storage_used / (1024 * 1024 * 1024)
472
- storage_remaining_gb = MAX_STORAGE_GB - storage_used_gb
473
 
474
  if request.method == 'POST':
475
- if 'create_folder' in request.form:
476
- folder_name = request.form.get('folder_name')
477
- if folder_name and folder_name not in current_folder['subfolders']:
478
- current_folder['subfolders'][folder_name] = {'name': folder_name, 'files': [], 'subfolders': {}}
479
- save_data(data)
480
-
481
- elif 'edit_folder' in request.form:
482
- old_name = request.form.get('old_name')
483
- new_name = request.form.get('new_name')
484
- if old_name in current_folder['subfolders'] and new_name and new_name not in current_folder['subfolders']:
485
- current_folder['subfolders'][new_name] = current_folder['subfolders'].pop(old_name)
486
- current_folder['subfolders'][new_name]['name'] = new_name
487
- save_data(data)
488
-
489
- elif 'delete_folder' in request.form:
490
- folder_name = request.form.get('folder_name')
491
- if folder_name in current_folder['subfolders']:
492
- del current_folder['subfolders'][folder_name]
493
- save_data(data)
494
-
495
- elif 'move_file' in request.form:
496
- file_index = int(request.form.get('file_index'))
497
- target_folder = request.form.get('target_folder')
498
- file = current_folder['files'].pop(file_index)
499
- target = get_folder(data, token, target_folder)
500
- target['files'].append(file)
501
  save_data(data)
 
 
 
502
 
503
- elif 'upload_files' in request.files:
504
- files = request.files.getlist('files')
505
- total_size = sum(f.content_length for f in files if f)
506
- if storage_used + total_size > max_storage_bytes:
507
- flash('Недостаточно места для загрузки файлов!')
508
- else:
509
- for file in files:
510
- if file and file.filename:
511
- filename = secure_filename(file.filename)
512
- temp_path = os.path.join('uploads', filename)
513
- os.makedirs('uploads', exist_ok=True)
514
- file.save(temp_path)
515
- file_size = os.path.getsize(temp_path)
516
-
517
- api = HfApi()
518
- file_path = f"cloud_files/{token}/{folder_path}/{filename}"
519
- api.upload_file(
520
- path_or_fileobj=temp_path,
521
- path_in_repo=file_path,
522
- repo_id=REPO_ID,
523
- repo_type="dataset",
524
- token=HF_TOKEN_WRITE,
525
- commit_message=f"Загружен файл для {token} в {folder_path}"
526
- )
527
-
528
- file_info = {
529
- 'filename': filename,
530
- 'path': file_path,
531
- 'type': get_file_type(filename),
532
- 'upload_date': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
533
- 'size': file_size
534
- }
535
- current_folder['files'].append(file_info)
536
- data['users'][token]['storage_used'] += file_size
537
-
538
- if os.path.exists(temp_path):
539
- os.remove(temp_path)
540
- save_data(data)
541
-
542
- return redirect(url_for('dashboard', folder_path=folder_path))
543
 
544
  html = '''
545
  <!DOCTYPE html>
@@ -555,57 +411,13 @@ def dashboard(folder_path='root'):
555
  <div class="container">
556
  <h1>Zues Cloud Dashboard</h1>
557
  <p>Токен: {{ token }}</p>
558
- <p>Текущая папка: {{ folder_path }}</p>
559
- <div class="storage-indicator">
560
- <p>Использовано места: {{ "%.2f" % storage_used_gb }} ГБ из {{ MAX_STORAGE_GB }} ГБ (Осталось: {{ "%.2f" % storage_remaining_gb }} ГБ)</p>
561
- <div class="storage-bar-container">
562
- <div class="storage-bar" style="width: {{ storage_percent }}%;"></div>
563
- <span class="storage-text">{{ "%.1f" % storage_percent }}%</span>
564
- </div>
565
- </div>
566
- {% if folder_path != 'root' %}
567
- <a href="{{ url_for('dashboard', folder_path='/'.join(folder_path.split('/')[:-1]) or 'root') }}" class="btn">Назад</a>
568
- {% endif %}
569
-
570
- <h2 style="margin-top: 20px;">Создать папку</h2>
571
- <form method="POST">
572
- <input type="text" name="folder_name" placeholder="Название папки" required>
573
- <button type="submit" name="create_folder" class="btn">Создать</button>
574
- </form>
575
-
576
- <h2 style="margin-top: 20px;">Загрузить файлы</h2>
577
- {% with messages = get_flashed_messages() %}
578
- {% if messages %}
579
- {% for message in messages %}
580
- <div class="flash">{{ message }}</div>
581
- {% endfor %}
582
- {% endif %}
583
- {% endwith %}
584
- <form method="POST" enctype="multipart/form-data" id="upload-form">
585
- <input type="file" name="files" multiple required>
586
- <button type="submit" name="upload_files" class="btn">Загрузить</button>
587
  </form>
588
- <div class="upload-progress" id="upload-progress">
589
- <div class="progress-bar-container">
590
- <div class="progress-bar" id="progress-bar"></div>
591
- <span class="progress-text" id="progress-text">0%</span>
592
- </div>
593
- </div>
594
-
595
- <h2 style="margin-top: 30px;">Папки и файлы</h2>
596
  <div class="file-grid">
597
- {% for folder_name, folder in current_folder['subfolders'].items() %}
598
- <div class="folder-item">
599
- <p><a href="{{ url_for('dashboard', folder_path=folder_path + '/' + folder_name) }}">{{ folder_name }}</a></p>
600
- <form method="POST" style="margin-top: 10px;">
601
- <input type="text" name="new_name" placeholder="Новое имя" value="{{ folder_name }}">
602
- <input type="hidden" name="old_name" value="{{ folder_name }}">
603
- <button type="submit" name="edit_folder" class="btn edit-btn">Переименовать</button>
604
- <button type="submit" name="delete_folder" class="btn delete-btn" onclick="return confirm('Удалить папку?');">Удалить</button>
605
- </form>
606
- </div>
607
- {% endfor %}
608
- {% for i, file in enumerate(current_folder['files']) %}
609
  <div class="file-item">
610
  {% if file['type'] == 'video' %}
611
  <video class="file-preview" preload="metadata" muted loading="lazy" onclick="openModal('https://huggingface.co/datasets/{{ repo_id }}/resolve/main/{{ file['path'] }}', true)">
@@ -616,22 +428,12 @@ def dashboard(folder_path='root'):
616
  {% else %}
617
  <p><a href="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/{{ file['path'] }}" target="_blank">{{ file['filename'] }}</a></p>
618
  {% endif %}
619
- <p>{{ file['upload_date'] }} ({{ "%.2f" % (file['size'] / (1024 * 1024)) }} МБ)</p>
620
  <a href="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/{{ file['path'] }}" class="btn download-btn" download="{{ file['filename'] }}">Скачать</a>
621
- <form method="POST" style="margin-top: 10px;">
622
- <input type="hidden" name="file_index" value="{{ i }}">
623
- <select name="target_folder">
624
- <option value="">Переместить в...</option>
625
- {% for f_name in current_folder['subfolders'] %}
626
- <option value="{{ folder_path + '/' + f_name }}">{{ f_name }}</option>
627
- {% endfor %}
628
- </select>
629
- <button type="submit" name="move_file" class="btn edit-btn">Переместить</button>
630
- </form>
631
  </div>
632
  {% endfor %}
633
- {% if not current_folder['files'] and not current_folder['subfolders'] %}
634
- <p>Папка пуста.</p>
635
  {% endif %}
636
  </div>
637
  <a href="{{ url_for('logout') }}" class="btn" style="margin-top: 20px;">Выйти</a>
@@ -657,52 +459,11 @@ def dashboard(folder_path='root'):
657
  modal.innerHTML = '<div id="modalContent"></div>';
658
  }
659
  }
660
- document.getElementById('upload-form').onsubmit = async function(e) {
661
- e.preventDefault();
662
- const formData = new FormData(this);
663
- const files = formData.getAll('files');
664
- const totalFiles = files.length;
665
- const progressContainer = document.getElementById('upload-progress');
666
- const progressBar = document.getElementById('progress-bar');
667
- const progressText = document.getElementById('progress-text');
668
-
669
- progressContainer.style.display = 'block';
670
- let uploadedFiles = 0;
671
-
672
- const xhr = new XMLHttpRequest();
673
- xhr.open('POST', window.location.pathname, true);
674
- xhr.upload.onprogress = function(event) {
675
- if (event.lengthComputable) {
676
- const percent = Math.round((event.loaded / event.total) * 100);
677
- progressBar.style.width = percent + '%';
678
- progressText.textContent = `Загрузка ${uploadedFiles + 1}/${totalFiles} (${percent}%)`;
679
- }
680
- };
681
- xhr.onload = function() {
682
- uploadedFiles++;
683
- if (uploadedFiles === totalFiles) {
684
- window.location.reload();
685
- } else {
686
- progressText.textContent = `Загружено ${uploadedFiles}/${totalFiles}`;
687
- }
688
- };
689
- xhr.send(formData);
690
- };
691
  </script>
692
  </body>
693
  </html>
694
  '''
695
- return render_template_string(
696
- html,
697
- token=token,
698
- current_folder=current_folder,
699
- folder_path=folder_path,
700
- repo_id=REPO_ID,
701
- storage_used_gb=storage_used_gb,
702
- storage_remaining_gb=storage_remaining_gb,
703
- storage_percent=storage_percent,
704
- MAX_STORAGE_GB=MAX_STORAGE_GB
705
- )
706
 
707
  # Выход
708
  @app.route('/logout')
 
14
  app = Flask(__name__)
15
  app.secret_key = os.getenv("FLASK_SECRET_KEY", "supersecretkey")
16
  DATA_FILE = 'cloud_data.json'
17
+ REPO_ID = "Z1e1u" # Новый репозиторий
18
  HF_TOKEN_WRITE = os.getenv("HF_TOKEN")
19
  HF_TOKEN_READ = os.getenv("HF_TOKEN_READ") or HF_TOKEN_WRITE
20
  ADMIN_PASSWORD = "87132morflot"
 
21
 
22
  cache = Cache(app, config={'CACHE_TYPE': 'simple'})
23
  logging.basicConfig(level=logging.INFO)
 
34
  return {'users': {}, 'files': {}}
35
  data.setdefault('users', {})
36
  data.setdefault('files', {})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  logging.info("Данные успешно загружены")
38
  return data
39
  except Exception as e:
 
86
  def periodic_backup():
87
  while True:
88
  upload_db_to_hf()
89
+ time.sleep(1800) # Бэкап каждые 30 минут
90
 
91
  # Генерация 13-значного токена
92
  def generate_token():
 
149
  -webkit-background-clip: text;
150
  color: transparent;
151
  }
152
+ input, textarea {
153
  width: 100%;
154
  padding: 14px;
155
  margin: 12px 0;
 
160
  font-size: 1.1em;
161
  box-shadow: inset 0 3px 10px rgba(0, 0, 0, 0.1);
162
  }
163
+ body.dark input, body.dark textarea {
164
  color: var(--text-dark);
165
  }
166
+ input:focus, textarea:focus {
167
  outline: none;
168
  box-shadow: 0 0 0 4px var(--primary);
169
  }
 
192
  .download-btn:hover {
193
  background: #00b8c5;
194
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
  .flash {
196
  color: var(--secondary);
197
  text-align: center;
 
199
  }
200
  .file-grid {
201
  display: grid;
202
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
203
  gap: 20px;
204
  margin-top: 20px;
205
  }
206
+ .file-item {
207
  background: var(--card-bg);
208
  padding: 15px;
209
  border-radius: 16px;
 
211
  text-align: center;
212
  transition: var(--transition);
213
  }
214
+ body.dark .file-item {
215
  background: var(--card-bg-dark);
216
  }
217
+ .file-item:hover {
218
  transform: translateY(-5px);
219
  }
 
 
 
 
 
 
220
  .file-preview {
221
  max-width: 100%;
222
  max-height: 200px;
 
225
  margin-bottom: 10px;
226
  loading: lazy;
227
  }
228
+ .file-item p {
229
  font-size: 0.9em;
230
  margin: 5px 0;
231
  }
232
+ .file-item a {
233
  color: var(--primary);
234
  text-decoration: none;
235
  }
236
+ .file-item a:hover {
237
  color: var(--accent);
238
  }
239
  .modal {
 
255
  border-radius: 20px;
256
  box-shadow: var(--shadow);
257
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  '''
259
 
260
  # Регистрация через /admhosto
 
267
  data = load_data()
268
  data['users'][token] = {
269
  'created_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
270
+ 'files': []
 
271
  }
272
  save_data(data)
273
  flash(f'Ваш токен: {token}. Сохраните его!')
 
313
  data = load_data()
314
  if token in data['users'] and len(token) == 13:
315
  session['token'] = token
 
316
  return redirect(url_for('dashboard'))
317
  else:
318
  flash('Неверный токен! Токен должен быть 13 символов.')
 
337
  {% endfor %}
338
  {% endif %}
339
  {% endwith %}
340
+ <form method="POST">
341
  <input type="text" name="token" placeholder="Введите ваш токен" required>
342
  <button type="submit" class="btn">Войти</button>
343
  </form>
344
  <p style="margin-top: 20px;">Нет токена? <a href="{{ url_for('register') }}">Зарегистрируйтесь</a></p>
345
  </div>
 
 
 
 
 
 
346
  </body>
347
  </html>
348
  '''
349
  return render_template_string(html)
350
 
 
 
 
 
 
 
 
 
 
351
  # Личный dashboard
352
  @app.route('/dashboard', methods=['GET', 'POST'])
353
+ def dashboard():
 
354
  if 'token' not in session:
355
  flash('Пожалуйста, войдите!')
356
  return redirect(url_for('login'))
 
362
  flash('Токен недействителен!')
363
  return redirect(url_for('login'))
364
 
365
+ user_files = data['users'][token]['files']
 
 
 
 
 
366
 
367
  if request.method == 'POST':
368
+ file = request.files.get('file')
369
+ if file and file.filename:
370
+ filename = secure_filename(file.filename)
371
+ temp_path = os.path.join('uploads', filename)
372
+ os.makedirs('uploads', exist_ok=True)
373
+ file.save(temp_path)
374
+
375
+ api = HfApi()
376
+ file_path = f"cloud_files/{token}/{filename}"
377
+ api.upload_file(
378
+ path_or_fileobj=temp_path,
379
+ path_in_repo=file_path,
380
+ repo_id=REPO_ID,
381
+ repo_type="dataset",
382
+ token=HF_TOKEN_WRITE,
383
+ commit_message=f"Загружен файл для {token}"
384
+ )
385
+
386
+ file_info = {
387
+ 'filename': filename,
388
+ 'path': file_path,
389
+ 'type': get_file_type(filename),
390
+ 'upload_date': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
391
+ }
392
+ data['users'][token]['files'].append(file_info)
 
393
  save_data(data)
394
+
395
+ if os.path.exists(temp_path):
396
+ os.remove(temp_path)
397
 
398
+ return redirect(url_for('dashboard'))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
399
 
400
  html = '''
401
  <!DOCTYPE html>
 
411
  <div class="container">
412
  <h1>Zues Cloud Dashboard</h1>
413
  <p>Токен: {{ token }}</p>
414
+ <form method="POST" enctype="multipart/form-data">
415
+ <input type="file" name="file" required>
416
+ <button type="submit" class="btn">Загрузить файл</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
417
  </form>
418
+ <h2 style="margin-top: 30px;">Ваши файлы</h2>
 
 
 
 
 
 
 
419
  <div class="file-grid">
420
+ {% for file in user_files %}
 
 
 
 
 
 
 
 
 
 
 
421
  <div class="file-item">
422
  {% if file['type'] == 'video' %}
423
  <video class="file-preview" preload="metadata" muted loading="lazy" onclick="openModal('https://huggingface.co/datasets/{{ repo_id }}/resolve/main/{{ file['path'] }}', true)">
 
428
  {% else %}
429
  <p><a href="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/{{ file['path'] }}" target="_blank">{{ file['filename'] }}</a></p>
430
  {% endif %}
431
+ <p>{{ file['upload_date'] }}</p>
432
  <a href="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/{{ file['path'] }}" class="btn download-btn" download="{{ file['filename'] }}">Скачать</a>
 
 
 
 
 
 
 
 
 
 
433
  </div>
434
  {% endfor %}
435
+ {% if not user_files %}
436
+ <p вас пока нет загруженных файлов.</p>
437
  {% endif %}
438
  </div>
439
  <a href="{{ url_for('logout') }}" class="btn" style="margin-top: 20px;">Выйти</a>
 
459
  modal.innerHTML = '<div id="modalContent"></div>';
460
  }
461
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
  </script>
463
  </body>
464
  </html>
465
  '''
466
+ return render_template_string(html, token=token, user_files=user_files, repo_id=REPO_ID)
 
 
 
 
 
 
 
 
 
 
467
 
468
  # Выход
469
  @app.route('/logout')