diff --git a/app/routers/dashboard.py b/app/routers/dashboard.py index b03f4c6..922afda 100644 --- a/app/routers/dashboard.py +++ b/app/routers/dashboard.py @@ -454,3 +454,82 @@ async def remove_member(request: Request, ws_id: int, user_id: int): ) conn.commit() return {"status": "ok"} + + +# ═══════════ Local Workspace (file/folder CRUD) ═══════════ + +@router.get("/local-workspace", response_class=HTMLResponse) +async def local_workspace_page(request: Request): + """Local workspace page with file/folder tree.""" + from jinja2 import Environment, FileSystemLoader + env = Environment(loader=FileSystemLoader("app/templates")) + sidebar = _sidebar_data(request, []) + user = SessionManager.decode_session(request.cookies.get("flowdeck_session", "")) + if not user: + return RedirectResponse("/auth/login?provider=local", status_code=302) + + with get_conn() as conn: + rows = conn.execute( + "SELECT id, title FROM pages WHERE parent_id IS NULL ORDER BY created_at DESC" + ).fetchall() + items = [{"id": r["id"], "name": r["title"] or "Untitled", "type": "page"} for r in rows] + + ctx = {**sidebar, "user": user, "workspace_name": "My Workspace", "items": items} + template = env.get_template("local_workspace.html") + return template.render(**ctx) + + +@router.get("/api/local-workspace/tree") +async def local_workspace_tree(request: Request): + """Return the file/folder tree.""" + with get_conn() as conn: + roots = conn.execute( + "SELECT id, title FROM pages WHERE parent_id IS NULL ORDER BY created_at DESC" + ).fetchall() + tree = [] + for r in roots: + with get_conn() as conn: + children = conn.execute( + "SELECT id, title FROM pages WHERE parent_id=? ORDER BY created_at", (r["id"],) + ).fetchall() + item = {"id": r["id"], "name": r["title"] or "Untitled", "type": "page", + "children": [{"id": c["id"], "name": c["title"] or "Untitled", "type": "page"} for c in children]} + tree.append(item) + return {"tree": tree} + + +@router.post("/api/local-workspace/items") +async def create_local_workspace_item(request: Request): + """Create a new file.""" + import json + body = await request.json() + name = body.get("name", "Untitled").strip() + with get_conn() as conn: + cursor = conn.execute( + "INSERT INTO pages (workspace, title, content, content_format, parent_section) VALUES ('', ?, '', 'blocks', 'Private')", + (name,), + ) + conn.commit() + pid = cursor.lastrowid + return {"id": pid, "name": name, "type": "page"} + + +@router.put("/api/local-workspace/items/{item_id:int}") +async def rename_local_workspace_item(request: Request, item_id: int): + """Rename a file.""" + import json + body = await request.json() + name = body.get("name", "Untitled").strip() + with get_conn() as conn: + conn.execute("UPDATE pages SET title=? WHERE id=?", (name, item_id)) + conn.commit() + return {"status": "ok"} + + +@router.delete("/api/local-workspace/items/{item_id:int}") +async def delete_local_workspace_item(request: Request, item_id: int): + """Delete a file (and its children).""" + with get_conn() as conn: + conn.execute("DELETE FROM pages WHERE id=? OR parent_id=?", (item_id, item_id)) + conn.commit() + return {"status": "ok"} diff --git a/app/templates/local_workspace.html b/app/templates/local_workspace.html new file mode 100644 index 0000000..b1a6f6e --- /dev/null +++ b/app/templates/local_workspace.html @@ -0,0 +1,159 @@ +{% extends "base.html" %} +{% block page_title %}My Workspace{% endblock %} +{% block page_icon %}📁{% endblock %} + +{% block topbar %} +
+
+ Workspace + {{ workspace_name }} +
+
+ +
+
+{% endblock %} + +{% block content %} + + +
+ +
+

📁 {{ workspace_name }}

+

{{ items | length }} item(s)

+
+ + +
+ + +
+ + +
+ +
+ + +
+
📁
+

Empty workspace

+

Create a new file or folder to get started

+
+ + +
+
+ +
+ + +{% endblock %}