diff --git a/devplacepy/routers/projects/index.py b/devplacepy/routers/projects/index.py
index aac1fe21..ad434b25 100644
--- a/devplacepy/routers/projects/index.py
+++ b/devplacepy/routers/projects/index.py
@@ -6,6 +6,7 @@ from sqlalchemy import or_
from fastapi import Depends, APIRouter, Request
from devplacepy.models import ProjectForm, ProjectEditForm, ProjectFlagForm, ForkForm
from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
+from devplacepy.attachments import get_attachments_batch
from devplacepy.database import (
get_table,
get_users_by_uids,
@@ -13,6 +14,10 @@ from devplacepy.database import (
get_site_stats,
get_user_votes,
get_recent_comments_by_target_uids,
+ get_reactions_by_targets,
+ get_user_bookmarks,
+ get_polls_by_post_uids,
+ get_project_devlog,
paginate,
text_search_clause,
resolve_by_slug,
@@ -171,7 +176,7 @@ async def projects_page(
)
@router.get("/{project_slug}", response_class=HTMLResponse)
-async def project_detail(request: Request, project_slug: str):
+async def project_detail(request: Request, project_slug: str, before: str = None):
user = get_current_user(request)
detail = load_detail("projects", "project", project_slug, user)
if not detail:
@@ -216,6 +221,25 @@ async def project_detail(request: Request, project_slug: str):
if parent
else None
)
+
+ devlog_posts, devlog_next_cursor = get_project_devlog(
+ project["uid"], before=before, viewer=user
+ )
+ if devlog_posts:
+ post_uids = [item["post"]["uid"] for item in devlog_posts]
+ attachments_map = get_attachments_batch("post", post_uids)
+ reactions_map = get_reactions_by_targets("post", post_uids, user)
+ bookmark_set = (
+ get_user_bookmarks(user["uid"], "post", post_uids) if user else set()
+ )
+ polls_map = get_polls_by_post_uids(post_uids, user)
+ for item in devlog_posts:
+ uid = item["post"]["uid"]
+ item["attachments"] = attachments_map.get(uid, [])
+ item["reactions"] = reactions_map.get(uid, {"counts": {}, "mine": []})
+ item["bookmarked"] = uid in bookmark_set
+ item["poll"] = polls_map.get(uid)
+
return respond(
request,
"project_detail.html",
@@ -235,6 +259,8 @@ async def project_detail(request: Request, project_slug: str):
"forked_from": forked_from,
"fork_count": count_forks(project["uid"]),
"file_count": count_files(project["uid"]),
+ "devlog_posts": devlog_posts,
+ "devlog_next_cursor": devlog_next_cursor,
},
),
model=ProjectDetailOut,
@@ -464,3 +490,5 @@ async def set_project_readonly(
request: Request, project_slug: str, data: Annotated[ProjectFlagForm, Depends(json_or_form(ProjectFlagForm))]
):
return _set_project_flag(request, project_slug, "read_only", data.value)
+
+
diff --git a/devplacepy/schemas/listings.py b/devplacepy/schemas/listings.py
index b3b7f2a7..ecbab0b7 100644
--- a/devplacepy/schemas/listings.py
+++ b/devplacepy/schemas/listings.py
@@ -163,6 +163,8 @@ class ProjectDetailOut(_Out):
forked_from: Optional[dict] = None
fork_count: int = 0
file_count: int = 0
+ devlog_posts: list[FeedItemOut] = []
+ devlog_next_cursor: Optional[str] = None
class GistsOut(_Out):
@@ -232,3 +234,4 @@ class LeaderboardOut(_Out):
class SavedOut(_Out):
items: list[SavedItemOut] = []
next_cursor: Optional[str] = None
+
diff --git a/devplacepy/templates/project_detail.html b/devplacepy/templates/project_detail.html
index 2b57ad19..df14fe10 100644
--- a/devplacepy/templates/project_detail.html
+++ b/devplacepy/templates/project_detail.html
@@ -102,6 +102,22 @@
+ No devlog posts yet.Devlog
+ {% if devlog_posts %}
+ {% for item in devlog_posts %}
+ {% set _author = item.author %}{% set _time = item.time_ago %}{% set _show_share = false %}{% set _show_comment_form = false %}{% include "_post_card.html" %}
+ {% endfor %}
+ {% if devlog_next_cursor %}
+
+ {% endif %}
+ {% else %}
+