left4me/l4d2web/templates/_overlay_file_node.html
mwiegand 2d3c98866a
feat(files-overlay): user-managed file content as a third overlay type
Adds Overlay.type='files' whose source-of-truth IS the overlay directory
itself. Users can:

  * upload arbitrary files / whole folders by dragging from the OS onto a
    folder row in the file tree (one POST per file, queue with
    concurrency 3, per-file progress in a floating Uploads panel)
  * move via drag-and-drop inside the tree (same gesture, source
    distinguishes; refuses cycles)
  * create / edit / rename / replace through a single editor modal
    (text flavor for editable files, binary flavor with replace-upload
    for everything else; filename input is the rename surface)
  * mkdir empty folders (slashes allowed for nested intermediates)
  * stream a folder as a zip download
  * delete files and empty folders

Backend is type-agnostic past the new files_routes endpoints, so the
existing mount / spec / overlayfs / expose_server_cfg pipeline is reused
unchanged. is_editable gates the row's edit affordance and the /save
content rules. Three new safe-resolve helpers (write/delete/move) cover
the new operations with the same anchor-and-resolve pattern as listing
and download. FilesBuilder is a no-op so the build subsystem can
dispatch uniformly.

Spec: docs/superpowers/specs/2026-05-09-files-overlay-design.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 18:59:32 +02:00

43 lines
2.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% if entry.kind == 'dir' %}
<li class="file-tree-row file-tree-row-dir{% if files_overlay %} files-row{% endif %}"
{% if files_overlay %}draggable="true" data-target-path="{{ entry.rel }}" data-row-kind="dir"{% endif %}>
<button type="button"
class="file-tree-toggle"
aria-expanded="false"
data-files-url="{{ files_base_url }}/files?path={{ entry.rel|urlencode }}">
<span class="chevron" aria-hidden="true"></span>{{ entry.name }}/
</button>
{% if files_overlay %}
<span class="files-row-actions" aria-label="Folder actions">
<button type="button" class="files-row-action" data-action="new-file" data-target-path="{{ entry.rel }}" title="New file">+ file</button>
<button type="button" class="files-row-action" data-action="new-folder" data-target-path="{{ entry.rel }}" title="New folder">+ folder</button>
<button type="button" class="files-row-action" data-action="zip" data-target-path="{{ entry.rel }}" title="Download as zip">⬇ zip</button>
<button type="button" class="files-row-action files-row-danger" data-action="delete" data-target-path="{{ entry.rel }}" data-row-kind="dir" data-row-name="{{ entry.name }}" title="Delete folder"></button>
</span>
{% endif %}
<div class="file-tree-children" hidden></div>
</li>
{% else %}
<li class="file-tree-row file-tree-row-file{% if files_overlay %} files-row{% endif %}"
{% if files_overlay %}draggable="true" data-target-path="{{ entry.rel }}" data-row-kind="file" data-editable="{{ '1' if entry.editable else '0' }}"{% endif %}>
{% if entry.broken %}
<span>{{ entry.name }}</span>
<span class="file-tree-badge file-tree-badge-warn">broken link</span>
{% else %}
{% if download_supported %}
<a href="{{ files_base_url }}/files/download?path={{ entry.rel|urlencode }}">{{ entry.name }}</a>
{% else %}
<span>{{ entry.name }}</span>
{% endif %}
{% if entry.is_symlink %}<span class="file-tree-badge">link</span>{% endif %}
<span class="muted">{{ entry.size_human }}</span>
{% endif %}
{% if files_overlay and not entry.broken %}
<span class="files-row-actions" aria-label="File actions">
<button type="button" class="files-row-action" data-action="edit" data-target-path="{{ entry.rel }}" data-editable="{{ '1' if entry.editable else '0' }}" title="Edit">edit</button>
<a class="files-row-action" href="{{ files_base_url }}/files/download?path={{ entry.rel|urlencode }}" title="Download"></a>
<button type="button" class="files-row-action files-row-danger" data-action="delete" data-target-path="{{ entry.rel }}" data-row-kind="file" data-row-name="{{ entry.name }}" title="Delete"></button>
</span>
{% endif %}
</li>
{% endif %}