forked from spitkov/sxbin
minor improvement to user dashboard
This commit is contained in:
parent
45699446e0
commit
d404490442
29
.gitignore
vendored
Normal file
29
.gitignore
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Ignore SQLite database
|
||||||
|
data.db
|
||||||
|
|
||||||
|
# Ignore uploads directory
|
||||||
|
/uploads/
|
||||||
|
|
||||||
|
# Python-related files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# Virtual environment
|
||||||
|
venv/
|
||||||
|
env/
|
||||||
|
.env
|
||||||
|
|
||||||
|
# IDE-specific files
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# OS-specific files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Log files
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
*.tmp
|
176
app.py
176
app.py
@ -22,7 +22,7 @@ app.secret_key = 'your_secret_key_here' # Add this line
|
|||||||
UPLOAD_FOLDER = './uploads'
|
UPLOAD_FOLDER = './uploads'
|
||||||
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
|
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
|
||||||
DATABASE = 'data.db'
|
DATABASE = 'data.db'
|
||||||
app.config['REMEMBER_COOKIE_DURATION'] = timedelta(days=30) # Set cookie to expire after 30 days
|
app.config['REMEMBER_COOKIE_DURATION'] = timedelta(days=30) # Set cookie to expire after 30 day
|
||||||
|
|
||||||
if not os.path.exists(UPLOAD_FOLDER):
|
if not os.path.exists(UPLOAD_FOLDER):
|
||||||
os.makedirs(UPLOAD_FOLDER)
|
os.makedirs(UPLOAD_FOLDER)
|
||||||
@ -501,17 +501,6 @@ def rename_user_file(username):
|
|||||||
os.rename(old_path, new_path)
|
os.rename(old_path, new_path)
|
||||||
return redirect(url_for('user_files', username=username))
|
return redirect(url_for('user_files', username=username))
|
||||||
|
|
||||||
@app.route('/dash/<username>/create_folder', methods=['POST'])
|
|
||||||
@login_required
|
|
||||||
def create_folder(username):
|
|
||||||
if current_user.username != username:
|
|
||||||
return "Unauthorized", 401
|
|
||||||
subpath = request.form.get('subpath', '').rstrip('/')
|
|
||||||
folder_name = secure_filename(request.form['folder_name'])
|
|
||||||
folder_path = os.path.join(app.config['UPLOAD_FOLDER'], username, subpath, folder_name)
|
|
||||||
if not os.path.exists(folder_path):
|
|
||||||
os.makedirs(folder_path)
|
|
||||||
return redirect(url_for('user_files', username=username, subpath=subpath))
|
|
||||||
|
|
||||||
@app.route('/dash/<username>/delete_folder/<folder_name>', methods=['POST'])
|
@app.route('/dash/<username>/delete_folder/<folder_name>', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@ -880,7 +869,7 @@ def create_new_file(username):
|
|||||||
if current_user.username != username:
|
if current_user.username != username:
|
||||||
return "Unauthorized", 401
|
return "Unauthorized", 401
|
||||||
subpath = request.form.get('subpath', '').rstrip('/')
|
subpath = request.form.get('subpath', '').rstrip('/')
|
||||||
file_name = secure_filename(request.form['file_name'])
|
file_name = request.form['file_name']
|
||||||
file_path = os.path.join(app.config['UPLOAD_FOLDER'], username, subpath, file_name)
|
file_path = os.path.join(app.config['UPLOAD_FOLDER'], username, subpath, file_name)
|
||||||
if not os.path.exists(file_path):
|
if not os.path.exists(file_path):
|
||||||
with open(file_path, 'w') as f:
|
with open(file_path, 'w') as f:
|
||||||
@ -890,95 +879,84 @@ def create_new_file(username):
|
|||||||
flash(f"File '{file_name}' already exists.", 'error')
|
flash(f"File '{file_name}' already exists.", 'error')
|
||||||
return redirect(url_for('user_files', username=username, subpath=subpath))
|
return redirect(url_for('user_files', username=username, subpath=subpath))
|
||||||
|
|
||||||
|
@app.route('/dash/<username>/get_folders')
|
||||||
|
@login_required
|
||||||
|
def get_folders(username):
|
||||||
|
if current_user.username != username:
|
||||||
|
return jsonify({'error': 'Unauthorized'}), 401
|
||||||
|
|
||||||
|
subpath = request.args.get('path', '')
|
||||||
|
folder_path = os.path.join(app.config['UPLOAD_FOLDER'], username, subpath)
|
||||||
|
|
||||||
|
if not os.path.exists(folder_path):
|
||||||
|
return jsonify({'error': 'Folder not found'}), 404
|
||||||
|
|
||||||
|
folders = [f for f in os.listdir(folder_path) if os.path.isdir(os.path.join(folder_path, f))]
|
||||||
|
return jsonify(folders)
|
||||||
|
|
||||||
|
@app.route('/dash/<username>/get_folders_and_files')
|
||||||
|
@login_required
|
||||||
|
def get_folders_and_files(username):
|
||||||
|
if current_user.username != username:
|
||||||
|
return jsonify({'error': 'Unauthorized'}), 401
|
||||||
|
|
||||||
|
subpath = request.args.get('path', '')
|
||||||
|
folder_path = os.path.join(app.config['UPLOAD_FOLDER'], username, subpath)
|
||||||
|
|
||||||
|
if not os.path.exists(folder_path):
|
||||||
|
return jsonify({'error': 'Folder not found'}), 404
|
||||||
|
|
||||||
|
folders = []
|
||||||
|
files = []
|
||||||
|
for item in os.listdir(folder_path):
|
||||||
|
item_path = os.path.join(folder_path, item)
|
||||||
|
if os.path.isdir(item_path):
|
||||||
|
folders.append(item)
|
||||||
|
else:
|
||||||
|
files.append(item)
|
||||||
|
|
||||||
|
return jsonify({'folders': folders, 'files': files})
|
||||||
|
|
||||||
|
@app.route('/dash/<username>/create_folder', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def create_folder(username):
|
||||||
|
if current_user.username != username:
|
||||||
|
return jsonify({'error': 'Unauthorized'}), 401
|
||||||
|
|
||||||
|
if request.is_json:
|
||||||
|
data = request.get_json()
|
||||||
|
folder_name = data.get('folder_name')
|
||||||
|
subpath = data.get('subpath', '').rstrip('/')
|
||||||
|
else:
|
||||||
|
folder_name = request.form.get('folder_name')
|
||||||
|
subpath = request.form.get('subpath', '').rstrip('/')
|
||||||
|
|
||||||
|
if not folder_name:
|
||||||
|
return jsonify({'error': 'Folder name is required'}), 400
|
||||||
|
|
||||||
|
folder_path = os.path.join(app.config['UPLOAD_FOLDER'], username, subpath, folder_name)
|
||||||
|
|
||||||
|
if os.path.exists(folder_path):
|
||||||
|
return jsonify({'error': 'Folder already exists'}), 400
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.makedirs(folder_path)
|
||||||
|
if request.is_json:
|
||||||
|
return jsonify({'success': True, 'message': 'Folder created successfully'})
|
||||||
|
else:
|
||||||
|
flash(f"Folder '{folder_name}' created successfully.", 'success')
|
||||||
|
return redirect(url_for('user_files', username=username, subpath=subpath))
|
||||||
|
except Exception as e:
|
||||||
|
if request.is_json:
|
||||||
|
return jsonify({'error': str(e)}), 500
|
||||||
|
else:
|
||||||
|
flash(f"Error creating folder: {str(e)}", 'error')
|
||||||
|
return redirect(url_for('user_files', username=username, subpath=subpath))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# Start the cleanup thread
|
# Start the cleanup thread
|
||||||
cleanup_thread = threading.Thread(target=delete_old_files)
|
cleanup_thread = threading.Thread(target=delete_old_files)
|
||||||
cleanup_thread.daemon = True
|
cleanup_thread.daemon = True
|
||||||
cleanup_thread.start()
|
cleanup_thread.start()
|
||||||
|
|
||||||
app.run(host='0.0.0.0', port=7123, debug=True)
|
app.run(host='0.0.0.0', port=7123, debug=True)
|
||||||
def api_upload():
|
|
||||||
api_key = request.headers.get('X-API-Key')
|
|
||||||
if not api_key:
|
|
||||||
return jsonify({'error': 'API key is missing'}), 401
|
|
||||||
|
|
||||||
db = get_db()
|
|
||||||
cursor = db.cursor()
|
|
||||||
cursor.execute("SELECT * FROM users WHERE api_key = ?", (api_key,))
|
|
||||||
user = cursor.fetchone()
|
|
||||||
|
|
||||||
if not user:
|
|
||||||
return jsonify({'error': 'Invalid API key'}), 401
|
|
||||||
|
|
||||||
if 'file' in request.files:
|
|
||||||
file = request.files['file']
|
|
||||||
if file.filename == '':
|
|
||||||
return jsonify({'error': 'No selected file'}), 400
|
|
||||||
if file:
|
|
||||||
filename = secure_filename(file.filename)
|
|
||||||
extension = os.path.splitext(filename)[1].lower()
|
|
||||||
|
|
||||||
if extension == '.txt':
|
|
||||||
# Handle text files as pastebins
|
|
||||||
content = file.read().decode('utf-8')
|
|
||||||
vanity = shortuuid.uuid()[:8]
|
|
||||||
|
|
||||||
cursor.execute("INSERT INTO content (vanity, type, data, created_at, user_id) VALUES (?, ?, ?, ?, ?)",
|
|
||||||
(vanity, 'pastebin', content, datetime.now(), user[0]))
|
|
||||||
db.commit()
|
|
||||||
|
|
||||||
url = url_for('redirect_vanity', vanity=vanity, _external=True, _scheme='https')
|
|
||||||
delete_url = url_for('delete_content', vanity=vanity, _external=True, _scheme='https')
|
|
||||||
else:
|
|
||||||
# Handle other file types
|
|
||||||
vanity = shortuuid.uuid()[:8]
|
|
||||||
new_filename = f"{vanity}{extension}"
|
|
||||||
file_path = os.path.join(app.config['UPLOAD_FOLDER'], new_filename)
|
|
||||||
file.save(file_path)
|
|
||||||
|
|
||||||
cursor.execute("INSERT INTO content (vanity, type, data, created_at, user_id) VALUES (?, ?, ?, ?, ?)",
|
|
||||||
(new_filename, 'file', new_filename, datetime.now(), user[0]))
|
|
||||||
db.commit()
|
|
||||||
|
|
||||||
url = url_for('redirect_vanity', vanity=new_filename, _external=True, _scheme='https')
|
|
||||||
delete_url = url_for('delete_content', vanity=new_filename, _external=True, _scheme='https')
|
|
||||||
|
|
||||||
return json.dumps({
|
|
||||||
'status': 'success',
|
|
||||||
'url': url.replace('/download', ''),
|
|
||||||
'deletion_url': delete_url,
|
|
||||||
})
|
|
||||||
elif 'text' in request.form:
|
|
||||||
content = request.form['text']
|
|
||||||
vanity = shortuuid.uuid()[:8]
|
|
||||||
|
|
||||||
cursor.execute("INSERT INTO content (vanity, type, data, created_at, user_id) VALUES (?, ?, ?, ?, ?)",
|
|
||||||
(vanity, 'pastebin', content, datetime.now(), user[0]))
|
|
||||||
db.commit()
|
|
||||||
|
|
||||||
url = url_for('redirect_vanity', vanity=vanity, _external=True, _scheme='https')
|
|
||||||
delete_url = url_for('delete_content', vanity=vanity, _external=True, _scheme='https')
|
|
||||||
|
|
||||||
return json.dumps({
|
|
||||||
'status': 'success',
|
|
||||||
'url': url.replace('/download', ''),
|
|
||||||
'deletion_url': delete_url,
|
|
||||||
})
|
|
||||||
elif 'url' in request.form:
|
|
||||||
long_url = request.form['url']
|
|
||||||
vanity = shortuuid.uuid()[:8]
|
|
||||||
|
|
||||||
cursor.execute("INSERT INTO content (vanity, type, data, created_at, user_id) VALUES (?, ?, ?, ?, ?)",
|
|
||||||
(vanity, 'url', long_url, datetime.now(), user[0]))
|
|
||||||
db.commit()
|
|
||||||
|
|
||||||
short_url = url_for('redirect_vanity', vanity=vanity, _external=True, _scheme='https')
|
|
||||||
delete_url = url_for('delete_content', vanity=vanity, _external=True, _scheme='https')
|
|
||||||
|
|
||||||
return json.dumps({
|
|
||||||
'status': 'success',
|
|
||||||
'url': short_url.replace('/download', ''),
|
|
||||||
'deletion_url': delete_url,
|
|
||||||
})
|
|
||||||
|
|
||||||
return jsonify({'error': 'No file, text, or URL content provided'}), 400
|
|
@ -107,6 +107,61 @@
|
|||||||
.tab-content.active {
|
.tab-content.active {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
.modal {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1000;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0,0,0,0.5);
|
||||||
|
}
|
||||||
|
.modal-content {
|
||||||
|
background-color: #2a2a2a;
|
||||||
|
margin: 15% auto;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
width: 300px;
|
||||||
|
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
.modal-input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px;
|
||||||
|
margin: 10px 0;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #4CAF50;
|
||||||
|
background-color: #333;
|
||||||
|
color: #f0f0f0;
|
||||||
|
}
|
||||||
|
.modal-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
.action-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.file-list {
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.file-item {
|
||||||
|
border-radius: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
border-bottom: 1px solid #3a3a3a;
|
||||||
|
}
|
||||||
|
.file-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
.file-actions .btn {
|
||||||
|
padding: 4px 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -145,19 +200,10 @@
|
|||||||
<input type="submit" value="Upload" class="btn">
|
<input type="submit" value="Upload" class="btn">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<h3>Create Folder</h3>
|
<div class="action-buttons">
|
||||||
<form action="{{ url_for('create_folder', username=username) }}" method="post">
|
<button onclick="showModal('createFolder')" class="btn">Create Folder</button>
|
||||||
<input type="hidden" name="subpath" value="{{ current_path }}">
|
<button onclick="showModal('createFile')" class="btn">Create File</button>
|
||||||
<input type="text" name="folder_name" placeholder="New folder name" required>
|
</div>
|
||||||
<input type="submit" value="Create Folder" class="btn">
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<h3>Create New File</h3>
|
|
||||||
<form action="{{ url_for('create_new_file', username=username) }}" method="post">
|
|
||||||
<input type="hidden" name="subpath" value="{{ current_path }}">
|
|
||||||
<input type="text" name="file_name" placeholder="New file name (e.g., index.html)" required>
|
|
||||||
<input type="submit" value="Create File" class="btn">
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<h3>Files and Folders</h3>
|
<h3>Files and Folders</h3>
|
||||||
<p style="text-align: center;">Current folder: {{ current_folder or 'Root' }}</p>
|
<p style="text-align: center;">Current folder: {{ current_folder or 'Root' }}</p>
|
||||||
@ -169,9 +215,6 @@
|
|||||||
<span class="file-name">
|
<span class="file-name">
|
||||||
<a href="{{ url_for('user_files', username=username, subpath=parent_folder) }}">..</a>
|
<a href="{{ url_for('user_files', username=username, subpath=parent_folder) }}">..</a>
|
||||||
</span>
|
</span>
|
||||||
<div class="file-actions">
|
|
||||||
<!-- No actions for parent directory -->
|
|
||||||
</div>
|
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% for item in items %}
|
{% for item in items %}
|
||||||
@ -185,10 +228,10 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</span>
|
</span>
|
||||||
<div class="file-actions">
|
<div class="file-actions">
|
||||||
|
<button onclick="showModal('rename', '{{ item.name }}', '{{ item.type }}')" class="btn">Rename</button>
|
||||||
|
<button onclick="showModal('move', '{{ item.name }}', '{{ item.type }}')" class="btn">Move</button>
|
||||||
|
<button onclick="showModal('copy', '{{ item.name }}', '{{ item.type }}')" class="btn">Copy</button>
|
||||||
<button onclick="deleteItem('{{ item.name }}', '{{ item.type }}')" class="btn">Delete</button>
|
<button onclick="deleteItem('{{ item.name }}', '{{ item.type }}')" class="btn">Delete</button>
|
||||||
<button onclick="renameItem('{{ item.name }}', '{{ item.type }}')" class="btn">Rename</button>
|
|
||||||
<button onclick="moveItem('{{ item.name }}', '{{ item.type }}')" class="btn">Move</button>
|
|
||||||
<button onclick="copyItem('{{ item.name }}', '{{ item.type }}')" class="btn">Copy</button>
|
|
||||||
{% if item.type == 'file' %}
|
{% if item.type == 'file' %}
|
||||||
<a href="{{ url_for('edit_file', username=username, filename=item.path) }}" class="btn">Edit</a>
|
<a href="{{ url_for('edit_file', username=username, filename=item.path) }}" class="btn">Edit</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -237,6 +280,36 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="customModal" class="modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<h3 id="modalTitle"></h3>
|
||||||
|
<input type="text" id="modalInput" class="modal-input">
|
||||||
|
<div class="modal-buttons">
|
||||||
|
<button onclick="closeModal()" class="btn" style="background-color: #888;">Cancel</button>
|
||||||
|
<button onclick="handleModalAction()" class="btn" style="background-color: #4CAF50;">Confirm</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="folderNavigationModal" class="modal">
|
||||||
|
<div class="modal-content" style="width: 80%; max-width: 600px;">
|
||||||
|
<h3 id="folderNavigationTitle"></h3>
|
||||||
|
<div id="currentPath" style="margin-bottom: 10px;"></div>
|
||||||
|
<div id="folderList" style="max-height: 300px; overflow-y: auto; margin-bottom: 10px;"></div>
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||||
|
<button onclick="showNewFolderInput()" class="btn" style="background-color: #4CAF50;">New Folder</button>
|
||||||
|
</div>
|
||||||
|
<div id="newFolderInputContainer" style="display: none; margin-top: 10px;">
|
||||||
|
<input type="text" id="newFolderInput" placeholder="Enter new folder name" style="width: 70%;">
|
||||||
|
<button onclick="createNewFolder()" class="btn" style="background-color: #4CAF50;">Create</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-buttons">
|
||||||
|
<button onclick="closeFolderNavigation()" class="btn" style="background-color: #888;">Cancel</button>
|
||||||
|
<button onclick="confirmFolderNavigation()" class="btn" style="background-color: #4CAF50;">OK</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function openTab(evt, tabName) {
|
function openTab(evt, tabName) {
|
||||||
var i, tabcontent, tablinks;
|
var i, tabcontent, tablinks;
|
||||||
@ -286,77 +359,107 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renameItem(name, type) {
|
function showModal(action, name = '', type = '') {
|
||||||
const newName = prompt(`Enter new name for this ${type}:`, name);
|
if (action === 'move' || action === 'copy') {
|
||||||
if (newName && newName !== name) {
|
showFolderNavigation(action, name, type);
|
||||||
const form = document.createElement('form');
|
} else {
|
||||||
form.method = 'POST';
|
const modal = document.getElementById('customModal');
|
||||||
form.action = "{{ url_for('rename_user_file', username=username, subpath=current_path) }}";
|
const title = document.getElementById('modalTitle');
|
||||||
const oldInput = document.createElement('input');
|
const input = document.getElementById('modalInput');
|
||||||
oldInput.type = 'hidden';
|
|
||||||
oldInput.name = 'old_filename';
|
switch (action) {
|
||||||
oldInput.value = name;
|
case 'createFolder':
|
||||||
const newInput = document.createElement('input');
|
title.textContent = 'Create New Folder';
|
||||||
newInput.type = 'hidden';
|
input.placeholder = 'Enter folder name';
|
||||||
newInput.name = 'new_filename';
|
break;
|
||||||
newInput.value = newName;
|
case 'createFile':
|
||||||
form.appendChild(oldInput);
|
title.textContent = 'Create New File';
|
||||||
form.appendChild(newInput);
|
input.placeholder = 'Enter file name (with or without extension)';
|
||||||
document.body.appendChild(form);
|
break;
|
||||||
form.submit();
|
case 'rename':
|
||||||
|
title.textContent = `Rename ${type}`;
|
||||||
|
input.value = name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
modal.style.display = 'block';
|
||||||
|
input.focus();
|
||||||
|
|
||||||
|
window.currentAction = { action, name, type };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveItem(name, type) {
|
function closeModal() {
|
||||||
const destination = prompt(`Enter destination path for this ${type}:`, '/');
|
const modal = document.getElementById('customModal');
|
||||||
if (destination) {
|
modal.style.display = 'none';
|
||||||
const form = document.createElement('form');
|
|
||||||
form.method = 'POST';
|
|
||||||
form.action = "{{ url_for('move_item', username=username, subpath=current_path) }}";
|
|
||||||
const nameInput = document.createElement('input');
|
|
||||||
nameInput.type = 'hidden';
|
|
||||||
nameInput.name = 'item_name';
|
|
||||||
nameInput.value = name;
|
|
||||||
const typeInput = document.createElement('input');
|
|
||||||
typeInput.type = 'hidden';
|
|
||||||
typeInput.name = 'item_type';
|
|
||||||
typeInput.value = type;
|
|
||||||
const destInput = document.createElement('input');
|
|
||||||
destInput.type = 'hidden';
|
|
||||||
destInput.name = 'destination_folder';
|
|
||||||
destInput.value = destination;
|
|
||||||
form.appendChild(nameInput);
|
|
||||||
form.appendChild(typeInput);
|
|
||||||
form.appendChild(destInput);
|
|
||||||
document.body.appendChild(form);
|
|
||||||
form.submit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyItem(name, type) {
|
function handleModalAction() {
|
||||||
const destination = prompt(`Enter destination path to copy this ${type}:`, '/');
|
const input = document.getElementById('modalInput');
|
||||||
if (destination) {
|
const value = input.value.trim();
|
||||||
const form = document.createElement('form');
|
|
||||||
form.method = 'POST';
|
if (!value) {
|
||||||
form.action = "{{ url_for('copy_item', username=username, subpath=current_path) }}";
|
alert('Please enter a valid value');
|
||||||
const nameInput = document.createElement('input');
|
return;
|
||||||
nameInput.type = 'hidden';
|
|
||||||
nameInput.name = 'item_name';
|
|
||||||
nameInput.value = name;
|
|
||||||
const typeInput = document.createElement('input');
|
|
||||||
typeInput.type = 'hidden';
|
|
||||||
typeInput.name = 'item_type';
|
|
||||||
typeInput.value = type;
|
|
||||||
const destInput = document.createElement('input');
|
|
||||||
destInput.type = 'hidden';
|
|
||||||
destInput.name = 'destination_folder';
|
|
||||||
destInput.value = destination;
|
|
||||||
form.appendChild(nameInput);
|
|
||||||
form.appendChild(typeInput);
|
|
||||||
form.appendChild(destInput);
|
|
||||||
document.body.appendChild(form);
|
|
||||||
form.submit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (window.currentAction.action) {
|
||||||
|
case 'createFolder':
|
||||||
|
createFolder(value);
|
||||||
|
break;
|
||||||
|
case 'createFile':
|
||||||
|
createFile(value);
|
||||||
|
break;
|
||||||
|
case 'rename':
|
||||||
|
renameItem(window.currentAction.name, window.currentAction.type, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
closeModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
function createFolder(name) {
|
||||||
|
const form = document.createElement('form');
|
||||||
|
form.method = 'POST';
|
||||||
|
form.action = "{{ url_for('create_folder', username=username) }}";
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'hidden';
|
||||||
|
input.name = 'folder_name';
|
||||||
|
input.value = name;
|
||||||
|
form.appendChild(input);
|
||||||
|
document.body.appendChild(form);
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
function createFile(name) {
|
||||||
|
const form = document.createElement('form');
|
||||||
|
form.method = 'POST';
|
||||||
|
form.action = "{{ url_for('create_new_file', username=username) }}";
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'hidden';
|
||||||
|
input.name = 'file_name';
|
||||||
|
input.value = name;
|
||||||
|
form.appendChild(input);
|
||||||
|
document.body.appendChild(form);
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
function renameItem(oldName, type, newName) {
|
||||||
|
const form = document.createElement('form');
|
||||||
|
form.method = 'POST';
|
||||||
|
form.action = "{{ url_for('rename_user_file', username=username, subpath=current_path) }}";
|
||||||
|
const oldInput = document.createElement('input');
|
||||||
|
oldInput.type = 'hidden';
|
||||||
|
oldInput.name = 'old_filename';
|
||||||
|
oldInput.value = oldName;
|
||||||
|
const newInput = document.createElement('input');
|
||||||
|
newInput.type = 'hidden';
|
||||||
|
newInput.name = 'new_filename';
|
||||||
|
newInput.value = newName;
|
||||||
|
form.appendChild(oldInput);
|
||||||
|
form.appendChild(newInput);
|
||||||
|
document.body.appendChild(form);
|
||||||
|
form.submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
function editUrl(vanity, currentUrl) {
|
function editUrl(vanity, currentUrl) {
|
||||||
@ -414,6 +517,156 @@
|
|||||||
this.checked = !this.checked;
|
this.checked = !this.checked;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let currentFolderPath = '';
|
||||||
|
let actionType = '';
|
||||||
|
let itemToMove = '';
|
||||||
|
|
||||||
|
function showFolderNavigation(action, itemName, itemType) {
|
||||||
|
actionType = action;
|
||||||
|
itemToMove = itemName;
|
||||||
|
currentFolderPath = '{{ current_path }}';
|
||||||
|
const modal = document.getElementById('folderNavigationModal');
|
||||||
|
const title = document.getElementById('folderNavigationTitle');
|
||||||
|
title.textContent = `${action} ${itemType}: ${itemName}`;
|
||||||
|
modal.style.display = 'block';
|
||||||
|
updateFolderNavigation();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateFolderNavigation() {
|
||||||
|
const currentPathElement = document.getElementById('currentPath');
|
||||||
|
currentPathElement.textContent = `Current path: ${currentFolderPath || '/'}`;
|
||||||
|
|
||||||
|
const folderList = document.getElementById('folderList');
|
||||||
|
folderList.innerHTML = '';
|
||||||
|
|
||||||
|
if (currentFolderPath) {
|
||||||
|
const parentFolder = document.createElement('div');
|
||||||
|
parentFolder.innerHTML = '<span style="margin-right: 5px;">📁</span> ..';
|
||||||
|
parentFolder.style.cursor = 'pointer';
|
||||||
|
parentFolder.onclick = () => {
|
||||||
|
currentFolderPath = currentFolderPath.split('/').slice(0, -1).join('/');
|
||||||
|
updateFolderNavigation();
|
||||||
|
};
|
||||||
|
folderList.appendChild(parentFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch and display folders and files
|
||||||
|
fetch(`{{ url_for('get_folders_and_files', username=username) }}?path=${currentFolderPath}`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
data.folders.forEach(folder => {
|
||||||
|
const folderElement = document.createElement('div');
|
||||||
|
folderElement.innerHTML = `<span style="margin-right: 5px;">📁</span> ${folder}`;
|
||||||
|
folderElement.style.cursor = 'pointer';
|
||||||
|
folderElement.onclick = () => {
|
||||||
|
currentFolderPath = currentFolderPath ? `${currentFolderPath}/${folder}` : folder;
|
||||||
|
updateFolderNavigation();
|
||||||
|
};
|
||||||
|
folderList.appendChild(folderElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
data.files.forEach(file => {
|
||||||
|
const fileElement = document.createElement('div');
|
||||||
|
fileElement.innerHTML = `<span style="margin-right: 5px;">📄</span> ${file}`;
|
||||||
|
folderList.appendChild(fileElement);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showNewFolderInput() {
|
||||||
|
document.getElementById('newFolderInputContainer').style.display = 'block';
|
||||||
|
document.getElementById('newFolderInput').focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
function createNewFolder() {
|
||||||
|
const newFolderName = document.getElementById('newFolderInput').value.trim();
|
||||||
|
if (newFolderName) {
|
||||||
|
fetch("{{ url_for('create_folder', username=username) }}", {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
folder_name: newFolderName,
|
||||||
|
subpath: currentFolderPath
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
document.getElementById('newFolderInput').value = '';
|
||||||
|
document.getElementById('newFolderInputContainer').style.display = 'none';
|
||||||
|
updateFolderNavigation();
|
||||||
|
} else {
|
||||||
|
alert('Error creating folder: ' + data.error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
alert('An error occurred while creating the folder');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeFolderNavigation() {
|
||||||
|
document.getElementById('folderNavigationModal').style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
function confirmFolderNavigation() {
|
||||||
|
if (actionType === 'move') {
|
||||||
|
moveItem(itemToMove, 'file', currentFolderPath);
|
||||||
|
} else if (actionType === 'copy') {
|
||||||
|
copyItem(itemToMove, 'file', currentFolderPath);
|
||||||
|
}
|
||||||
|
closeFolderNavigation();
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveItem(name, type, destination) {
|
||||||
|
const form = document.createElement('form');
|
||||||
|
form.method = 'POST';
|
||||||
|
form.action = "{{ url_for('move_item', username=username, subpath=current_path) }}";
|
||||||
|
const nameInput = document.createElement('input');
|
||||||
|
nameInput.type = 'hidden';
|
||||||
|
nameInput.name = 'item_name';
|
||||||
|
nameInput.value = name;
|
||||||
|
const typeInput = document.createElement('input');
|
||||||
|
typeInput.type = 'hidden';
|
||||||
|
typeInput.name = 'item_type';
|
||||||
|
typeInput.value = type;
|
||||||
|
const destInput = document.createElement('input');
|
||||||
|
destInput.type = 'hidden';
|
||||||
|
destInput.name = 'destination_folder';
|
||||||
|
destInput.value = destination;
|
||||||
|
form.appendChild(nameInput);
|
||||||
|
form.appendChild(typeInput);
|
||||||
|
form.appendChild(destInput);
|
||||||
|
document.body.appendChild(form);
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyItem(name, type, destination) {
|
||||||
|
const form = document.createElement('form');
|
||||||
|
form.method = 'POST';
|
||||||
|
form.action = "{{ url_for('copy_item', username=username, subpath=current_path) }}";
|
||||||
|
const nameInput = document.createElement('input');
|
||||||
|
nameInput.type = 'hidden';
|
||||||
|
nameInput.name = 'item_name';
|
||||||
|
nameInput.value = name;
|
||||||
|
const typeInput = document.createElement('input');
|
||||||
|
typeInput.type = 'hidden';
|
||||||
|
typeInput.name = 'item_type';
|
||||||
|
typeInput.value = type;
|
||||||
|
const destInput = document.createElement('input');
|
||||||
|
destInput.type = 'hidden';
|
||||||
|
destInput.name = 'destination_folder';
|
||||||
|
destInput.value = destination;
|
||||||
|
form.appendChild(nameInput);
|
||||||
|
form.appendChild(typeInput);
|
||||||
|
form.appendChild(destInput);
|
||||||
|
document.body.appendChild(form);
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
Loading…
Reference in New Issue
Block a user