fix: side peek des bases repasse en vanilla JS + largeur 1100px standard (v7.49.0)
FlowDeck CI / test (push) Failing after 3h13m58s
FlowDeck CI / lint (push) Successful in 2m12s
FlowDeck CI / docker (push) Skipped

- Panneau peek: les bindings Alpine (x-data absent du conteneur) rendaient
  loovverture et le redimensionnement inoperants -> cblage direct sur le document.
- Helper unique window.fdWirePeekResize (app.js): pointer capture, 300px-90vw,
  clic=fermer, largeur persiste fd_peek_width partagee entre les 4 peeks.
- database-table-container margin:0 (tableau colle a gauche, marge Library).
- .lib-container remonte dans app.css (trash etait pleine largeur), .db-index 1100px.
- ObsiGate verifie sans code: creation .xlsx OK (openpyxl, #186).
This commit is contained in:
2026-10-05 22:47:36 -04:00
parent 894004a1f5
commit 1d1cdbd618
63 changed files with 9473 additions and 393 deletions
+68
View File
@@ -9,7 +9,9 @@ See ``docs/V71_Calendar_Meetings.md``.
"""
from __future__ import annotations
import json
import secrets
from datetime import UTC, date, datetime, timedelta
from fastapi import APIRouter, Body, HTTPException, Request
from fastapi.responses import JSONResponse
@@ -115,6 +117,72 @@ def freebusy(collection_id: int, request: Request):
return out
# ── upcoming (sidebar "Meeting" tab) ────────────────────────────────────────
@router.get("/api/v2/meetings/upcoming")
def upcoming_meetings(request: Request, days: int = 30):
"""Upcoming calendar events for the sidebar Meeting tab.
Reads every calendar collection linked to the current user, extracts the
date property of each linked row and returns the ones falling in the next
``days`` days (today included), sorted chronologically. Rows imported from
Google/CalDAV carry an ``external_event_id`` and are flagged ``synced``.
"""
user = _auth_user(request)
horizon = max(1, min(days, 365))
today = datetime.now(UTC).date()
end = today + timedelta(days=horizon)
events: list[dict] = []
with get_conn() as conn:
links = conn.execute(
"SELECT id, collection_id, date_property, calendar_id, provider "
"FROM calendar_links WHERE user_id=? ORDER BY id",
(user["id"],),
).fetchall()
for link in links:
collection_id = link["collection_id"]
if not collection_id:
continue
date_prop = cal.date_prop_id(conn, collection_id,
link["date_property"] or "")
if not date_prop:
continue
prop_id, prop_name = date_prop
rows = conn.execute(
"SELECT id, title, property_values_json, external_event_id "
"FROM collection_pages WHERE collection_id=?",
(collection_id,),
).fetchall()
for row in rows:
try:
values = json.loads(row["property_values_json"] or "{}")
except (TypeError, ValueError):
continue
raw = cal.row_date(values, prop_id, prop_name)[:10]
if len(raw) != 10:
continue
try:
day = date.fromisoformat(raw)
except ValueError:
continue
if not (today <= day <= end):
continue
events.append({
"id": row["id"],
"title": row["title"] or "Untitled",
"date": raw,
"today": day == today,
"collection_id": collection_id,
"calendar_id": link["calendar_id"] or "primary",
"provider": link["provider"],
"synced": bool(row["external_event_id"]),
"url": f"/db/{collection_id}",
})
events.sort(key=lambda e: (e["date"], e["title"].lower()))
return {"today": today.isoformat(), "days": horizon,
"events": events[:200], "count": len(events)}
# ── meetings ───────────────────────────────────────────────────────────────
@router.post("/api/v2/meetings/transcribe")