Spaces:
Sleeping
Sleeping
Commit ·
4044a32
1
Parent(s): ccdda22
chore: remove who-saved user label (shared credentials make it meaningless)
Browse files
main.py
CHANGED
|
@@ -1730,24 +1730,6 @@ async def latest_questions_page(courseId: int, chapterId: Optional[int] = None,
|
|
| 1730 |
)
|
| 1731 |
questions = questions[:limit]
|
| 1732 |
|
| 1733 |
-
# Fetch the logged-in user's profile to resolve their name
|
| 1734 |
-
known_users: dict[int, str] = {}
|
| 1735 |
-
try:
|
| 1736 |
-
async with httpx.AsyncClient() as _mc:
|
| 1737 |
-
_mr = await _mc.get(
|
| 1738 |
-
f"{EDUVERSE_API_URL}/api/auth/me",
|
| 1739 |
-
headers={"Authorization": f"Bearer {token}"},
|
| 1740 |
-
timeout=10,
|
| 1741 |
-
)
|
| 1742 |
-
if _mr.status_code == 200:
|
| 1743 |
-
_md = _mr.json()
|
| 1744 |
-
_uid = int(_md.get("userId") or 0)
|
| 1745 |
-
_name = f"{_md.get('firstName', '')} {_md.get('lastName', '')}".strip()
|
| 1746 |
-
if _uid and _name:
|
| 1747 |
-
known_users[_uid] = _name
|
| 1748 |
-
except Exception:
|
| 1749 |
-
pass
|
| 1750 |
-
|
| 1751 |
# Duplicate detection
|
| 1752 |
dup_groups: dict[str, list[dict]] = defaultdict(list)
|
| 1753 |
for q in questions:
|
|
@@ -1757,23 +1739,23 @@ async def latest_questions_page(courseId: int, chapterId: Optional[int] = None,
|
|
| 1757 |
dups = {k: v for k, v in dup_groups.items() if len(v) > 1}
|
| 1758 |
dup_ids: set[int] = {q.get("id") for items in dups.values() for q in items}
|
| 1759 |
|
| 1760 |
-
# Group by save-minute (YYYY-MM-DD HH:MM)
|
| 1761 |
def minute_key(q):
|
| 1762 |
raw = q.get("createdAt") or ""
|
| 1763 |
if not raw:
|
| 1764 |
-
return
|
| 1765 |
try:
|
| 1766 |
iso = raw[:-1] + "+00:00" if raw.endswith("Z") else raw
|
| 1767 |
d = _dt.fromisoformat(iso)
|
| 1768 |
-
return
|
| 1769 |
except Exception:
|
| 1770 |
-
return
|
| 1771 |
|
| 1772 |
-
batches: dict[
|
| 1773 |
for q in questions:
|
| 1774 |
batches[minute_key(q)].append(q)
|
| 1775 |
# Sort batches newest first
|
| 1776 |
-
sorted_batches = sorted(batches.items(), key=lambda kv: kv[0]
|
| 1777 |
|
| 1778 |
def fmt_date(s):
|
| 1779 |
if not s:
|
|
@@ -1786,14 +1768,13 @@ async def latest_questions_page(courseId: int, chapterId: Optional[int] = None,
|
|
| 1786 |
return str(s)
|
| 1787 |
|
| 1788 |
def fmt_minute(key):
|
| 1789 |
-
|
| 1790 |
-
if ts == "~no-date":
|
| 1791 |
return "Unknown time"
|
| 1792 |
try:
|
| 1793 |
-
d = _dt.strptime(
|
| 1794 |
return d.strftime("%Y-%m-%d %I:%M %p") + " UTC"
|
| 1795 |
except Exception:
|
| 1796 |
-
return
|
| 1797 |
|
| 1798 |
def trunc(s, n=240):
|
| 1799 |
s = s or ""
|
|
@@ -1820,17 +1801,9 @@ async def latest_questions_page(courseId: int, chapterId: Optional[int] = None,
|
|
| 1820 |
c = {"approved": "badge-green", "draft": "badge-gray", "rejected": "badge-red"}.get(v.lower(), "badge-gray")
|
| 1821 |
return f'<span class="badge {c}">{html.escape(v)}</span>' if v else '<span class="muted">—</span>'
|
| 1822 |
|
| 1823 |
-
def user_label(uid):
|
| 1824 |
-
uid = int(uid) if uid else 0
|
| 1825 |
-
name = known_users.get(uid)
|
| 1826 |
-
if name:
|
| 1827 |
-
return f'<span class="badge badge-blue">{html.escape(name)}</span>'
|
| 1828 |
-
return f'<span class="badge badge-gray">User #{uid}</span>' if uid else '<span class="muted">—</span>'
|
| 1829 |
-
|
| 1830 |
# Build batch HTML
|
| 1831 |
batches_html_parts = []
|
| 1832 |
for key, qs in sorted_batches:
|
| 1833 |
-
_, by_id = key
|
| 1834 |
q_rows = "".join(
|
| 1835 |
f"<tr{' class=\"dup-row\"' if q.get('id') in dup_ids else ''}>"
|
| 1836 |
f"<td><span class='badge badge-gray'>{q.get('id')}</span>{'<span class=\"dup-marker\" title=\"Duplicate\">⚠</span>' if q.get('id') in dup_ids else ''}</td>"
|
|
@@ -1853,9 +1826,6 @@ async def latest_questions_page(courseId: int, chapterId: Optional[int] = None,
|
|
| 1853 |
<i data-lucide="clock" style="width:13px;height:13px;flex-shrink:0;"></i>
|
| 1854 |
<span class="batch-time">{html.escape(fmt_minute(key))}</span>
|
| 1855 |
<span class="batch-sep">—</span>
|
| 1856 |
-
<i data-lucide="user" style="width:13px;height:13px;flex-shrink:0;"></i>
|
| 1857 |
-
{user_label(by_id)}
|
| 1858 |
-
<span class="batch-sep">—</span>
|
| 1859 |
<span class="badge badge-gray">{len(qs)} question{'s' if len(qs) != 1 else ''}</span>
|
| 1860 |
{dup_warn}
|
| 1861 |
</div>
|
|
|
|
| 1730 |
)
|
| 1731 |
questions = questions[:limit]
|
| 1732 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1733 |
# Duplicate detection
|
| 1734 |
dup_groups: dict[str, list[dict]] = defaultdict(list)
|
| 1735 |
for q in questions:
|
|
|
|
| 1739 |
dups = {k: v for k, v in dup_groups.items() if len(v) > 1}
|
| 1740 |
dup_ids: set[int] = {q.get("id") for items in dups.values() for q in items}
|
| 1741 |
|
| 1742 |
+
# Group by save-minute (YYYY-MM-DD HH:MM)
|
| 1743 |
def minute_key(q):
|
| 1744 |
raw = q.get("createdAt") or ""
|
| 1745 |
if not raw:
|
| 1746 |
+
return "~no-date"
|
| 1747 |
try:
|
| 1748 |
iso = raw[:-1] + "+00:00" if raw.endswith("Z") else raw
|
| 1749 |
d = _dt.fromisoformat(iso)
|
| 1750 |
+
return d.strftime("%Y-%m-%d %H:%M")
|
| 1751 |
except Exception:
|
| 1752 |
+
return "~no-date"
|
| 1753 |
|
| 1754 |
+
batches: dict[str, list[dict]] = defaultdict(list)
|
| 1755 |
for q in questions:
|
| 1756 |
batches[minute_key(q)].append(q)
|
| 1757 |
# Sort batches newest first
|
| 1758 |
+
sorted_batches = sorted(batches.items(), key=lambda kv: kv[0], reverse=True)
|
| 1759 |
|
| 1760 |
def fmt_date(s):
|
| 1761 |
if not s:
|
|
|
|
| 1768 |
return str(s)
|
| 1769 |
|
| 1770 |
def fmt_minute(key):
|
| 1771 |
+
if key == "~no-date":
|
|
|
|
| 1772 |
return "Unknown time"
|
| 1773 |
try:
|
| 1774 |
+
d = _dt.strptime(key, "%Y-%m-%d %H:%M")
|
| 1775 |
return d.strftime("%Y-%m-%d %I:%M %p") + " UTC"
|
| 1776 |
except Exception:
|
| 1777 |
+
return key
|
| 1778 |
|
| 1779 |
def trunc(s, n=240):
|
| 1780 |
s = s or ""
|
|
|
|
| 1801 |
c = {"approved": "badge-green", "draft": "badge-gray", "rejected": "badge-red"}.get(v.lower(), "badge-gray")
|
| 1802 |
return f'<span class="badge {c}">{html.escape(v)}</span>' if v else '<span class="muted">—</span>'
|
| 1803 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1804 |
# Build batch HTML
|
| 1805 |
batches_html_parts = []
|
| 1806 |
for key, qs in sorted_batches:
|
|
|
|
| 1807 |
q_rows = "".join(
|
| 1808 |
f"<tr{' class=\"dup-row\"' if q.get('id') in dup_ids else ''}>"
|
| 1809 |
f"<td><span class='badge badge-gray'>{q.get('id')}</span>{'<span class=\"dup-marker\" title=\"Duplicate\">⚠</span>' if q.get('id') in dup_ids else ''}</td>"
|
|
|
|
| 1826 |
<i data-lucide="clock" style="width:13px;height:13px;flex-shrink:0;"></i>
|
| 1827 |
<span class="batch-time">{html.escape(fmt_minute(key))}</span>
|
| 1828 |
<span class="batch-sep">—</span>
|
|
|
|
|
|
|
|
|
|
| 1829 |
<span class="badge badge-gray">{len(qs)} question{'s' if len(qs) != 1 else ''}</span>
|
| 1830 |
{dup_warn}
|
| 1831 |
</div>
|