server/client: add post deletion

This commit is contained in:
Max Leiter 2022-03-26 00:24:18 -07:00
parent 62bc7af004
commit 5ac73718cf
No known key found for this signature in database
GPG key ID: A3512F2F2F17EBDA
6 changed files with 50 additions and 54 deletions

View file

@ -11,6 +11,7 @@
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
margin-bottom: var(--gap);
} }
@media screen and (max-width: 650px) { @media screen and (max-width: 650px) {

View file

@ -6,7 +6,7 @@ import styles from './post-list.module.css'
import ListItemSkeleton from "./list-item-skeleton" import ListItemSkeleton from "./list-item-skeleton"
import ListItem from "./list-item" import ListItem from "./list-item"
import { Post } from "@lib/types" import { Post } from "@lib/types"
import { ChangeEvent, MouseEventHandler, useCallback, useEffect, useMemo, useState } from "react" import { ChangeEvent, useCallback, useEffect, useMemo, useState } from "react"
import debounce from "lodash.debounce" import debounce from "lodash.debounce"
import Cookies from "js-cookie" import Cookies from "js-cookie"
@ -36,9 +36,7 @@ const PostList = ({ morePosts, initialPosts, error }: Props) => {
} }
} }
) )
console.log(res)
const json = await res.json() const json = await res.json()
console.log(json)
setPosts([...posts, ...json.posts]) setPosts([...posts, ...json.posts])
setHasMorePosts(json.morePosts) setHasMorePosts(json.morePosts)
} }
@ -85,6 +83,23 @@ const PostList = ({ morePosts, initialPosts, error }: Props) => {
} }
}, [debouncedSearchHandler]); }, [debouncedSearchHandler]);
const deletePost = useCallback((postId: string) => async () => {
const res = await fetch(`/server-api/posts/${postId}`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${Cookies.get("drift-token")}`
},
})
if (!res.ok) {
console.error(res)
return
} else {
setPosts((posts) => posts.filter(post => post.id !== postId))
}
}, [])
return ( return (
<div className={styles.container}> <div className={styles.container}>
<div className={styles.searchContainer}> <div className={styles.searchContainer}>
@ -94,7 +109,7 @@ const PostList = ({ morePosts, initialPosts, error }: Props) => {
onChange={debouncedSearchHandler} /> onChange={debouncedSearchHandler} />
</div> </div>
{error && <Text type='error'>Failed to load.</Text>} {error && <Text type='error'>Failed to load.</Text>}
{!posts && searching && <ul> {!posts.length && searching && <ul>
<li> <li>
<ListItemSkeleton /> <ListItemSkeleton />
</li> </li>
@ -107,7 +122,7 @@ const PostList = ({ morePosts, initialPosts, error }: Props) => {
posts?.length > 0 && <div> posts?.length > 0 && <div>
<ul> <ul>
{posts.map((post) => { {posts.map((post) => {
return <ListItem post={post} key={post.id} /> return <ListItem deletePost={deletePost(post.id)} post={post} key={post.id} />
})} })}
</ul> </ul>
</div> </div>

View file

@ -4,12 +4,14 @@ import { useEffect, useMemo, useState } from "react"
import timeAgo from "@lib/time-ago" import timeAgo from "@lib/time-ago"
import VisibilityBadge from "../visibility-badge" import VisibilityBadge from "../visibility-badge"
import getPostPath from "@lib/get-post-path" import getPostPath from "@lib/get-post-path"
import { Link, Text, Card, Tooltip, Divider, Badge } from "@geist-ui/core" import { Link, Text, Card, Tooltip, Divider, Badge, Button } from "@geist-ui/core"
import { File, Post } from "@lib/types" import { File, Post } from "@lib/types"
import FadeIn from "@components/fade-in" import FadeIn from "@components/fade-in"
import Trash from "@geist-ui/icons/trash"
import Cookies from "js-cookie"
// TODO: isOwner should default to false so this can be used generically // TODO: isOwner should default to false so this can be used generically
const ListItem = ({ post, isOwner = true }: { post: Post, isOwner?: boolean }) => { const ListItem = ({ post, isOwner = true, deletePost }: { post: Post, isOwner?: boolean, deletePost: () => void }) => {
const createdDate = useMemo(() => new Date(post.createdAt), [post.createdAt]) const createdDate = useMemo(() => new Date(post.createdAt), [post.createdAt])
const [time, setTimeAgo] = useState(timeAgo(createdDate)) const [time, setTimeAgo] = useState(timeAgo(createdDate))
@ -43,7 +45,7 @@ const ListItem = ({ post, isOwner = true }: { post: Post, isOwner?: boolean }) =
</span> </span>
</div> </div>
{isOwner && <span style={{ float: 'right' }}> {isOwner && <span style={{ float: 'right' }}>
<Button iconRight={<Trash />} onClick={deletePost} auto />
</span>} </span>}
</Text> </Text>

View file

@ -1,22 +0,0 @@
import type { Document } from "@lib/types"
import DocumentComponent from "@components/edit-document"
import { memo, } from "react"
const DocumentList = ({ docs }: {
docs: Document[],
}) => {
return (<>{
docs.map(({ content, id, title }) => {
return (
<DocumentComponent
key={id}
content={content}
title={title}
/>
)
})
}
</>)
}
export default memo(DocumentList)

View file

@ -8,6 +8,7 @@ import Skeleton from "react-loading-skeleton"
import { Button, Text, ButtonGroup, Spacer, Tabs, Textarea, Tooltip, Link, Tag } from "@geist-ui/core" import { Button, Text, ButtonGroup, Spacer, Tabs, Textarea, Tooltip, Link, Tag } from "@geist-ui/core"
import HtmlPreview from "@components/preview" import HtmlPreview from "@components/preview"
import FadeIn from "@components/fade-in"
// import Link from "next/link" // import Link from "next/link"
type Props = { type Props = {
@ -82,7 +83,7 @@ const Document = ({ content, title, initialTab = 'edit', skeleton, id }: Props)
return ( return (
<> <FadeIn>
<Spacer height={1} /> <Spacer height={1} />
<div className={styles.card}> <div className={styles.card}>
<Link href={`#${title}`} className={styles.fileNameContainer}> <Link href={`#${title}`} className={styles.fileNameContainer}>
@ -114,9 +115,9 @@ const Document = ({ content, title, initialTab = 'edit', skeleton, id }: Props)
</div> </div>
</Tabs.Item> </Tabs.Item>
</Tabs> </Tabs>
</div > </div>
</div > </div>
</> </FadeIn>
) )
} }

View file

@ -104,7 +104,6 @@ posts.get("/", secretKey, async (req, res, next) => {
const posts = await Post.findAll({ const posts = await Post.findAll({
attributes: ["id", "title", "visibility", "createdAt"] attributes: ["id", "title", "visibility", "createdAt"]
}) })
res.json(posts) res.json(posts)
} catch (e) { } catch (e) {
next(e) next(e)