server/client: add post deletion
This commit is contained in:
parent
62bc7af004
commit
5ac73718cf
6 changed files with 50 additions and 54 deletions
|
@ -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) {
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
|
@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue