diff --git a/app/static/css/browser.css b/app/static/css/browser.css new file mode 100644 index 0000000..5dc38c6 --- /dev/null +++ b/app/static/css/browser.css @@ -0,0 +1,401 @@ +/* File Browser Styles */ +.browser-container { + background: var(--card-bg); + border-radius: var(--border-radius-md); + box-shadow: var(--shadow-md); + padding: 1.5rem; + margin-bottom: 2rem; +} + +.browser-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1.5rem; +} + +.browser-actions { + display: flex; + gap: 0.5rem; + align-items: center; +} + +.view-toggle { + display: flex; + border: 1px solid var(--border-color); + border-radius: var(--border-radius-sm); + overflow: hidden; + margin-left: 0.5rem; +} + +.view-btn { + background: var(--card-bg); + border: none; + padding: 0.5rem 0.75rem; + cursor: pointer; + transition: all 0.2s ease; +} + +.view-btn:hover { + background: var(--bg-hover); +} + +.view-btn.active { + background: var(--primary-color); + color: white; +} + +.breadcrumbs { + display: flex; + flex-wrap: wrap; + align-items: center; + margin-bottom: 1.5rem; + padding: 0.75rem; + background: var(--bg-alt); + border-radius: var(--border-radius-sm); +} + +.breadcrumb-item { + color: var(--text-color); + text-decoration: none; + padding: 0.25rem 0.5rem; + border-radius: var(--border-radius-sm); + transition: background 0.2s ease; +} + +.breadcrumb-item:hover { + background: var(--bg-hover); +} + +.breadcrumb-separator { + margin: 0 0.25rem; + color: var(--text-muted); +} + +.loading-spinner { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 3rem; + color: var(--text-muted); +} + +.loading-spinner i { + font-size: 2rem; + margin-bottom: 1rem; +} + +.files-grid { + display: grid; + gap: 1rem; +} + +.grid-view { + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); +} + +.list-view { + grid-template-columns: 1fr; +} + +.folder-item, +.file-item { + display: flex; + flex-direction: column; + text-decoration: none; + color: var(--text-color); + background: var(--bg-alt); + border-radius: var(--border-radius-sm); + transition: all 0.2s ease; + overflow: hidden; + position: relative; +} + +.list-view .folder-item, +.list-view .file-item { + flex-direction: row; + align-items: center; + padding: 0.75rem; +} + +.folder-item:hover, +.file-item:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-md); +} + +.item-icon { + display: flex; + align-items: center; + justify-content: center; + font-size: 2.5rem; + padding: 1.5rem 0; + background: var(--card-bg); +} + +.list-view .item-icon { + font-size: 1.5rem; + padding: 0.5rem; + margin-right: 1rem; + background: none; +} + +.folder-item .item-icon { + color: var(--folder-color, #f8d775); +} + +.item-info { + padding: 0.75rem; + flex: 1; +} + +.item-name { + font-weight: 500; + margin-bottom: 0.25rem; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.item-details { + display: flex; + justify-content: space-between; + font-size: 0.8rem; + color: var(--text-muted); +} + +.empty-folder { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 4rem 1rem; + text-align: center; + color: var(--text-muted); +} + +.empty-icon { + font-size: 4rem; + margin-bottom: 1.5rem; + opacity: 0.5; +} + +.empty-message h3 { + margin-bottom: 0.5rem; +} + +/* Modal Styles */ +.modal { + display: none; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + z-index: 1000; + overflow-y: auto; + animation: fadeIn 0.3s ease; +} + +.modal.active { + display: flex; + align-items: center; + justify-content: center; +} + +.modal-content { + background: var(--card-bg); + border-radius: var(--border-radius-md); + box-shadow: var(--shadow-lg); + width: 90%; + max-width: 500px; + max-height: 90vh; + overflow-y: auto; + position: relative; + animation: modalIn 0.3s ease; +} + +.modal-lg { + max-width: 800px; +} + +.modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1.25rem 1.5rem; + border-bottom: 1px solid var(--border-color); +} + +.modal-close { + background: none; + border: none; + font-size: 1.5rem; + cursor: pointer; + color: var(--text-muted); + transition: color 0.2s ease; +} + +.modal-close:hover { + color: var(--text-color); +} + +.modal-body { + padding: 1.5rem; +} + +.modal-footer { + padding: 1.25rem 1.5rem; + border-top: 1px solid var(--border-color); + display: flex; + justify-content: space-between; + align-items: center; +} + +/* File Preview Styles */ +.image-preview, +.pdf-preview, +.video-preview { + display: flex; + justify-content: center; + align-items: center; + max-height: 60vh; + overflow: hidden; + border-radius: var(--border-radius-sm); +} + +.image-preview img { + max-width: 100%; + max-height: 60vh; + object-fit: contain; +} + +.pdf-preview iframe, +.video-preview video { + width: 100%; + height: 60vh; + border: none; +} + +.audio-preview { + display: flex; + justify-content: center; + padding: 2rem 0; +} + +.text-preview { + max-height: 60vh; + overflow: auto; + background: var(--code-bg); + border-radius: var(--border-radius-sm); +} + +.text-preview pre { + margin: 0; + padding: 1rem; + white-space: pre-wrap; + word-wrap: break-word; + font-family: monospace; +} + +.file-details { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.detail-item { + display: flex; + align-items: baseline; +} + +.detail-label { + font-weight: 500; + min-width: 70px; +} + +.no-preview { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 4rem 2rem; + text-align: center; + color: var(--text-muted); +} + +.no-preview i { + font-size: 4rem; + margin-bottom: 1.5rem; + opacity: 0.5; +} + +.error-message { + color: var(--error-color); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 3rem 2rem; + text-align: center; +} + +.error-message i { + font-size: 3rem; + margin-bottom: 1rem; +} + +/* Animations */ +@keyframes fadeIn { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@keyframes modalIn { + from { + opacity: 0; + transform: translateY(-20px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +.fade-out { + animation: fadeOut 0.3s forwards; +} + +@keyframes fadeOut { + from { + opacity: 1; + } + + to { + opacity: 0; + } +} + +/* Responsive Adjustments */ +@media (max-width: 768px) { + .grid-view { + grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); + } + + .browser-header { + flex-direction: column; + align-items: flex-start; + } + + .browser-actions { + margin-top: 1rem; + } +} \ No newline at end of file diff --git a/app/templates/base.html b/app/templates/base.html index 08bde10..4f367fe 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -17,40 +17,33 @@ {% block extra_css %}{% endblock %} + {% block extra_js %}{% endblock %} @@ -73,7 +66,7 @@
  • Login
  • {% endif %}
  • -
  • diff --git a/app/templates/files/browser.html b/app/templates/files/browser.html index 6413689..a7bf541 100644 --- a/app/templates/files/browser.html +++ b/app/templates/files/browser.html @@ -176,6 +176,51 @@ if (emptyNewFolderBtn) { emptyNewFolderBtn.addEventListener('click', showNewFolderPrompt); } + + // Setup dismiss + const closeBtn = alert.querySelector('.close'); + closeBtn.addEventListener('click', function () { + alert.classList.add('fade-out'); + setTimeout(() => { + alert.remove(); + }, 300); + }); + + // Auto dismiss + setTimeout(() => { + if (alert.parentNode) { + alert.classList.add('fade-out'); + setTimeout(() => { + if (alert.parentNode) { + alert.remove(); + } + }, 300); + } + }, 5000); }); + + // Helper functions + function formatSize(bytes) { + if (bytes === 0) return '0 Bytes'; + const k = 1024; + const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; + } + + function formatDate(dateString) { + if (!dateString) return 'Unknown'; + const date = new Date(dateString); + return date.toLocaleString(); + } + + function escapeHtml(unsafe) { + return unsafe + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); + } {% endblock %} \ No newline at end of file diff --git a/app/templates/files/partials/folder_contents.html b/app/templates/files/partials/folder_contents.html new file mode 100644 index 0000000..5119c96 --- /dev/null +++ b/app/templates/files/partials/folder_contents.html @@ -0,0 +1,47 @@ +{% if folders or files %} +
    + {% if folders %} + {% for folder in folders %} + +
    + +
    +
    +
    {{ folder.name }}
    +
    + {{ folder.files.count() }} items + {{ folder.created_at.strftime('%Y-%m-%d') }} +
    +
    +
    + {% endfor %} + {% endif %} + + {% if files %} + {% for file in files %} + +
    + +
    +
    +
    {{ file.name }}
    +
    + {{ format_size(file.size) }} + {{ file.created_at.strftime('%Y-%m-%d') }} +
    +
    +
    + {% endfor %} + {% endif %} +
    +{% else %} +
    +
    + +
    +
    +

    This folder is empty

    +

    Upload files or create a folder to get started

    +
    +
    +{% endif %} \ No newline at end of file diff --git a/app/templates/files/upload.html b/app/templates/files/upload.html index e410377..b49d0fc 100644 --- a/app/templates/files/upload.html +++ b/app/templates/files/upload.html @@ -8,133 +8,556 @@ {% block content %}
    -

    Upload Files

    - -
    - - -
    - -
    -

    - Uploading to: +

    +

    Upload Files

    +
    + Uploading to: {% if parent_folder %} {{ parent_folder.name }} {% else %} Root {% endif %} -

    +
    -
    -
    - - -
    - -

    Drag & drop files here to start uploading

    -

    or

    +
    +
    + +
    +
    +

    Drag & drop files or folders here

    +

    or

    +
    -
    - -
    -

    Upload Progress

    -
    -
    - Overall Progress - 0% -
    -
    -
    -
    -
    -
    -
    - Speed: - 0 KB/s -
    -
    - Uploaded: - 0 KB / 0 KB -
    -
    - Remaining: - calculating... -
    -
    -
    - -
    -

    Files

    -
    -
    - - - -
    - -
    -
    - - -
    - -

    Select a folder to upload

    -

    (Some browsers may not fully support folder drag & drop)

    -
    +

    Files will upload automatically when dropped or selected

    +
    +
    -
    -

    Upload Progress

    -
    -
    - Overall Progress - 0% -
    -
    -
    -
    -
    -
    -
    - Speed: - 0 KB/s -
    -
    - Uploaded: - 0 KB / 0 KB -
    -
    - Remaining: - calculating... -
    -
    +
    {% endblock %} {% block extra_js %} - + {% endblock %} \ No newline at end of file