Skip to content

Commit

Permalink
feat: add popup support
Browse files Browse the repository at this point in the history
* introduce menu button for edit feed and delete comment
  • Loading branch information
OXeu committed Jun 8, 2024
1 parent 46af1c2 commit 9b23ab6
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 9 deletions.
1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"react-dom": "^18.2.0",
"react-helmet": "^6.1.0",
"react-loading": "^2.0.3",
"reactjs-popup": "^2.0.6",
"remixicon": "^4.2.0",
"rin-server": "workspace:../server",
"typescript-cookie": "^1.0.6",
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ export function IconSmall({ name, label, className, onClick, hover = true }: { n
<i className={name}></i>
</button>
)
}
}
23 changes: 23 additions & 0 deletions client/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,26 @@ ul {
.markdown-alert-title {
@apply !mb-2 !text-inherit !font-bold;
}

/* animation */

@keyframes anvil {
0% {
transform: scale(1) translateY(0px);
opacity: 0;
box-shadow: 0 0 0 rgba(241, 241, 241, 0);
}
1% {
transform: scale(0.96) translateY(10px);
opacity: 0;
box-shadow: 0 0 0 rgba(241, 241, 241, 0);
}
100% {
transform: scale(1) translateY(0px);
opacity: 1;
box-shadow: 0 0 500px rgba(241, 241, 241, 0);
}
}
.popup-content {
-webkit-animation: anvil 0.3s cubic-bezier(0.38, 0.1, 0.36, 0.9) forwards;
}
55 changes: 48 additions & 7 deletions client/src/page/feed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { format } from "@astroimg/timeago";
import MarkdownPreview from '@uiw/react-markdown-preview';
import { useContext, useEffect, useRef, useState } from "react";
import { Helmet } from 'react-helmet';
import { Icon, IconSmall } from "../components/icon";
import Popup from "reactjs-popup";
import { Link, useLocation } from "wouter";
import { Waiting } from "../components/loading";
import { client } from "../main";
import { ProfileContext } from "../state/profile";
Expand Down Expand Up @@ -33,6 +34,22 @@ export function FeedPage({ id }: { id: string }) {
const [error, setError] = useState<string>()
const [headImage, setHeadImage] = useState<string>()
const ref = useRef("")
const [_, setLocation] = useLocation()
function deleteFeed() {
// 询问
if (!confirm("确定要删除这篇文章吗?")) return
if (!feed) return
client.feed({ id: feed.id }).delete(null, {
headers: headersWithAuth()
}).then(({ error }) => {
if (error) {
alert(error.value)
} else {
alert("删除成功")
setLocation('/')
}
})
}
useEffect(() => {
if (ref.current == id) return
setFeed(undefined)
Expand Down Expand Up @@ -93,9 +110,22 @@ export function FeedPage({ id }: { id: string }) {
<h1 className="text-xl font-bold t-primary">
{feed.title}
</h1>
{profile?.permission && <div className="flex-1 flex flex-col items-end justify-center">
<Icon label="编辑" name="ri-edit-2-line ri-lg" onClick={() => window.location.href = `/writing/${feed.id}`} />
</div>}
<div className="flex-1 w-0" />
{profile?.permission &&
<Popup arrow={false} trigger={
<button className="px-2 py bg-neutral-400/15 rounded-full">
<i className="ri-more-fill t-secondary"></i>
</button>
} position="bottom center">
<div className="flex flex-col self-end t-secondary mt-2 space-y-2">
<Link aria-label="编辑" href={`/writing/${feed.id}`} className="flex-1 flex flex-col items-end justify-center px-2 py bg-neutral-400/15 rounded-full">
<i className="ri-edit-2-line" />
</Link>
<button aria-label="删除" onClick={deleteFeed} className="flex-1 flex flex-col items-end justify-center px-2 py bg-neutral-400/15 rounded-full">
<i className="ri-delete-bin-7-line" />
</button>
</div>
</Popup>}
</div>
<div className="my-2">
<p className="text-gray-400 text-sm" title={new Date(feed.createdAt).toLocaleString()}>
Expand Down Expand Up @@ -270,10 +300,21 @@ function CommentItem({ comment, onRefresh }: { comment: Comment, onRefresh: () =
<p className="t-primary">
{comment.content}
</p>
{(profile?.permission || profile?.id == comment.user.id) && <div className="flex flex-row self-end">
<IconSmall label="删除评论" name="ri-delete-bin-2-line ri-sm" onClick={deleteComment} />
<div className="flex flex-row justify-end">
{(profile?.permission || profile?.id == comment.user.id) &&
<Popup arrow={false} trigger={
<button className="px-2 py bg-neutral-400/15 rounded-full">
<i className="ri-more-fill t-secondary"></i>
</button>
} position="left center">
<div className="flex flex-row self-end mr-2">
<button onClick={deleteComment} aria-label="删除评论" className="px-2 py bg-neutral-400/15 rounded-full">
<i className="ri-delete-bin-2-line t-secondary"></i>
</button>
</div>
</Popup>
}
</div>
}
</div>
</div>)
}
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
"devDependencies": {
"autoprefixer": "^10.4.19",
"postcss": "^8.4.38",
"puppeteer": "^22.10.0",
"tailwindcss": "^3.4.3",
"turbo": "^1.13.3",
"vitest": "1.3.0"
Expand Down
16 changes: 16 additions & 0 deletions server/src/services/feed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,5 +218,21 @@ export const FeedService = (db: DB, env: Env) => new Elysia({ aot: false })
tags: t.Optional(t.Array(t.String()))
})
})
.delete('/:id', async ({ admin, set, uid, params: { id } }) => {
const id_num = parseInt(id);
const feed = await db.query.feeds.findFirst({
where: eq(feeds.id, id_num)
});
if (!feed) {
set.status = 404;
return 'Not found';
}
if (feed.uid !== uid && !admin) {
set.status = 403;
return 'Permission denied';
}
await db.delete(feeds).where(eq(feeds.id, id_num));
return 'Deleted';
})

);

0 comments on commit 9b23ab6

Please sign in to comment.