2264 lines
72 KiB
HTML
2264 lines
72 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>{{ username }}'s Dashboard</title>
|
|
<style>
|
|
:root {
|
|
--bg-color: #1e1e1e;
|
|
--text-color: #e0e0e0;
|
|
--highlight-bg: #2d2d2d;
|
|
--highlight-border: #444;
|
|
--button-bg: #3a3a3a;
|
|
--button-text: #e0e0e0;
|
|
}
|
|
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
line-height: 1.6;
|
|
margin: 0;
|
|
padding: 20px;
|
|
background-color: var(--bg-color);
|
|
color: var(--text-color);
|
|
display: flex;
|
|
justify-content: center;
|
|
}
|
|
.container {
|
|
max-width: 800px;
|
|
width: 100%;
|
|
}
|
|
h2, h3 {
|
|
color: #4CAF50;
|
|
text-align: center;
|
|
}
|
|
nav {
|
|
margin-bottom: 20px;
|
|
text-align: center;
|
|
}
|
|
nav a, .btn {
|
|
display: inline-block;
|
|
background-color: var(--button-bg);
|
|
color: var(--button-text);
|
|
padding: 8px 12px;
|
|
text-decoration: none;
|
|
border-radius: 4px;
|
|
margin: 0 5px;
|
|
border: none;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
}
|
|
nav a:hover, .btn:hover {
|
|
opacity: 0.8;
|
|
}
|
|
form {
|
|
margin-bottom: 20px;
|
|
text-align: center;
|
|
}
|
|
input[type="text"], input[type="file"] {
|
|
padding: 8px;
|
|
margin-right: 10px;
|
|
border-radius: 4px;
|
|
border: 1px solid var(--highlight-border);
|
|
background-color: var(--highlight-bg);
|
|
color: var(--text-color);
|
|
}
|
|
.file-list {
|
|
list-style-type: none;
|
|
padding: 0;
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
.file-item {
|
|
background-color: var(--highlight-bg);
|
|
padding: 10px;
|
|
border-radius: 5px;
|
|
margin-bottom: 5px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
position: relative;
|
|
z-index: 2;
|
|
}
|
|
.file-icon {
|
|
margin-right: 10px;
|
|
}
|
|
.file-name {
|
|
flex-grow: 1;
|
|
}
|
|
.file-actions {
|
|
display: flex;
|
|
gap: 5px;
|
|
}
|
|
.folder {
|
|
font-weight: bold;
|
|
}
|
|
.upload-list {
|
|
margin-top: 20px;
|
|
}
|
|
.upload-item {
|
|
margin-bottom: 10px;
|
|
}
|
|
.tabs {
|
|
display: flex;
|
|
justify-content: center;
|
|
margin-bottom: 20px;
|
|
}
|
|
.tab {
|
|
background-color: var(--button-bg);
|
|
color: var(--button-text);
|
|
padding: 10px 20px;
|
|
cursor: pointer;
|
|
border: none;
|
|
}
|
|
.tab.active {
|
|
background-color: #4CAF50;
|
|
}
|
|
.tab-content {
|
|
display: none;
|
|
}
|
|
.tab-content.active {
|
|
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: var(--bg-color);
|
|
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 var(--highlight-border);
|
|
background-color: var(--highlight-bg);
|
|
color: var(--text-color);
|
|
}
|
|
.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 var(--highlight-border);
|
|
}
|
|
.file-item:last-child {
|
|
border-bottom: none;
|
|
}
|
|
.file-actions .btn {
|
|
padding: 4px 8px;
|
|
font-size: 12px;
|
|
}
|
|
.btn-ok {
|
|
background-color: #4CAF50;
|
|
color: white;
|
|
}
|
|
.btn-cancel {
|
|
background-color: #888;
|
|
color: white;
|
|
}
|
|
.btn-remove {
|
|
background-color: #f44336;
|
|
color: white;
|
|
}
|
|
a {
|
|
color: var(--text-color);
|
|
text-decoration: none;
|
|
}
|
|
a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
.dropdown {
|
|
position: relative;
|
|
display: inline-block;
|
|
}
|
|
.dropdown-content {
|
|
display: none;
|
|
position: absolute;
|
|
background-color: var(--highlight-bg);
|
|
min-width: 160px;
|
|
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
|
padding: 12px 16px;
|
|
z-index: 1;
|
|
border-radius: 4px;
|
|
}
|
|
.dropdown-content a {
|
|
color: var(--text-color);
|
|
padding: 12px 16px;
|
|
text-decoration: none;
|
|
display: block;
|
|
}
|
|
.dropdown-content a:hover {
|
|
background-color: var(--button-bg);
|
|
}
|
|
.dropdown:hover .dropdown-content {
|
|
display: block;
|
|
}
|
|
.dropbtn {
|
|
background-color: var(--button-bg);
|
|
color: var(--button-text);
|
|
padding: 4px 8px;
|
|
font-size: 12px;
|
|
border: none;
|
|
cursor: pointer;
|
|
}
|
|
.dropbtn:hover {
|
|
opacity: 0.8;
|
|
}
|
|
|
|
.dropdown {
|
|
position: relative;
|
|
display: inline-block;
|
|
}
|
|
|
|
.dropbtn {
|
|
background-color: var(--button-bg);
|
|
color: var(--button-text);
|
|
padding: 8px 12px;
|
|
font-size: 16px;
|
|
border: none;
|
|
cursor: pointer;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.dropdown-content {
|
|
display: none;
|
|
position: absolute;
|
|
right: 0;
|
|
background-color: var(--bg-color);
|
|
min-width: 160px;
|
|
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
|
z-index: 1000;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.dropdown-content a {
|
|
color: var(--text-color);
|
|
padding: 12px 16px;
|
|
text-decoration: none;
|
|
display: block;
|
|
}
|
|
|
|
.dropdown-content a:hover {
|
|
background-color: var(--highlight-bg);
|
|
}
|
|
|
|
.dropdown:hover .dropdown-content {
|
|
display: block;
|
|
}
|
|
|
|
.dropdown:hover .dropbtn {
|
|
background-color: var(--highlight-bg);
|
|
}
|
|
|
|
.btn {
|
|
display: inline-block;
|
|
background-color: #4CAF50;
|
|
color: white;
|
|
padding: 8px 12px;
|
|
text-decoration: none;
|
|
border-radius: 4px;
|
|
margin: 0 5px;
|
|
border: none;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
min-width: 120px; /* Increased width */
|
|
text-align: center;
|
|
}
|
|
|
|
.btn:hover {
|
|
background-color: #45a049;
|
|
}
|
|
|
|
.dropdown {
|
|
position: relative;
|
|
display: inline-block;
|
|
margin-left: 10px;
|
|
}
|
|
|
|
.dropbtn {
|
|
background-color: transparent;
|
|
color: var(--text-color);
|
|
padding: 5px 10px;
|
|
font-size: 16px;
|
|
border: none;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.dropdown-content {
|
|
display: none;
|
|
position: absolute;
|
|
background-color: var(--bg-color);
|
|
min-width: 160px;
|
|
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
|
z-index: 1000;
|
|
border-radius: 4px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.dropdown-content a {
|
|
color: var(--text-color);
|
|
padding: 12px 16px;
|
|
text-decoration: none;
|
|
display: block;
|
|
transition: background-color 0.3s ease;
|
|
}
|
|
|
|
.dropdown-content a:hover {
|
|
background-color: var(--highlight-bg);
|
|
}
|
|
|
|
.dropdown:hover .dropdown-content {
|
|
display: block;
|
|
animation: fadeIn 0.3s;
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; }
|
|
to { opacity: 1; }
|
|
}
|
|
|
|
input[type="text"], input[type="file"], input[type="password"] {
|
|
width: 100%;
|
|
padding: 10px;
|
|
margin: 10px 0;
|
|
border: 1px solid var(--highlight-border);
|
|
background-color: var(--highlight-bg);
|
|
color: var(--text-color);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.action-buttons {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 10px;
|
|
margin: 20px 0;
|
|
}
|
|
|
|
.action-buttons .btn {
|
|
min-width: 150px; /* Increased width for action buttons */
|
|
}
|
|
|
|
.upload-item {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.upload-item a {
|
|
color: #4CAF50;
|
|
text-decoration: none;
|
|
margin-right: 5px;
|
|
}
|
|
|
|
.upload-item a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.dropbtn {
|
|
background-color: transparent;
|
|
color: var(--text-color);
|
|
border: none;
|
|
cursor: pointer;
|
|
font-size: 16px;
|
|
padding: 0 5px;
|
|
}
|
|
|
|
.dropdown {
|
|
position: relative;
|
|
display: inline-block;
|
|
}
|
|
|
|
.dropdown-content {
|
|
display: none;
|
|
position: absolute;
|
|
background-color: var(--bg-color);
|
|
min-width: 160px;
|
|
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
|
z-index: 1000;
|
|
right: 0;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.dropdown-content a {
|
|
color: var(--text-color);
|
|
padding: 12px 16px;
|
|
text-decoration: none;
|
|
display: block;
|
|
}
|
|
|
|
.dropdown-content a:hover {
|
|
background-color: var(--highlight-bg);
|
|
}
|
|
|
|
.dropdown:hover .dropdown-content {
|
|
display: block;
|
|
}
|
|
|
|
.action-buttons {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 10px;
|
|
margin: 20px 0;
|
|
}
|
|
|
|
.action-buttons .btn {
|
|
flex: 1;
|
|
max-width: 200px;
|
|
}
|
|
|
|
/* Styles from index.html for file upload */
|
|
.upload-form {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 10px;
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.upload-form input[type="file"] {
|
|
display: none;
|
|
}
|
|
|
|
.upload-form label {
|
|
background-color: #4CAF50;
|
|
color: white;
|
|
padding: 10px 20px;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
transition: background-color 0.3s;
|
|
}
|
|
|
|
.upload-form label:hover {
|
|
background-color: #45a049;
|
|
}
|
|
|
|
.upload-form button {
|
|
background-color: #4CAF50;
|
|
color: white;
|
|
border: none;
|
|
padding: 10px 20px;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
transition: background-color 0.3s;
|
|
}
|
|
|
|
.upload-form button:hover {
|
|
background-color: #45a049;
|
|
}
|
|
|
|
.upload-area {
|
|
border: 2px dashed #4CAF50;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
text-align: center;
|
|
cursor: pointer;
|
|
margin-bottom: 20px;
|
|
width: calc(100% - 44px);
|
|
}
|
|
.upload-area:hover {
|
|
background-color: #2d2d2d;
|
|
}
|
|
#fileInput {
|
|
display: none;
|
|
}
|
|
.progress-bar {
|
|
width: 100%;
|
|
background-color: #333;
|
|
border-radius: 4px;
|
|
margin-top: 10px;
|
|
}
|
|
.progress {
|
|
width: 0%;
|
|
height: 20px;
|
|
background-color: #4CAF50;
|
|
border-radius: 4px;
|
|
text-align: center;
|
|
line-height: 20px;
|
|
color: white;
|
|
}
|
|
|
|
/* Styles for the new upload modal */
|
|
.upload-modal {
|
|
display: none;
|
|
position: fixed;
|
|
z-index: 1000;
|
|
left: 0;
|
|
top: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background-color: rgba(0,0,0,0.5);
|
|
}
|
|
.upload-modal-content {
|
|
background-color: var(--bg-color);
|
|
margin: 15% auto;
|
|
padding: 20px;
|
|
border-radius: 8px;
|
|
width: 300px;
|
|
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
|
}
|
|
.upload-modal-input {
|
|
width: 100%;
|
|
padding: 8px;
|
|
margin: 10px 0;
|
|
border-radius: 4px;
|
|
border: 1px solid var(--highlight-border);
|
|
background-color: var(--highlight-bg);
|
|
color: var(--text-color);
|
|
}
|
|
.upload-modal-buttons {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: 10px;
|
|
margin-top: 15px;
|
|
}
|
|
.upload-modal-file-list {
|
|
list-style-type: none;
|
|
padding: 0;
|
|
margin-top: 10px;
|
|
}
|
|
.upload-modal-file-item {
|
|
background-color: var(--highlight-bg);
|
|
padding: 10px;
|
|
border-radius: 5px;
|
|
margin-bottom: 5px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
.upload-modal-file-icon {
|
|
margin-right: 10px;
|
|
}
|
|
.upload-modal-file-name {
|
|
flex-grow: 1;
|
|
}
|
|
.upload-modal-file-actions {
|
|
display: flex;
|
|
gap: 5px;
|
|
}
|
|
.upload-modal-file-item:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
.upload-modal-file-actions .btn {
|
|
padding: 4px 8px;
|
|
font-size: 12px;
|
|
}
|
|
.upload-modal-btn-ok {
|
|
background-color: #4CAF50;
|
|
color: white;
|
|
}
|
|
.upload-modal-btn-cancel {
|
|
background-color: #888;
|
|
color: white;
|
|
}
|
|
.upload-modal-btn-remove {
|
|
background-color: #f44336;
|
|
color: white;
|
|
}
|
|
.upload-modal-drop-area {
|
|
border: 2px dashed #4CAF50;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
text-align: center;
|
|
cursor: pointer;
|
|
margin-bottom: 20px;
|
|
width: calc(100% - 44px);
|
|
}
|
|
.upload-modal-drop-area:hover {
|
|
background-color: #2d2d2d;
|
|
}
|
|
.upload-modal-progress-bar {
|
|
width: 100%;
|
|
background-color: #333;
|
|
border-radius: 4px;
|
|
margin-top: 10px;
|
|
}
|
|
.upload-modal-progress {
|
|
width: 0%;
|
|
height: 20px;
|
|
background-color: #4CAF50;
|
|
border-radius: 4px;
|
|
text-align: center;
|
|
line-height: 20px;
|
|
color: white;
|
|
}
|
|
|
|
/* Styles for the dropdown menu */
|
|
.dropdown {
|
|
position: relative;
|
|
display: inline-block;
|
|
}
|
|
|
|
.dropbtn {
|
|
background-color: transparent;
|
|
color: var(--text-color);
|
|
padding: 5px;
|
|
font-size: 16px;
|
|
border: none;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.dropdown-content {
|
|
display: none;
|
|
position: absolute;
|
|
background-color: var(--bg-color);
|
|
min-width: 160px;
|
|
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
|
z-index: 1000;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.dropdown-content a {
|
|
color: var(--text-color);
|
|
padding: 12px 16px;
|
|
text-decoration: none;
|
|
display: block;
|
|
}
|
|
|
|
.dropdown-content a:hover {
|
|
background-color: var(--highlight-bg);
|
|
}
|
|
|
|
.dropdown:hover .dropdown-content {
|
|
display: block;
|
|
}
|
|
|
|
.file-item, .upload-item {
|
|
position: relative;
|
|
}
|
|
|
|
.dropdown {
|
|
position: static;
|
|
}
|
|
|
|
.dropdown-content {
|
|
position: absolute;
|
|
top: 100%;
|
|
right: 0;
|
|
}
|
|
|
|
/* New styles for adaptive positioning */
|
|
.file-list, .upload-list {
|
|
position: relative;
|
|
}
|
|
|
|
.file-item:last-child .dropdown-content,
|
|
.upload-item:last-child .dropdown-content {
|
|
bottom: auto;
|
|
top: 100%;
|
|
}
|
|
|
|
/* Media query for smaller screens */
|
|
@media screen and (max-height: 600px) {
|
|
.dropdown-content {
|
|
bottom: auto;
|
|
top: 100%;
|
|
}
|
|
}
|
|
|
|
.file-item, .upload-item {
|
|
position: relative;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 10px;
|
|
background-color: var(--highlight-bg);
|
|
margin-bottom: 5px;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.file-name, .upload-info {
|
|
flex-grow: 1;
|
|
margin-right: 10px;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.dropdown {
|
|
position: relative;
|
|
}
|
|
|
|
.dropbtn {
|
|
background-color: transparent;
|
|
color: var(--text-color);
|
|
padding: 5px;
|
|
font-size: 16px;
|
|
border: none;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.dropdown-content {
|
|
display: none;
|
|
position: absolute;
|
|
background-color: var(--bg-color);
|
|
min-width: 160px;
|
|
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
|
z-index: 9999;
|
|
border-radius: 4px;
|
|
right: 0;
|
|
margin-top: 2px; /* Add a small gap between button and dropdown */
|
|
}
|
|
|
|
.dropdown-content a {
|
|
color: var(--text-color);
|
|
padding: 12px 16px;
|
|
text-decoration: none;
|
|
display: block;
|
|
}
|
|
|
|
.dropdown-content a:hover {
|
|
background-color: var(--highlight-bg);
|
|
}
|
|
|
|
.dropdown:hover .dropdown-content {
|
|
display: block;
|
|
}
|
|
|
|
/* Ensure the dropdown is always on top */
|
|
.file-item:hover, .upload-item:hover {
|
|
z-index: 1001;
|
|
}
|
|
|
|
.dropdown:hover {
|
|
z-index: 1002;
|
|
}
|
|
|
|
/* Styles for the collapsible file groups */
|
|
.file-group {
|
|
margin-bottom: 10px;
|
|
border: 1px solid var(--highlight-border);
|
|
border-radius: 4px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.file-group-header {
|
|
display: flex;
|
|
align-items: center;
|
|
background-color: var(--highlight-bg);
|
|
padding: 10px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.file-group-arrow {
|
|
margin-right: 10px;
|
|
font-size: 16px;
|
|
transition: transform 0.3s;
|
|
}
|
|
|
|
.file-group-arrow.collapsed {
|
|
transform: rotate(-90deg);
|
|
}
|
|
|
|
.file-group-content.expanded {
|
|
display: block;
|
|
}
|
|
|
|
.file-group-links {
|
|
margin-top: 10px;
|
|
}
|
|
|
|
.file-group-link {
|
|
display: block;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.file-group-link a {
|
|
color: var(--text-color);
|
|
text-decoration: none;
|
|
}
|
|
|
|
.file-group-link a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.file-list {
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
|
|
.file-item {
|
|
position: relative;
|
|
z-index: 2;
|
|
}
|
|
|
|
.dropdown {
|
|
position: relative;
|
|
z-index: 1000; /* Increased z-index */
|
|
}
|
|
|
|
.dropbtn {
|
|
background-color: transparent;
|
|
color: var(--text-color);
|
|
padding: 5px;
|
|
font-size: 16px;
|
|
border: none;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.dropdown-content {
|
|
display: none;
|
|
position: absolute;
|
|
right: 0;
|
|
top: 100%;
|
|
background-color: var(--bg-color);
|
|
min-width: 160px;
|
|
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
|
z-index: 1001; /* Increased z-index */
|
|
border-radius: 4px;
|
|
overflow: visible; /* Changed from hidden to visible */
|
|
}
|
|
|
|
.dropdown-content a {
|
|
color: var(--text-color);
|
|
padding: 12px 16px;
|
|
text-decoration: none;
|
|
display: block;
|
|
}
|
|
|
|
.dropdown-content a:hover {
|
|
background-color: var(--highlight-bg);
|
|
}
|
|
|
|
.dropdown:hover .dropdown-content {
|
|
display: block;
|
|
}
|
|
|
|
/* Ensure the dropdown is always on top */
|
|
.file-item:hover,
|
|
.upload-item:hover {
|
|
z-index: 1002; /* Increased z-index */
|
|
}
|
|
|
|
.dropdown:hover {
|
|
z-index: 1003; /* Increased z-index */
|
|
}
|
|
|
|
/* Remove any max-height or overflow properties on parent containers */
|
|
.tab-content,
|
|
.file-list,
|
|
.upload-list {
|
|
overflow: visible;
|
|
max-height: none;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<h2>{{ username }}'s Dashboard</h2>
|
|
<nav>
|
|
<a href="{{ url_for('index') }}">Home</a>
|
|
<a href="{{ url_for('logout') }}">Logout</a>
|
|
</nav>
|
|
<div style="text-align: center; margin-top: 10px;">
|
|
<a href="{{ url_for('serve_user_page', username=username) }}" class="btn" style="min-width: 150px;">Visit my site</a>
|
|
</div>
|
|
|
|
<div class="tabs">
|
|
<button class="tab active" onclick="openTab(event, 'filesAndFolders')">Files and Folders</button>
|
|
<button class="tab" onclick="openTab(event, 'myUploads')">My Uploads</button>
|
|
<button class="tab" onclick="openTab(event, 'apiKeyShareX')">API Key & ShareX</button>
|
|
</div>
|
|
|
|
<div id="filesAndFolders" class="tab-content active">
|
|
<form id="toggleIndexForm" style="text-align: center;">
|
|
<label>
|
|
<input type="checkbox" id="ignoreIndexCheckbox" {% if ignore_index %}checked{% endif %}>
|
|
Ignore index.html and always show file listing
|
|
</label>
|
|
</form>
|
|
|
|
{% if index_exists and not ignore_index %}
|
|
<p style="text-align: center;">An index.html file exists in this folder. When viewing publicly, this file will be displayed instead of the file listing.</p>
|
|
{% endif %}
|
|
|
|
<div class="action-buttons">
|
|
<button onclick="showModal('createFolder')" class="btn">Create Folder</button>
|
|
<button onclick="showModal('createFile')" class="btn">Create File</button>
|
|
<button onclick="showUploadModal()" class="btn">Upload File</button>
|
|
</div>
|
|
|
|
<h3>Files and Folders</h3>
|
|
<p style="text-align: center;">Current folder: {{ current_folder or 'Root' }}</p>
|
|
|
|
<ul class="file-list">
|
|
{% if parent_folder is not none %}
|
|
<li class="file-item folder">
|
|
<span class="file-icon">📁</span>
|
|
<span class="file-name">
|
|
<a href="{{ url_for('user_files', username=username, subpath=parent_folder) }}">..</a>
|
|
</span>
|
|
</li>
|
|
{% endif %}
|
|
{% for item in items %}
|
|
<li class="file-item {% if item.type == 'folder' %}folder{% endif %}">
|
|
<span class="file-icon">{% if item.type == 'folder' %}📁{% else %}📄{% endif %}</span>
|
|
<span class="file-name">
|
|
{% if item.type == 'folder' %}
|
|
<a href="{{ url_for('user_files', username=username, subpath=item.path) }}">{{ item.name }}</a>
|
|
{% else %}
|
|
{{ item.name }}
|
|
{% endif %}
|
|
</span>
|
|
<div class="dropdown">
|
|
<button class="dropbtn">•••</button>
|
|
<div class="dropdown-content">
|
|
<a href="#" onclick="showModal('rename', '{{ item.name }}', '{{ item.type }}')">Rename</a>
|
|
<a href="#" onclick="showModal('move', '{{ item.name }}', '{{ item.type }}')">Move</a>
|
|
<a href="#" onclick="showModal('copy', '{{ item.name }}', '{{ item.type }}')">Copy</a>
|
|
<a href="#" onclick="deleteItem('{{ item.name }}', '{{ item.type }}')">Delete</a>
|
|
{% if item.type == 'file' %}
|
|
<a href="{{ url_for('edit_file', username=username, filename=item.path) }}">Edit</a>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
</div>
|
|
|
|
<div id="myUploads" class="tab-content">
|
|
<h3>Your Uploads</h3>
|
|
<div class="upload-list">
|
|
{% for upload in uploads %}
|
|
<div class="upload-item">
|
|
<div class="upload-info">
|
|
{% if upload.type == 'pastebin' %}
|
|
Pastebin:
|
|
{% elif upload.type == 'file' %}
|
|
File:
|
|
{% elif upload.type == 'url' %}
|
|
Shortened URL:
|
|
{% endif %}
|
|
<a href="{{ upload.url }}" target="_blank">
|
|
{% if upload.type == 'file' %}
|
|
{{ upload.data }}
|
|
{% else %}
|
|
{{ upload.vanity }}
|
|
{% endif %}
|
|
</a>
|
|
(Created: {{ upload.created_at }})
|
|
</div>
|
|
<div class="dropdown">
|
|
<button class="dropbtn">•••</button>
|
|
<div class="dropdown-content">
|
|
<a href="{{ url_for('content_info', vanity=upload.vanity) }}">Info</a>
|
|
{% if upload.type == 'url' %}
|
|
<a href="#" onclick="editUrl('{{ upload.vanity }}', '{{ upload.data }}')">Edit</a>
|
|
{% else %}
|
|
<a href="{{ url_for('edit_content', vanity=upload.vanity) }}">Edit</a>
|
|
{% endif %}
|
|
<a href="#" onclick="deleteUpload('{{ upload.vanity }}')">Delete</a>
|
|
{% if upload.is_private %}
|
|
<a href="#" onclick="openEditPasswordModal('{{ upload.vanity }}')">Edit Password</a>
|
|
{% else %}
|
|
<a href="#" onclick="openAddPasswordModal('{{ upload.vanity }}')">Add Password</a>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
|
|
<div id="apiKeyShareX" class="tab-content">
|
|
<h3>API Key & ShareX</h3>
|
|
|
|
<div class="sharex-config-section">
|
|
<h4>ShareX Configuration</h4>
|
|
<p>Download the ShareX configuration file to easily integrate with our service:</p>
|
|
<a href="{{ url_for('generate_sharex_config') }}" class="btn">Download ShareX Config</a>
|
|
</div>
|
|
|
|
<div class="api-key-section">
|
|
<h4>Your API Key</h4>
|
|
<p>API Key: <span id="apiKey" class="blurred">{{ current_user.api_key }}</span></p>
|
|
<button onclick="showResetApiKeyModal()" class="btn">Reset API Key</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Reset API Key Modal -->
|
|
<div id="resetApiKeyModal" class="modal">
|
|
<div class="modal-content">
|
|
<h2>Reset API Key</h2>
|
|
<p>Are you sure you want to reset your API key? This action cannot be undone.</p>
|
|
<p>Your old ShareX configuration will no longer work. You'll need to generate a new one after resetting.</p>
|
|
<div class="modal-buttons">
|
|
<button onclick="resetApiKey()" class="btn btn-danger">Reset API Key</button>
|
|
<button onclick="closeResetApiKeyModal()" class="btn">Cancel</button>
|
|
</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>
|
|
|
|
<div id="passwordModal" class="modal">
|
|
<div class="modal-content">
|
|
<h3 id="passwordModalTitle">Edit Password</h3>
|
|
<input type="password" id="newPassword1" placeholder="Enter new password">
|
|
<input type="password" id="newPassword2" placeholder="Confirm new password">
|
|
<div class="modal-buttons">
|
|
<button onclick="closePasswordModal()" class="btn-cancel">Cancel</button>
|
|
<button onclick="updatePassword()" class="btn-ok">OK</button>
|
|
<button onclick="removePassword()" class="btn-remove" id="removePasswordBtn">Remove Password</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="uploadModal" class="modal">
|
|
<div class="modal-content">
|
|
<span class="close" onclick="closeUploadModal()">×</span>
|
|
<h2>Upload File</h2>
|
|
<div id="uploadArea" class="upload-area">
|
|
<p>Drag and drop files here or click to select files</p>
|
|
<input type="file" id="fileInput" multiple>
|
|
</div>
|
|
<div class="progress-bar">
|
|
<div id="progressBar" class="progress"></div>
|
|
</div>
|
|
<div id="fileResult"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
:root {
|
|
--bg-color: #121212;
|
|
--text-color: #ffffff;
|
|
--highlight-bg: #333333;
|
|
--highlight-text: #ffffff;
|
|
--btn-bg: #4CAF50;
|
|
--btn-text: #ffffff;
|
|
--btn-hover-bg: #45a049;
|
|
--btn-hover-text: #ffffff;
|
|
--modal-bg: #222222;
|
|
--modal-text: #ffffff;
|
|
--modal-btn-bg: #4CAF50;
|
|
--modal-btn-text: #ffffff;
|
|
--modal-btn-hover-bg: #45a049;
|
|
--modal-btn-hover-text: #ffffff;
|
|
}
|
|
|
|
body {
|
|
background-color: var(--bg-color);
|
|
color: var(--text-color);
|
|
font-family: Arial, sans-serif;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
.container {
|
|
max-width: 800px;
|
|
margin: 0 auto;
|
|
padding: 20px;
|
|
}
|
|
|
|
h2 {
|
|
text-align: center;
|
|
}
|
|
|
|
nav {
|
|
text-align: center;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
nav a {
|
|
color: var(--text-color);
|
|
text-decoration: none;
|
|
margin: 0 10px;
|
|
}
|
|
|
|
.tabs {
|
|
display: flex;
|
|
justify-content: center;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.tab {
|
|
background-color: var(--bg-color);
|
|
color: var(--text-color);
|
|
border: none;
|
|
outline: none;
|
|
cursor: pointer;
|
|
padding: 14px 16px;
|
|
font-size: 17px;
|
|
width: 100%;
|
|
transition: background-color 0.3s;
|
|
}
|
|
|
|
.tab:hover {
|
|
background-color: var(--highlight-bg);
|
|
}
|
|
|
|
.tab.active {
|
|
background-color: var(--btn-bg);
|
|
color: var(--btn-text);
|
|
}
|
|
|
|
.tab-content {
|
|
display: none;
|
|
padding: 20px;
|
|
border: 1px solid var(--highlight-bg);
|
|
background-color: var(--modal-bg);
|
|
color: var(--modal-text);
|
|
border-radius: 5px;
|
|
}
|
|
|
|
.tab-content.active {
|
|
display: block;
|
|
}
|
|
|
|
.btn {
|
|
display: inline-block;
|
|
background-color: #4CAF50;
|
|
color: white;
|
|
padding: 8px 12px;
|
|
text-decoration: none;
|
|
border-radius: 4px;
|
|
margin: 0 5px;
|
|
border: none;
|
|
cursor: pointer;
|
|
font-size: 14px; /* Increased width */
|
|
text-align: center;
|
|
}
|
|
|
|
.btn:hover {
|
|
background-color: #45a049;
|
|
}
|
|
|
|
.dropdown {
|
|
position: relative;
|
|
display: inline-block;
|
|
margin-left: 10px;
|
|
}
|
|
|
|
.dropbtn {
|
|
background-color: transparent;
|
|
color: var(--text-color);
|
|
padding: 5px 10px;
|
|
font-size: 16px;
|
|
border: none;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.dropdown-content {
|
|
display: none;
|
|
position: absolute;
|
|
background-color: var(--bg-color);
|
|
min-width: 160px;
|
|
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
|
z-index: 1000;
|
|
border-radius: 4px;
|
|
overflow: hidden;
|
|
right: 0;
|
|
top: 100%;
|
|
}
|
|
|
|
.dropdown-content a {
|
|
color: var(--text-color);
|
|
padding: 12px 16px;
|
|
text-decoration: none;
|
|
display: block;
|
|
transition: background-color 0.3s ease;
|
|
}
|
|
|
|
.dropdown-content a:hover {
|
|
background-color: var(--highlight-bg);
|
|
}
|
|
|
|
.dropdown:hover .dropdown-content {
|
|
display: block;
|
|
animation: fadeIn 0.3s;
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; }
|
|
to { opacity: 1; }
|
|
}
|
|
|
|
input[type="text"], input[type="file"], input[type="password"] {
|
|
width: 100%;
|
|
padding: 10px;
|
|
margin: 10px 0;
|
|
border: 1px solid var(--highlight-border);
|
|
background-color: var(--highlight-bg);
|
|
color: var(--text-color);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.action-buttons {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 10px;
|
|
margin: 20px 0;
|
|
}
|
|
|
|
.action-buttons .btn {
|
|
flex: 1;
|
|
max-width: 200px;
|
|
}
|
|
|
|
.upload-item {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.upload-item a {
|
|
color: #4CAF50;
|
|
text-decoration: none;
|
|
margin-right: 5px;
|
|
}
|
|
|
|
.upload-item a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.dropbtn {
|
|
background-color: transparent;
|
|
color: var(--text-color);
|
|
border: none;
|
|
cursor: pointer;
|
|
font-size: 16px;
|
|
padding: 0 5px;
|
|
}
|
|
|
|
.dropdown {
|
|
position: relative;
|
|
display: inline-block;
|
|
}
|
|
|
|
.dropdown-content {
|
|
display: none;
|
|
position: absolute;
|
|
background-color: var(--bg-color);
|
|
min-width: 160px;
|
|
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
|
z-index: 1000;
|
|
right: 0;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.dropdown-content a {
|
|
color: var(--text-color);
|
|
padding: 12px 16px;
|
|
text-decoration: none;
|
|
display: block;
|
|
}
|
|
|
|
.dropdown-content a:hover {
|
|
background-color: var(--highlight-bg);
|
|
}
|
|
|
|
.dropdown:hover .dropdown-content {
|
|
display: block;
|
|
}
|
|
|
|
.action-buttons {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 10px;
|
|
margin: 20px 0;
|
|
}
|
|
|
|
.action-buttons .btn {
|
|
flex: 1;
|
|
max-width: 200px;
|
|
}
|
|
|
|
.upload-area {
|
|
border: 2px dashed #4CAF50;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
text-align: center;
|
|
cursor: pointer;
|
|
margin-bottom: 20px;
|
|
width: calc(100% - 44px);
|
|
}
|
|
.upload-area:hover {
|
|
background-color: #2d2d2d;
|
|
}
|
|
#fileInput {
|
|
display: none;
|
|
}
|
|
.progress-bar {
|
|
width: 100%;
|
|
background-color: #333;
|
|
border-radius: 4px;
|
|
margin-top: 10px;
|
|
}
|
|
.progress {
|
|
width: 0%;
|
|
height: 20px;
|
|
background-color: #4CAF50;
|
|
border-radius: 4px;
|
|
text-align: center;
|
|
line-height: 20px;
|
|
color: white;
|
|
}
|
|
|
|
/* Styles for the new upload modal */
|
|
.upload-modal {
|
|
display: none;
|
|
position: fixed;
|
|
z-index: 1000;
|
|
left: 0;
|
|
top: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background-color: rgba(0,0,0,0.5);
|
|
}
|
|
.upload-modal-content {
|
|
background-color: var(--bg-color);
|
|
margin: 15% auto;
|
|
padding: 20px;
|
|
border-radius: 8px;
|
|
width: 300px;
|
|
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
|
}
|
|
.upload-modal-input {
|
|
width: 100%;
|
|
padding: 8px;
|
|
margin: 10px 0;
|
|
border-radius: 4px;
|
|
border: 1px solid var(--highlight-border);
|
|
background-color: var(--highlight-bg);
|
|
color: var(--text-color);
|
|
}
|
|
.upload-modal-buttons {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: 10px;
|
|
margin-top: 15px;
|
|
}
|
|
.upload-modal-file-list {
|
|
list-style-type: none;
|
|
padding: 0;
|
|
margin-top: 10px;
|
|
}
|
|
.upload-modal-file-item {
|
|
background-color: var(--highlight-bg);
|
|
padding: 10px;
|
|
border-radius: 5px;
|
|
margin-bottom: 5px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
.upload-modal-file-icon {
|
|
margin-right: 10px;
|
|
}
|
|
.upload-modal-file-name {
|
|
flex-grow: 1;
|
|
}
|
|
.upload-modal-file-actions {
|
|
display: flex;
|
|
gap: 5px;
|
|
}
|
|
.upload-modal-file-item:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
.upload-modal-file-actions .btn {
|
|
padding: 4px 8px;
|
|
font-size: 12px;
|
|
}
|
|
.upload-modal-btn-ok {
|
|
background-color: #4CAF50;
|
|
color: white;
|
|
}
|
|
.upload-modal-btn-cancel {
|
|
background-color: #888;
|
|
color: white;
|
|
}
|
|
.upload-modal-btn-remove {
|
|
background-color: #f44336;
|
|
color: white;
|
|
}
|
|
.upload-modal-drop-area {
|
|
border: 2px dashed #4CAF50;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
text-align: center;
|
|
cursor: pointer;
|
|
margin-bottom: 20px;
|
|
width: calc(100% - 44px);
|
|
}
|
|
.upload-modal-drop-area:hover {
|
|
background-color: #2d2d2d;
|
|
}
|
|
.upload-modal-progress-bar {
|
|
width: 100%;
|
|
background-color: #333;
|
|
border-radius: 4px;
|
|
margin-top: 10px;
|
|
}
|
|
.upload-modal-progress {
|
|
width: 0%;
|
|
height: 20px;
|
|
background-color: #4CAF50;
|
|
border-radius: 4px;
|
|
text-align: center;
|
|
line-height: 20px;
|
|
color: white;
|
|
}
|
|
|
|
/* Styles for the dropdown menu */
|
|
.dropdown {
|
|
position: relative;
|
|
display: inline-block;
|
|
}
|
|
|
|
.dropbtn {
|
|
background-color: transparent;
|
|
color: var(--text-color);
|
|
padding: 5px;
|
|
font-size: 16px;
|
|
border: none;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.dropdown-content {
|
|
display: none;
|
|
position: absolute;
|
|
right: 0;
|
|
background-color: var(--bg-color);
|
|
min-width: 160px;
|
|
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
|
z-index: 1000;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.dropdown-content a {
|
|
color: var(--text-color);
|
|
padding: 12px 16px;
|
|
text-decoration: none;
|
|
display: block;
|
|
}
|
|
|
|
.dropdown-content a:hover {
|
|
background-color: var(--highlight-bg);
|
|
}
|
|
|
|
.dropdown:hover .dropdown-content {
|
|
display: block;
|
|
}
|
|
|
|
.file-item, .upload-item {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 10px;
|
|
background-color: var(--highlight-bg);
|
|
margin-bottom: 5px;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.file-name, .upload-info {
|
|
flex-grow: 1;
|
|
margin-right: 10px;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.dropdown {
|
|
position: relative;
|
|
display: inline-block;
|
|
}
|
|
|
|
.dropbtn {
|
|
background-color: transparent;
|
|
color: var(--text-color);
|
|
padding: 5px;
|
|
font-size: 16px;
|
|
border: none;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.dropdown-content {
|
|
display: none;
|
|
position: absolute;
|
|
right: 0;
|
|
background-color: var(--bg-color);
|
|
min-width: 160px;
|
|
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
|
z-index: 1000;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.dropdown-content a {
|
|
color: var(--text-color);
|
|
padding: 12px 16px;
|
|
text-decoration: none;
|
|
display: block;
|
|
}
|
|
|
|
.dropdown-content a:hover {
|
|
background-color: var(--highlight-bg);
|
|
}
|
|
|
|
.dropdown:hover .dropdown-content {
|
|
display: block;
|
|
}
|
|
|
|
/* Ensure the dropdown is always on top */
|
|
.file-item:hover, .upload-item:hover {
|
|
z-index: 1001;
|
|
}
|
|
|
|
.dropdown:hover {
|
|
z-index: 1002;
|
|
}
|
|
|
|
/* Styles for the collapsible file groups */
|
|
.file-group {
|
|
margin-bottom: 10px;
|
|
border: 1px solid var(--highlight-border);
|
|
border-radius: 4px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.file-group-header {
|
|
display: flex;
|
|
align-items: center;
|
|
background-color: var(--highlight-bg);
|
|
padding: 10px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.file-group-arrow {
|
|
margin-right: 10px;
|
|
font-size: 16px;
|
|
transition: transform 0.3s;
|
|
}
|
|
|
|
.file-group-arrow.collapsed {
|
|
transform: rotate(-90deg);
|
|
}
|
|
|
|
.file-group-content {
|
|
display: none;
|
|
padding: 10px;
|
|
}
|
|
|
|
.file-group-content.expanded {
|
|
display: block;
|
|
}
|
|
|
|
.file-group-links {
|
|
margin-top: 10px;
|
|
}
|
|
|
|
.file-group-link {
|
|
display: block;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.file-group-link a {
|
|
color: var(--text-color);
|
|
text-decoration: none;
|
|
}
|
|
|
|
.file-group-link a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.blurred {
|
|
filter: blur(5px);
|
|
transition: filter 0.3s ease;
|
|
}
|
|
|
|
.blurred:hover {
|
|
filter: blur(0);
|
|
}
|
|
|
|
.api-key-section, .sharex-config-section {
|
|
margin-bottom: 20px;
|
|
padding: 15px;
|
|
background-color: var(--highlight-bg);
|
|
border-radius: 5px;
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
function openTab(evt, tabName) {
|
|
var i, tabcontent, tablinks;
|
|
tabcontent = document.getElementsByClassName("tab-content");
|
|
for (i = 0; i < tabcontent.length; i++) {
|
|
tabcontent[i].style.display = "none";
|
|
}
|
|
tablinks = document.getElementsByClassName("tab");
|
|
for (i = 0; i < tablinks.length; i++) {
|
|
tablinks[i].className = tablinks[i].className.replace(" active", "");
|
|
}
|
|
document.getElementById(tabName).style.display = "block";
|
|
evt.currentTarget.className += " active";
|
|
}
|
|
|
|
function deleteItem(name, type) {
|
|
if (confirm(`Are you sure you want to delete this ${type}?`)) {
|
|
const form = document.createElement('form');
|
|
form.method = 'POST';
|
|
form.action = "{{ url_for('delete_user_file', username=username, filename='') }}" + name;
|
|
document.body.appendChild(form);
|
|
form.submit();
|
|
}
|
|
}
|
|
|
|
function deleteUpload(vanity) {
|
|
if (confirm('Are you sure you want to delete this upload?')) {
|
|
fetch("{{ url_for('delete_content', vanity='') }}" + vanity, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({})
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
location.reload();
|
|
} else {
|
|
alert('Error deleting upload: ' + data.error);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert('An error occurred while deleting the upload');
|
|
});
|
|
}
|
|
}
|
|
|
|
function showModal(action, name = '', type = '') {
|
|
if (action === 'move' || action === 'copy') {
|
|
showFolderNavigation(action, name, type);
|
|
} else {
|
|
const modal = document.getElementById('customModal');
|
|
const title = document.getElementById('modalTitle');
|
|
const input = document.getElementById('modalInput');
|
|
|
|
switch (action) {
|
|
case 'createFolder':
|
|
title.textContent = 'Create New Folder';
|
|
input.placeholder = 'Enter folder name';
|
|
break;
|
|
case 'createFile':
|
|
title.textContent = 'Create New File';
|
|
input.placeholder = 'Enter file name (with or without extension)';
|
|
break;
|
|
case 'rename':
|
|
title.textContent = `Rename ${type}`;
|
|
input.value = name;
|
|
break;
|
|
}
|
|
|
|
modal.style.display = 'block';
|
|
input.focus();
|
|
|
|
window.currentAction = { action, name, type };
|
|
}
|
|
}
|
|
|
|
function closeModal() {
|
|
const modal = document.getElementById('customModal');
|
|
modal.style.display = 'none';
|
|
}
|
|
|
|
function handleModalAction() {
|
|
const input = document.getElementById('modalInput');
|
|
const value = input.value.trim();
|
|
|
|
if (!value) {
|
|
alert('Please enter a valid value');
|
|
return;
|
|
}
|
|
|
|
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;
|
|
const pathInput = document.createElement('input');
|
|
pathInput.type = 'hidden';
|
|
pathInput.name = 'subpath';
|
|
pathInput.value = '{{ current_path }}';
|
|
form.appendChild(input);
|
|
form.appendChild(pathInput);
|
|
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) }}";
|
|
|
|
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;
|
|
|
|
const typeInput = document.createElement('input');
|
|
typeInput.type = 'hidden';
|
|
typeInput.name = 'item_type';
|
|
typeInput.value = type;
|
|
|
|
const currentPathInput = document.createElement('input');
|
|
currentPathInput.type = 'hidden';
|
|
currentPathInput.name = 'current_path';
|
|
currentPathInput.value = '{{ current_path }}';
|
|
|
|
form.appendChild(oldInput);
|
|
form.appendChild(newInput);
|
|
form.appendChild(typeInput);
|
|
form.appendChild(currentPathInput);
|
|
document.body.appendChild(form);
|
|
form.submit();
|
|
}
|
|
|
|
function editUrl(vanity, currentUrl) {
|
|
const newUrl = prompt("Enter the new URL:", currentUrl);
|
|
if (newUrl && newUrl !== currentUrl) {
|
|
fetch('/edit/content/' + vanity, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({ content: newUrl }),
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
alert('URL updated successfully');
|
|
location.reload();
|
|
} else {
|
|
alert('Error updating URL: ' + data.error);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert('An error occurred while updating the URL');
|
|
});
|
|
}
|
|
}
|
|
|
|
document.getElementById('ignoreIndexCheckbox').addEventListener('change', function() {
|
|
fetch("{{ url_for('toggle_index', username=username) }}", {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-Requested-With': 'XMLHttpRequest'
|
|
},
|
|
body: JSON.stringify({})
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
// Update the checkbox state based on the server response
|
|
this.checked = data.ignore_index;
|
|
// Reload the page to reflect the changes
|
|
location.reload();
|
|
} else {
|
|
alert('Error toggling index.html ignore setting: ' + data.error);
|
|
// Revert the checkbox state if there was an error
|
|
this.checked = !this.checked;
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert('An error occurred while toggling the index.html ignore setting');
|
|
// Revert the checkbox state if there was an error
|
|
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();
|
|
}
|
|
|
|
let currentVanity = '';
|
|
|
|
function openEditPasswordModal(vanity) {
|
|
currentVanity = vanity;
|
|
document.getElementById('passwordModalTitle').textContent = 'Edit Password';
|
|
document.getElementById('removePasswordBtn').style.display = 'inline-block';
|
|
document.getElementById('passwordModal').style.display = 'block';
|
|
}
|
|
|
|
function openAddPasswordModal(vanity) {
|
|
currentVanity = vanity;
|
|
document.getElementById('passwordModalTitle').textContent = 'Add Password';
|
|
document.getElementById('removePasswordBtn').style.display = 'none';
|
|
document.getElementById('passwordModal').style.display = 'block';
|
|
}
|
|
|
|
function closePasswordModal() {
|
|
document.getElementById('passwordModal').style.display = 'none';
|
|
document.getElementById('newPassword1').value = '';
|
|
document.getElementById('newPassword2').value = '';
|
|
}
|
|
|
|
function updatePassword() {
|
|
const password1 = document.getElementById('newPassword1').value;
|
|
const password2 = document.getElementById('newPassword2').value;
|
|
|
|
if (password1 !== password2) {
|
|
alert('Passwords do not match');
|
|
return;
|
|
}
|
|
|
|
fetch(`{{ url_for('edit_password', vanity='') }}${currentVanity}`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
action: 'update',
|
|
new_password: password1
|
|
}),
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
alert('Password updated successfully');
|
|
closePasswordModal();
|
|
location.reload(); // Reload the page to reflect the changes
|
|
} else {
|
|
alert('Error updating password: ' + data.error);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert('An error occurred while updating the password');
|
|
});
|
|
}
|
|
|
|
function removePassword() {
|
|
if (confirm('Are you sure you want to remove the password?')) {
|
|
fetch(`{{ url_for('edit_password', vanity='') }}${currentVanity}`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
action: 'remove'
|
|
}),
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
alert('Password removed successfully');
|
|
closePasswordModal();
|
|
location.reload(); // Reload the page to reflect the changes
|
|
} else {
|
|
alert('Error removing password: ' + data.error);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert('An error occurred while removing the password');
|
|
});
|
|
}
|
|
}
|
|
|
|
function showUploadModal() {
|
|
document.getElementById('uploadModal').style.display = 'block';
|
|
}
|
|
|
|
function closeUploadModal() {
|
|
document.getElementById('uploadModal').style.display = 'none';
|
|
}
|
|
|
|
const uploadArea = document.getElementById('uploadArea');
|
|
const fileInput = document.getElementById('fileInput');
|
|
const progressBar = document.getElementById('progressBar');
|
|
|
|
uploadArea.addEventListener('click', () => fileInput.click());
|
|
uploadArea.addEventListener('dragover', (e) => {
|
|
e.preventDefault();
|
|
uploadArea.style.backgroundColor = '#2d2d2d';
|
|
});
|
|
uploadArea.addEventListener('dragleave', () => {
|
|
uploadArea.style.backgroundColor = '';
|
|
});
|
|
uploadArea.addEventListener('drop', (e) => {
|
|
e.preventDefault();
|
|
uploadArea.style.backgroundColor = '';
|
|
handleFiles(e.dataTransfer.files);
|
|
});
|
|
fileInput.addEventListener('change', () => handleFiles(fileInput.files));
|
|
|
|
function handleFiles(files) {
|
|
for (let file of files) {
|
|
uploadFile(file);
|
|
}
|
|
}
|
|
|
|
function uploadFile(file) {
|
|
const formData = new FormData();
|
|
formData.append('file', file);
|
|
formData.append('subpath', '{{ current_path }}');
|
|
|
|
const xhr = new XMLHttpRequest();
|
|
xhr.open('POST', '{{ url_for("upload_user_file", username=username) }}', true);
|
|
|
|
xhr.upload.onprogress = (e) => {
|
|
if (e.lengthComputable) {
|
|
const percentComplete = (e.loaded / e.total) * 100;
|
|
progressBar.style.width = percentComplete + '%';
|
|
progressBar.textContent = percentComplete.toFixed(2) + '%';
|
|
}
|
|
};
|
|
|
|
xhr.onload = function() {
|
|
if (xhr.status === 200) {
|
|
try {
|
|
const response = JSON.parse(xhr.responseText);
|
|
if (response.success) {
|
|
document.getElementById('fileResult').innerHTML += `File uploaded: ${file.name}<br>`;
|
|
addFileToList(file.name);
|
|
} else {
|
|
document.getElementById('fileResult').innerHTML += `Error: ${response.error}<br>`;
|
|
}
|
|
} catch (error) {
|
|
console.error('Error parsing JSON:', error);
|
|
document.getElementById('fileResult').innerHTML += `File uploaded: ${file.name}<br>`;
|
|
addFileToList(file.name);
|
|
}
|
|
} else {
|
|
document.getElementById('fileResult').innerHTML += `Error: ${xhr.statusText}<br>`;
|
|
}
|
|
progressBar.style.width = '0%';
|
|
progressBar.textContent = '';
|
|
};
|
|
|
|
xhr.onerror = function() {
|
|
console.error('Error:', xhr.statusText);
|
|
document.getElementById('fileResult').innerHTML += `Error uploading file: ${xhr.statusText}<br>`;
|
|
progressBar.style.width = '0%';
|
|
progressBar.textContent = '';
|
|
};
|
|
|
|
xhr.send(formData);
|
|
}
|
|
|
|
function addFileToList(fileName) {
|
|
const fileList = document.querySelector('.file-list');
|
|
const newItem = document.createElement('li');
|
|
newItem.className = 'file-item';
|
|
newItem.innerHTML = `
|
|
<span class="file-icon">📄</span>
|
|
<span class="file-name">${fileName}</span>
|
|
<div class="dropdown">
|
|
<button class="dropbtn">•••</button>
|
|
<div class="dropdown-content">
|
|
<a href="#" onclick="showModal('rename', '${fileName}', 'file')">Rename</a>
|
|
<a href="#" onclick="showModal('move', '${fileName}', 'file')">Move</a>
|
|
<a href="#" onclick="showModal('copy', '${fileName}', 'file')">Copy</a>
|
|
<a href="#" onclick="deleteItem('${fileName}', 'file')">Delete</a>
|
|
<a href="{{ url_for('edit_file', username=username, filename='') }}${fileName}">Edit</a>
|
|
</div>
|
|
</div>
|
|
`;
|
|
fileList.appendChild(newItem);
|
|
}
|
|
|
|
// Close dropdowns when clicking outside
|
|
window.onclick = function(event) {
|
|
if (!event.target.matches('.dropbtn')) {
|
|
var dropdowns = document.getElementsByClassName("dropdown-content");
|
|
for (var i = 0; i < dropdowns.length; i++) {
|
|
var openDropdown = dropdowns[i];
|
|
if (openDropdown.style.display === "block") {
|
|
openDropdown.style.display = "none";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const dropdowns = document.querySelectorAll('.dropdown');
|
|
|
|
dropdowns.forEach(dropdown => {
|
|
const dropbtn = dropdown.querySelector('.dropbtn');
|
|
const dropdownContent = dropdown.querySelector('.dropdown-content');
|
|
|
|
dropbtn.addEventListener('click', (e) => {
|
|
e.stopPropagation();
|
|
dropdownContent.style.display = dropdownContent.style.display === 'block' ? 'none' : 'block';
|
|
});
|
|
|
|
document.addEventListener('click', (e) => {
|
|
if (!dropdown.contains(e.target)) {
|
|
dropdownContent.style.display = 'none';
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
function showResetApiKeyModal() {
|
|
document.getElementById('resetApiKeyModal').style.display = 'block';
|
|
}
|
|
|
|
function closeResetApiKeyModal() {
|
|
document.getElementById('resetApiKeyModal').style.display = 'none';
|
|
}
|
|
|
|
function resetApiKey() {
|
|
fetch('/reset_api_key', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
document.getElementById('apiKey').textContent = data.new_api_key;
|
|
alert('API Key has been reset. Please update your applications and download a new ShareX configuration.');
|
|
} else {
|
|
alert('Error resetting API Key: ' + data.error);
|
|
}
|
|
closeResetApiKeyModal();
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert('An error occurred while resetting the API Key');
|
|
closeResetApiKeyModal();
|
|
});
|
|
}
|
|
</script>
|
|
</body>
|
|
</html> |