From 9d69649e27cc5d93c07adeb20d406e2ccdce6d6d Mon Sep 17 00:00:00 2001 From: Nazaryan ART <84046495+SL1dee36@users.noreply.github.com> Date: Thu, 19 Dec 2024 23:20:53 +0300 Subject: [PATCH] v1.1.0.0 --- CloudNest/app.py | 102 ++++++++++++++++- CloudNest/static/style.css | 85 ++++++++++---- CloudNest/templates/edit.html | 2 +- CloudNest/templates/folder.html | 101 +++++++++------- CloudNest/templates/index.html | 196 +++++++++++++++----------------- 5 files changed, 318 insertions(+), 168 deletions(-) diff --git a/CloudNest/app.py b/CloudNest/app.py index d8805b6..ed186a2 100644 --- a/CloudNest/app.py +++ b/CloudNest/app.py @@ -22,10 +22,15 @@ if not os.path.exists(app.config['THUMBNAIL_FOLDER']): os.makedirs(app.config['THUMBNAIL_FOLDER']) -def generate_thumbnail(filepath, filename): - thumbnail_path = os.path.join(app.config['THUMBNAIL_FOLDER'], f"{os.path.splitext(filename)[0]}.jpg") +def generate_thumbnail(filepath, filename, current_path=None): + if current_path: + thumbnail_filename = os.path.join(current_path,f"{os.path.splitext(filename)[0]}.jpg") + thumbnail_path = os.path.join(app.config['THUMBNAIL_FOLDER'],thumbnail_filename) + else: + thumbnail_path = os.path.join(app.config['THUMBNAIL_FOLDER'], f"{os.path.splitext(filename)[0]}.jpg") + if os.path.exists(thumbnail_path): - return thumbnail_path # Если миниатюра уже есть, возвращаем путь к ней + return thumbnail_path # Если миниатюра уже есть, возвращаем путь к ней try: mime_type = mimetypes.guess_type(filepath)[0] if mime_type and mime_type.startswith('image'): @@ -49,6 +54,7 @@ def generate_thumbnail(filepath, filename): # Изменяем размер до желаемого размера миниатюры image = image.resize((200, 200)) + os.makedirs(os.path.dirname(thumbnail_path), exist_ok=True) image.save(thumbnail_path) elif mime_type and mime_type.startswith('video'): clip = VideoFileClip(filepath) @@ -72,6 +78,7 @@ def generate_thumbnail(filepath, filename): # Изменяем размер до желаемого размера миниатюры img = img.resize((200, 200)) + os.makedirs(os.path.dirname(thumbnail_path), exist_ok=True) img.save(thumbnail_path) clip.close() else: @@ -276,7 +283,7 @@ def open_folder(foldername): mime_type.startswith('application/x-bzip2')): is_archive = True - thumbnail_path = generate_thumbnail(item_path, item_name) + thumbnail_path = generate_thumbnail(item_path, item_name, current_path=foldername) item_info = { 'name': item_name, @@ -310,6 +317,93 @@ def is_editable_file(filename): editable_extensions = ['.txt', '.html', '.css', '.js', '.py', '.json', '.xml', '.csv', '.md', '.log'] # и другие текстовые форматы return filename.lower().endswith(tuple(editable_extensions)) +# Добавленные маршруты для создания папок, файлов и переименования +@app.route('/create_folder', methods=['POST']) +def create_folder(): + folder_name = request.form.get('folderName') + current_path = request.form.get('currentPath') + if not folder_name: + return jsonify({'error': 'Folder name is required'}), 400 + + if current_path: + folder_path = os.path.join(app.config['UPLOAD_FOLDER'], current_path, folder_name) + else: + folder_path = os.path.join(app.config['UPLOAD_FOLDER'], folder_name) + + try: + if os.path.exists(folder_path): + return jsonify({'error': 'Folder already exists'}), 400 + os.makedirs(folder_path) + update_file_list() + return jsonify({'message': 'Folder created successfully'}) + except Exception as e: + return jsonify({'error': str(e)}), 500 + +@app.route('/create_file', methods=['POST']) +def create_file(): + file_name = request.form.get('fileName') + file_content = request.form.get('fileContent', '') + current_path = request.form.get('currentPath') + if not file_name: + return jsonify({'error': 'File name is required'}), 400 + + if current_path: + file_path = os.path.join(app.config['UPLOAD_FOLDER'],current_path, file_name) + else: + file_path = os.path.join(app.config['UPLOAD_FOLDER'], file_name) + + try: + if os.path.exists(file_path): + return jsonify({'error': 'File already exists'}), 400 + with open(file_path, 'w', encoding='utf-8') as f: + f.write(file_content) + update_file_list() + return jsonify({'message': 'File created successfully'}) + except Exception as e: + return jsonify({'error': str(e)}), 500 + +@app.route('/rename', methods=['POST']) +def rename_item(): + old_name = request.form.get('oldName') + new_name = request.form.get('newName') + current_path = request.form.get('currentPath') + + + if not old_name or not new_name: + return jsonify({'error': 'Old and new names are required'}), 400 + + if current_path: + old_path = os.path.join(app.config['UPLOAD_FOLDER'], current_path, old_name) + new_path = os.path.join(app.config['UPLOAD_FOLDER'], current_path, new_name) + else: + old_path = os.path.join(app.config['UPLOAD_FOLDER'], old_name) + new_path = os.path.join(app.config['UPLOAD_FOLDER'], new_name) + + try: + if not os.path.exists(old_path): + return jsonify({'error': 'File not found'}), 404 + if os.path.exists(new_path): + return jsonify({'error': 'New name already exists'}), 400 + + os.rename(old_path,new_path) + # Переименование миниатюры (если есть) + + if current_path: + old_thumbnail_path = os.path.join(app.config['THUMBNAIL_FOLDER'],current_path, f"{os.path.splitext(old_name)[0]}.jpg") + new_thumbnail_path = os.path.join(app.config['THUMBNAIL_FOLDER'],current_path, f"{os.path.splitext(new_name)[0]}.jpg") + else: + old_thumbnail_path = os.path.join(app.config['THUMBNAIL_FOLDER'], f"{os.path.splitext(old_name)[0]}.jpg") + new_thumbnail_path = os.path.join(app.config['THUMBNAIL_FOLDER'], f"{os.path.splitext(new_name)[0]}.jpg") + + + if os.path.exists(old_thumbnail_path): + os.rename(old_thumbnail_path, new_thumbnail_path) + update_file_list() + return jsonify({'message': 'Item renamed successfully'}) + except Exception as e: + return jsonify({'error': str(e)}), 500 + + if __name__ == '__main__': if not os.path.exists(app.config['UPLOAD_FOLDER']): os.makedirs(app.config['UPLOAD_FOLDER']) diff --git a/CloudNest/static/style.css b/CloudNest/static/style.css index 22e5cea..fa6aae8 100644 --- a/CloudNest/static/style.css +++ b/CloudNest/static/style.css @@ -82,22 +82,12 @@ ul#fileList { flex-direction: column; gap: 8px; } -ul#fileList.list-view li { - background-color: #333; - padding: 10px; - border-radius: 5px; - display: flex; - justify-content: space-between; - align-items: center; - transition: background-color 0.3s ease; - position: relative; - overflow: hidden; -} ul#fileList.list-view li:hover { - padding: 9px; + padding: 10px; border: 1px solid #fff; + margin: -1px; } /* Стили для плиточного отображения */ @@ -106,6 +96,18 @@ ul#fileList.grid-view { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 15px; } +ul#fileList.list-view li { + background-color: #333; + padding: 10px; + border-radius: 5px; + display: flex; + justify-content: space-between; + align-items: center; + transition: background-color 0.3s ease; + position: relative; /* Добавлено relative позиционирование */ + /* overflow: hidden; */ +} + ul#fileList.grid-view li { background-color: #333; padding: 15px; @@ -115,17 +117,17 @@ ul#fileList.grid-view li { justify-content: space-between; align-items: flex-start; transition: background-color 0.3s ease; - position: relative; - overflow: hidden; + position: relative; /* Добавлено relative позиционирование */ + /* overflow: hidden; */ } ul#fileList.grid-view li:hover { background-color: #444; border: 1px solid #fff; padding: 14px; + } - /* Анимация загрузки и извлечения */ li.uploading::before, li.extracting::before { @@ -197,8 +199,8 @@ button:hover { } .delete-btn:hover { - background-color: transparent; - border: 1px solid #fff; + border: 1px solid #ff9d9d; + padding: 7px 14px; } .delete-btn { @@ -206,7 +208,6 @@ button:hover { border: 1px solid #fff; color: #fff; } - /* Дополнительные стили для плиток */ ul#fileList.grid-view .item-name, ul#fileList.grid-view .item-type, @@ -256,6 +257,8 @@ ul#fileList.grid-view .item-thumbnail { margin: 0 auto; /* Центрируем изображение/видео внутри контейнера */ } + + /* Стили для модальных окон */ .modal { display: none; @@ -289,7 +292,7 @@ ul#fileList.grid-view .item-thumbnail { display: flex; flex-direction: column; } -.modal-content form label { + .modal-content form label { margin-bottom: 5px; } .modal-content form input, .modal-content form textarea{ @@ -302,4 +305,48 @@ ul#fileList.grid-view .item-thumbnail { } .modal-content form textarea{ height: 150px; +} + + + + +/* Стили для меню действий */ +.actions-btn { + font-size: 1.5em; + line-height: 0.8; + padding: 0; + margin-left: 5px; + border: none; + background-color: transparent; /* Убедитесь, что фон прозрачный */ + color: white; /* Убедитесь, что текст виден */ +} + +.actions-menu { + position: absolute; + top: 110%; + right: -1%; + background-color: #333; + border: 1px solid #555; + border-radius: 5px; + padding: 5px 0; + display: none; + z-index: 100; +} + +.actions-menu.show { + display: block; +} + +.actions-menu button { + display: block; + border: none; + width: 100%; + text-align: left; + padding: 8px 15px; + margin: 0; + background-color: transparent; /* Убедитесь, что фон прозрачный */ + color: white; /* Убедитесь, что текст виден */ +} +.actions-menu button:hover { + background-color: #444; } \ No newline at end of file diff --git a/CloudNest/templates/edit.html b/CloudNest/templates/edit.html index e8b312a..a3e72ba 100644 --- a/CloudNest/templates/edit.html +++ b/CloudNest/templates/edit.html @@ -11,7 +11,7 @@ color: #fff; } textarea { - width: 100%; + width: calc((100% - 22px)); height: 500px; background-color: #242424; color: #fff; diff --git a/CloudNest/templates/folder.html b/CloudNest/templates/folder.html index 6ac255e..5cc9ac7 100644 --- a/CloudNest/templates/folder.html +++ b/CloudNest/templates/folder.html @@ -30,28 +30,31 @@