diff --git a/app.py b/app.py index 2856a61..0aa513a 100644 --- a/app.py +++ b/app.py @@ -478,7 +478,8 @@ def dest_for(row, tx): return os.path.join(tx["organized_root"], "Projects", row["topic"], row["role"] or "Misc") return propose_destination(row, tx) -def apply_moves(ids, dry_run=True): +def apply_moves(ids, dry_run=True, overrides=None): + overrides = overrides or {} tx = load_taxonomy() c = db() session = uuid.uuid4().hex[:12] @@ -487,7 +488,13 @@ def apply_moves(ids, dry_run=True): row = c.execute("SELECT * FROM files WHERE id=?", (fid,)).fetchone() if not row or row["status"] not in ("classified", "approved"): skipped += 1; continue dst_dir = dest_for(row, tx) - name = row["rename"] or row["name"] + if fid in overrides: + ov = os.path.abspath(os.path.expanduser(overrides[fid])) + dst_dir = os.path.dirname(ov) if overrides[fid].endswith("/") or os.path.splitext(ov)[1] == "" else os.path.dirname(ov) + forced_name = os.path.basename(ov) if os.path.splitext(ov)[1] else None + else: + forced_name = None + name = forced_name or row["rename"] or row["name"] base, ext = os.path.splitext(name) if ext.lower() != row["ext"] and row["ext"]: name = base + row["ext"] @@ -747,43 +754,88 @@ def plan_page(): plans.sort(key=lambda p: (p.get("topic") or "zzz", -p["conf"], p["verdict"] != "APPROVE")) cards = "" approved_default = 0 + cur_topic = "zzz" for p in plans[:600]: + if (p.get("topic") or "zzz") != cur_topic: + cur_topic = p.get("topic") or "zzz" + if cur_topic != "zzz": + grp = [q for q in plans[:600] if q.get("topic") == cur_topic] + gids = ",".join(str(q["id"]) for q in grp) + cards += (f"
{len(plans)} proposals · {approved_default} auto-approved at this threshold. Uncheck anything you're unsure of — nothing moves without your click.
+{len(plans)} proposals · {approved_default} auto-approved at this threshold · destinations are click-to-edit (type a path, it wins over the default). Nothing moves without your click.