feat: Drag & Drop Upload mit Ordner-Unterstuetzung

Dateien und komplette Verzeichnisse koennen jetzt hochgeladen werden:

Drag & Drop:
- Dateien per Drag & Drop auf den Datei-Explorer ziehen
- Ganze Ordner (inkl. Unterordner) per Drag & Drop hochladen
- Visuelles Overlay zeigt Drop-Zone an
- Ordnerstruktur wird automatisch auf dem Server nachgebildet

Buttons:
- "Dateien" Button: Mehrere Dateien auswaehlen (wie vorher)
- "Ordner" Button: Kompletten Ordner mit Unterordnern hochladen
  (nutzt webkitdirectory API)

Upload-Fortschritt:
- Fortschrittsbalken mit Datei-Zaehler waehrend des Uploads
- Fehlerhafte Uploads werden gezaehlt und gemeldet

Backend: /files/ensure-path Endpunkt erstellt verschachtelte
Ordnerstrukturen (z.B. "Docs/Work/Project") in einem Aufruf

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Hacker
2026-04-11 18:17:39 +02:00
parent 10fde2396d
commit 61ce2ec244
2 changed files with 244 additions and 13 deletions
+40
View File
@@ -126,6 +126,46 @@ def create_folder():
return jsonify(folder.to_dict()), 201
def _ensure_folder_path(user_id, parent_id, path_parts):
"""Create nested folder structure. Returns the ID of the deepest folder."""
current_parent = parent_id
for part in path_parts:
part = part.strip()
if not part:
continue
existing = File.query.filter_by(
owner_id=user_id, parent_id=current_parent, name=part, is_folder=True
).first()
if existing:
current_parent = existing.id
else:
folder = File(owner_id=user_id, parent_id=current_parent, name=part, is_folder=True)
db.session.add(folder)
db.session.flush()
current_parent = folder.id
return current_parent
@api_bp.route('/files/ensure-path', methods=['POST'])
@token_required
def ensure_folder_path():
"""Create nested folder structure from a path string like 'Docs/Work/Project'.
Returns the ID of the deepest folder."""
user = request.current_user
data = request.get_json()
path = data.get('path', '').strip().strip('/')
parent_id = data.get('parent_id', None)
if not path:
return jsonify({'folder_id': parent_id}), 200
parts = [p for p in path.split('/') if p.strip()]
folder_id = _ensure_folder_path(user.id, parent_id, parts)
db.session.commit()
return jsonify({'folder_id': folder_id}), 200
# --- Upload ---
@api_bp.route('/files/upload', methods=['POST'])