diff --git a/pkg/server/posts_api.go b/pkg/server/posts_api.go index 29fa03b..2b4b8fc 100644 --- a/pkg/server/posts_api.go +++ b/pkg/server/posts_api.go @@ -48,6 +48,42 @@ func listPost(c *fiber.Ctx) error { }) } +func getPost(c *fiber.Ctx) error { + id, _ := c.ParamsInt("postId", 0) + take := c.QueryInt("take", 0) + offset := c.QueryInt("offset", 0) + + var post models.Post + if err := services.PreloadRelatedPost(database.C.Where(&models.Post{ + BaseModel: models.BaseModel{ID: uint(id)}, + })).First(&post).Error; err != nil { + return fiber.NewError(fiber.StatusNotFound, err.Error()) + } + + tx := database.C. + Where(&models.Post{ReplyID: &post.ID}). + Where("published_at <= ? OR published_at IS NULL", time.Now()). + Order("created_at desc") + + var count int64 + if err := tx. + Model(&models.Post{}). + Count(&count).Error; err != nil { + return fiber.NewError(fiber.StatusInternalServerError, err.Error()) + } + + posts, err := services.ListPost(tx, take, offset) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } + + return c.JSON(fiber.Map{ + "data": post, + "count": count, + "related": posts, + }) +} + func createPost(c *fiber.Ctx) error { user := c.Locals("principal").(models.Account) diff --git a/pkg/server/startup.go b/pkg/server/startup.go index 3bcfc5e..b8bc482 100644 --- a/pkg/server/startup.go +++ b/pkg/server/startup.go @@ -69,6 +69,7 @@ func NewServer() { api.Post("/attachments", auth, uploadAttachment) api.Get("/posts", listPost) + api.Get("/posts/:postId", getPost) api.Post("/posts", auth, createPost) api.Post("/posts/:postId/react/:reactType", auth, reactPost) api.Put("/posts/:postId", auth, editPost) diff --git a/pkg/view/src/components/PostItem.tsx b/pkg/view/src/components/PostItem.tsx index fa17504..7a5fef2 100644 --- a/pkg/view/src/components/PostItem.tsx +++ b/pkg/view/src/components/PostItem.tsx @@ -5,8 +5,10 @@ import { SolidMarkdown } from "solid-markdown"; export default function PostItem(props: { post: any, + noClick?: boolean, noAuthor?: boolean, noControl?: boolean, + noRelated?: boolean, onRepost?: (post: any) => void, onReply?: (post: any) => void, onEdit?: (post: any) => void, @@ -33,8 +35,8 @@ export default function PostItem(props: { setReacting(false); } - return ( -
+ const element = ( + <>
@@ -55,7 +57,6 @@ export default function PostItem(props: {
-

{props.post.title}

@@ -77,7 +78,7 @@ export default function PostItem(props: { - +

Reposted a post @@ -87,11 +88,10 @@ export default function PostItem(props: { noControl post={props.post.repost_to} onError={props.onError} - onReact={props.onReact} - /> + onReact={props.onReact} />

- +

Replied a post @@ -101,12 +101,10 @@ export default function PostItem(props: { noControl post={props.post.reply_to} onError={props.onError} - onReact={props.onReact} - /> + onReact={props.onReact} />

-
@@ -168,7 +166,20 @@ export default function PostItem(props: {
- - + ); + + if (props.noClick) { + return ( +
+ {element} +
+ ) + } else { + return ( + + {element} + + ); + } } \ No newline at end of file diff --git a/pkg/view/src/components/PostList.tsx b/pkg/view/src/components/PostList.tsx index 18a4909..e1581a9 100644 --- a/pkg/view/src/components/PostList.tsx +++ b/pkg/view/src/components/PostList.tsx @@ -5,6 +5,7 @@ import PostItem from "./PostItem.tsx"; import { getAtk } from "../stores/userinfo.tsx"; export default function PostList(props: { + noRelated?: boolean, info: { data: any[], count: number } | null, onRepost?: (post: any) => void, onReply?: (post: any) => void, @@ -58,6 +59,7 @@ export default function PostList(props: { {item => ( - import("./pages/realms.tsx"))} /> - import("./pages/realm.tsx"))} /> + + import("./pages/realms"))} /> + import("./pages/realms/realm.tsx"))} /> import("./pages/account.tsx"))} /> import("./pages/auth/callout.tsx"))} /> diff --git a/pkg/view/src/layouts/RootLayout.tsx b/pkg/view/src/layouts/RootLayout.tsx index 1d24999..fb5f9b7 100644 --- a/pkg/view/src/layouts/RootLayout.tsx +++ b/pkg/view/src/layouts/RootLayout.tsx @@ -2,7 +2,7 @@ import Navbar from "./shared/Navbar.tsx"; import { readProfiles, useUserinfo } from "../stores/userinfo.tsx"; import { createEffect, createMemo, createSignal, Show } from "solid-js"; import { readWellKnown } from "../stores/wellKnown.tsx"; -import { BeforeLeaveEventArgs, useBeforeLeave, useLocation, useNavigate, useSearchParams } from "@solidjs/router"; +import { BeforeLeaveEventArgs, useLocation, useNavigate, useSearchParams } from "@solidjs/router"; export default function RootLayout(props: any) { const [ready, setReady] = createSignal(false); @@ -17,21 +17,19 @@ export default function RootLayout(props: any) { createEffect(() => { if (ready()) { - keepGate(location.pathname); + keepGate(location.pathname + location.search); } }, [ready, userinfo]); function keepGate(path: string, e?: BeforeLeaveEventArgs) { - const whitelist = ["/auth", "/auth/callback"]; + const blacklist = ["/creator"]; - if (!userinfo?.isLoggedIn && !whitelist.includes(path)) { + if (!userinfo?.isLoggedIn && blacklist.includes(path)) { if (!e?.defaultPrevented) e?.preventDefault(); - navigate(`/auth/login?redirect_uri=${path}`); + navigate(`/auth?redirect_uri=${path}`); } } - useBeforeLeave((e: BeforeLeaveEventArgs) => keepGate(e.to.toString().split("?")[0], e)); - const mainContentStyles = createMemo(() => { if(!searchParams["noTitle"]) { return "h-[calc(100vh-64px)] mt-[64px]" diff --git a/pkg/view/src/pages/account.tsx b/pkg/view/src/pages/account.tsx index 9caea93..48e3ebf 100644 --- a/pkg/view/src/pages/account.tsx +++ b/pkg/view/src/pages/account.tsx @@ -7,7 +7,7 @@ import PostPublish from "../components/PostPublish.tsx"; import { createStore } from "solid-js/store"; import { closeModel, openModel } from "../scripts/modals.ts"; -export default function DashboardPage() { +export default function AccountPage() { const [error, setError] = createSignal(null); const [page, setPage] = createSignal(0); diff --git a/pkg/view/src/pages/post.tsx b/pkg/view/src/pages/post.tsx new file mode 100644 index 0000000..e0fc276 --- /dev/null +++ b/pkg/view/src/pages/post.tsx @@ -0,0 +1,132 @@ +import { createSignal, Show } from "solid-js"; +import { useNavigate, useParams } from "@solidjs/router"; +import { createStore } from "solid-js/store"; +import { closeModel, openModel } from "../scripts/modals.ts"; +import PostPublish from "../components/PostPublish.tsx"; +import PostList from "../components/PostList.tsx"; +import PostItem from "../components/PostItem.tsx"; + +export default function PostPage() { + const [error, setError] = createSignal(null); + + const [page, setPage] = createSignal(0); + const [related, setRelated] = createSignal(null); + const [info, setInfo] = createSignal(null); + + const params = useParams(); + const navigate = useNavigate(); + + async function readPost(pn?: number) { + if (pn) setPage(pn); + const res = await fetch(`/api/posts/${params["postId"]}?` + new URLSearchParams({ + take: (10).toString(), + offset: ((page() - 1) * 10).toString() + })); + if (res.status !== 200) { + setError(await res.text()); + } else { + setError(null); + const data = await res.json(); + setInfo(data["data"]); + setRelated({ + count: data["count"], + data: data["related"] + }); + } + } + + readPost(); + + function setMeta(data: any, field: string, open = true) { + const meta: { [id: string]: any } = { + reposting: null, + replying: null, + editing: null + }; + meta[field] = data; + setPublishMeta(meta); + + if (open) openModel("#post-publish"); + else closeModel("#post-publish"); + } + + const [publishMeta, setPublishMeta] = createStore({ + replying: null, + reposting: null, + editing: null + }); + + function back() { + if (window.history.length > 0) { + window.history.back(); + } else { + navigate("/"); + } + } + + return ( + <> +
+ + + +
+ +
+ +
+

Post #{info()?.id}

+
+
+ + + + + + +

+

Creating fake news...

+ + }> + setMeta(item, "reposting")} + onReply={(item) => setMeta(item, "replying")} + onEdit={(item) => setMeta(item, "editing")} + /> + + setMeta(item, "reposting")} + onReply={(item) => setMeta(item, "replying")} + onEdit={(item) => setMeta(item, "editing")} + /> +
+ + ); +} \ No newline at end of file diff --git a/pkg/view/src/pages/realms.tsx b/pkg/view/src/pages/realms/index.tsx similarity index 100% rename from pkg/view/src/pages/realms.tsx rename to pkg/view/src/pages/realms/index.tsx diff --git a/pkg/view/src/pages/realm.module.css b/pkg/view/src/pages/realms/realm.module.css similarity index 100% rename from pkg/view/src/pages/realm.module.css rename to pkg/view/src/pages/realms/realm.module.css diff --git a/pkg/view/src/pages/realm.tsx b/pkg/view/src/pages/realms/realm.tsx similarity index 96% rename from pkg/view/src/pages/realm.tsx rename to pkg/view/src/pages/realms/realm.tsx index 4bf0e1d..2492c00 100644 --- a/pkg/view/src/pages/realm.tsx +++ b/pkg/view/src/pages/realms/realm.tsx @@ -2,8 +2,8 @@ import { createSignal, Show } from "solid-js"; import { createStore } from "solid-js/store"; import { useParams } from "@solidjs/router"; -import PostList from "../components/PostList.tsx"; -import PostPublish from "../components/PostPublish.tsx"; +import PostList from "../../components/PostList.tsx"; +import PostPublish from "../../components/PostPublish.tsx"; import styles from "./realm.module.css";