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>
43 lines
2.7 KiB
HTML
43 lines
2.7 KiB
HTML
{% 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 %}
|