diff --git a/app/app.py b/app/app.py index bcf98f6..1a6c410 100644 --- a/app/app.py +++ b/app/app.py @@ -531,6 +531,30 @@ def rename_file(): }) +# ── Vérification des conflits avant upload ─────────────────────────── + +@app.route("/check-upload", methods=["POST"]) +def check_upload(): + redir = _require_admin() + if redir: + return redir + + subpath = request.form.get("path", "").strip() + names = request.form.getlist("names") + + if subpath: + parts = Path(subpath).parts + if parts and (parts[0] in _HIDDEN or parts[0].startswith(".")): + abort(403) + + dest = _safe_path(subpath) if subpath else ASSETS_ROOT + if not dest.is_dir(): + abort(400) + + conflicts = [n for n in names if n and (dest / secure_filename(n)).exists()] + return jsonify({"conflicts": conflicts}) + + # ── Upload de fichiers ──────────────────────────────────────────────── @app.route("/upload", methods=["POST"]) diff --git a/app/static/app.css b/app/static/app.css index d888214..8a0be89 100644 --- a/app/static/app.css +++ b/app/static/app.css @@ -165,7 +165,10 @@ main { max-width: 1100px; margin: 2rem auto; padding: 0 1.5rem 3rem; display: fl /* ── Upload ───────────────────────────────────────────────────────── */ .upload-card h2 { margin-bottom: .8rem; } -.upload-conflict { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; margin-bottom: .8rem; } + +.conflict-panel { margin-top: .9rem; padding: 1rem 1.2rem; background: #fffbeb; border: 1px solid #fcd34d; border-radius: var(--radius); display: flex; flex-direction: column; gap: .7rem; } +.conflict-title { font-size: .88rem; color: #92400e; } +.conflict-actions { display: flex; align-items: center; gap: .8rem; } .drop-zone { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .5rem; border: 2px dashed var(--border); border-radius: var(--radius); padding: 2rem 1.5rem; cursor: pointer; background: var(--bg); transition: border-color .15s, background .15s; text-align: center; position: relative; margin-bottom: 1rem; } .drop-zone:hover, .drop-zone:focus-within { border-color: var(--blue); background: var(--blue-light); } .drop-zone input[type=file] { position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; height: 100%; } diff --git a/app/templates/browse.html b/app/templates/browse.html index 71210ef..523411c 100644 --- a/app/templates/browse.html +++ b/app/templates/browse.html @@ -120,26 +120,81 @@ -