From f5ca3e25ea169dadcc3d5f822bd1da094987b854 Mon Sep 17 00:00:00 2001 From: sunface Date: Mon, 10 May 2021 16:14:17 +0800 Subject: [PATCH] add story forbidden --- pages/[username]/[post_id].tsx | 10 ++++--- pages/admin/report.tsx | 2 +- pages/r/comment/[id].tsx | 25 ++++++----------- server/internal/admin/admin.go | 24 +++++++++++++++++ server/internal/api/admin.go | 17 ++++++++++++ server/internal/api/comment.go | 22 +++++++++++++++ server/internal/server.go | 3 ++- server/pkg/models/story.go | 1 + src/components/story/forbidden.tsx | 37 ++++++++++++++++++++++++++ src/components/story/story-sidebar.tsx | 16 +++++++++-- src/types/story.ts | 3 ++- 11 files changed, 135 insertions(+), 25 deletions(-) create mode 100644 src/components/story/forbidden.tsx diff --git a/pages/[username]/[post_id].tsx b/pages/[username]/[post_id].tsx index cdffe569..14d88715 100644 --- a/pages/[username]/[post_id].tsx +++ b/pages/[username]/[post_id].tsx @@ -1,4 +1,4 @@ -import { Box, Button, chakra, Divider, Flex, Heading, HStack, Image, Radio, RadioGroup, Stack, Text} from "@chakra-ui/react" +import { Box, Button, chakra, Divider, Flex, Heading, HStack, Image, Radio, RadioGroup, Stack, Tag, Text, Tooltip} from "@chakra-ui/react" import Comments from "components/comments/comments" import { MarkdownRender } from "components/markdown-editor/render" import { StoryAuthor } from "components/story/story-author" @@ -9,7 +9,7 @@ import PostNav from "layouts/nav/post-nav" import PageContainer from "layouts/page-container" import { useRouter } from "next/router" import React, { useEffect, useState } from "react" -import { Story } from "src/types/story" +import { Story, StoryStatus } from "src/types/story" import { requestApi } from "utils/axios/request" import StorySidebar from "components/story/story-sidebar" import Series from "components/story/series" @@ -63,7 +63,11 @@ const PostPage = () => { - {post.title} + + {post.title} + {post.status === StoryStatus.Forbidden && 已禁用} + + setReport(true)}> diff --git a/pages/admin/report.tsx b/pages/admin/report.tsx index 7e19fa70..122fa660 100644 --- a/pages/admin/report.tsx +++ b/pages/admin/report.tsx @@ -61,7 +61,7 @@ const PostsPage = () => { - + ) diff --git a/pages/r/comment/[id].tsx b/pages/r/comment/[id].tsx index f70c9e6d..f0cdddbb 100644 --- a/pages/r/comment/[id].tsx +++ b/pages/r/comment/[id].tsx @@ -1,24 +1,10 @@ -import { Box, Button, Flex, Heading, HStack, Image, Text, VStack } from "@chakra-ui/react" -import Card from "components/card" -import Empty from "components/empty" -import { MarkdownRender } from "components/markdown-editor/render" -import Stories from "components/story/stories" -import SEO from "components/seo" -import siteConfig from "configs/site-config" import useSession from "hooks/use-session" -import PageContainer1 from "layouts/page-container1" import { useRouter } from "next/router" import React, { useEffect, useState } from "react" -import { ReserveUrls } from "src/data/reserve-urls" -import { Story } from "src/types/story" -import { Tag } from "src/types/tag" import { requestApi } from "utils/axios/request" -import { isAdmin } from "utils/role" -import Follow from "components/interaction/follow" -import Count from "components/count" -import StoryFilters from "components/story/story-filter" import CommentCard from "components/comments/comment" import { Comment } from "src/types/comments" +import { Box, Button } from "@chakra-ui/react" const CommentPage = () => { const router = useRouter() @@ -37,11 +23,16 @@ const CommentPage = () => { console.log(res.data) } + const gotoPost = async () => { + const res = await requestApi.get(`/story/byCommentID/${comment.id}`) + router.push(res.data + '#comments') + } return ( - <> + + {comment && session && } - + ) } diff --git a/server/internal/admin/admin.go b/server/internal/admin/admin.go index f218f2ba..d7408f8a 100644 --- a/server/internal/admin/admin.go +++ b/server/internal/admin/admin.go @@ -25,3 +25,27 @@ func GetUsers() ([]*models.User, *e.Error) { return users, nil } + +func ForbiddenStory(id string) *e.Error { + var status int + err := db.Conn.QueryRow("SELECT status FROM story WHERE id=?", id).Scan(&status) + if err != nil { + logger.Warn("get story status error", "error", err) + return e.New(http.StatusInternalServerError, e.Internal) + } + + var newStatus int + if status != models.StatusForbidden { + newStatus = models.StatusForbidden + } else { + newStatus = models.StatusDraft + } + + _, err = db.Conn.Exec("UPDATE story SET status=? WHERE id=?", newStatus, id) + if err != nil { + logger.Warn("update story status error", "error", err) + return e.New(http.StatusInternalServerError, e.Internal) + } + + return nil +} diff --git a/server/internal/api/admin.go b/server/internal/api/admin.go index 7dfe6d8e..09950224 100644 --- a/server/internal/api/admin.go +++ b/server/internal/api/admin.go @@ -119,3 +119,20 @@ func DeleteReport(c *gin.Context) { c.JSON(http.StatusOK, common.RespSuccess(nil)) } + +func ForbiddenStory(c *gin.Context) { + id := c.Param("id") + currentUser := user.CurrentUser(c) + if !currentUser.Role.IsAdmin() { + c.JSON(http.StatusForbidden, common.RespError(e.NoPermission)) + return + } + + err := admin.ForbiddenStory(id) + if err != nil { + c.JSON(err.Status, common.RespError(err.Message)) + return + } + + c.JSON(http.StatusOK, common.RespSuccess(nil)) +} diff --git a/server/internal/api/comment.go b/server/internal/api/comment.go index ca95d8b6..d62e985e 100644 --- a/server/internal/api/comment.go +++ b/server/internal/api/comment.go @@ -1,6 +1,7 @@ package api import ( + "fmt" "net/http" "strings" @@ -89,6 +90,7 @@ func GetStoryComment(c *gin.Context) { id := c.Param("id") comment, err := story.GetComment(id) if err != nil { + c.JSON(err.Status, common.RespError(err.Message)) return } @@ -133,3 +135,23 @@ func DeleteStoryComment(c *gin.Context) { c.JSON(http.StatusOK, common.RespSuccess(nil)) } + +func GetStoryIDByCommentID(c *gin.Context) { + cid := c.Param("cid") + id, _, err := story.GetStoryIDByCommentID(cid) + if err != nil { + c.JSON(http.StatusInternalServerError, common.RespError(e.Internal)) + return + } + + creatorID, err1 := story.GetPostCreator(id) + if err1 != nil { + c.JSON(err1.Status, common.RespError(err1.Message)) + return + } + + creator := &models.UserSimple{ID: creatorID} + creator.Query() + + c.JSON(http.StatusOK, common.RespSuccess(fmt.Sprintf("/%s/%s", creator.Username, id))) +} diff --git a/server/internal/server.go b/server/internal/server.go index c479ae27..e59fe68c 100644 --- a/server/internal/server.go +++ b/server/internal/server.go @@ -73,6 +73,7 @@ func (s *Server) Start() error { r.GET("/story/comment/:id", api.GetStoryComment) r.POST("/story/comment", IsLogin(), api.SubmitComment) r.DELETE("/story/comment/:id", IsLogin(), api.DeleteStoryComment) + r.GET("/story/byCommentID/:cid", api.GetStoryIDByCommentID) r.GET("/story/posts/editor", IsLogin(), api.GetEditorPosts) r.GET("/story/posts/org/:id", IsLogin(), api.GetOrgPosts) @@ -91,7 +92,7 @@ func (s *Server) Start() error { r.DELETE("/story/post/:id", IsLogin(), api.DeletePost) r.POST("/story/bookmark/:storyID", IsLogin(), api.Bookmark) r.GET("/story/bookmark/posts", IsLogin(), api.GetBookmarkPosts) - + r.POST("/story/forbidden/:id", IsLogin(), api.ForbiddenStory) // tag apis r.POST("/tag", IsLogin(), api.SubmitTag) r.DELETE("/tag/:id", IsLogin(), api.DeleteTag) diff --git a/server/pkg/models/story.go b/server/pkg/models/story.go index e931ffb9..3287227c 100644 --- a/server/pkg/models/story.go +++ b/server/pkg/models/story.go @@ -10,6 +10,7 @@ const ( StatusDraft = 1 StatusPublished = 2 StatusHidden = 3 + StatusForbidden = 4 ) type Story struct { diff --git a/src/components/story/forbidden.tsx b/src/components/story/forbidden.tsx new file mode 100644 index 00000000..b439b47e --- /dev/null +++ b/src/components/story/forbidden.tsx @@ -0,0 +1,37 @@ +import { chakra, HStack, IconButton, Image, Tooltip, useColorMode, useColorModeValue } from "@chakra-ui/react"; +import SvgButton from "components/svg-button"; +import { useState } from "react"; +import { FaBan, FaHeart, FaRegHeart } from "react-icons/fa"; +import { Story, StoryStatus } from "src/types/story"; +import { requestApi } from "utils/axios/request"; + +interface Props { + story: Story +} + +const Forbidden = (props: Props) => { + const { story } = props + const [status,setStatus] = useState(story.status) + + const forbiddenStory = async () => { + await requestApi.post(`/story/forbidden/${story.id}`) + if (status != StoryStatus.Forbidden) { + setStatus(StoryStatus.Forbidden) + } else { + setStatus(StoryStatus.Draft) + } + } + + return ( + } + /> + ) +} + +export default Forbidden \ No newline at end of file diff --git a/src/components/story/story-sidebar.tsx b/src/components/story/story-sidebar.tsx index d5d2d45f..81315e36 100644 --- a/src/components/story/story-sidebar.tsx +++ b/src/components/story/story-sidebar.tsx @@ -1,6 +1,6 @@ import React from "react" -import { Box, BoxProps, useColorModeValue, VStack } from "@chakra-ui/react" -import { Story } from "src/types/story" +import { Box, BoxProps, IconButton, useColorModeValue, VStack } from "@chakra-ui/react" +import { Story, StoryStatus } from "src/types/story" import useSession from "hooks/use-session" import Like from "../interaction/like" import Bookmark from "./bookmark" @@ -8,6 +8,11 @@ import SvgButton from "components/svg-button" import { useRouter } from "next/router" import { ReserveUrls } from "src/data/reserve-urls" import { IDType } from "src/types/id" +import { isAdmin } from "utils/role" +import { getSvgIcon } from "components/svg-icon" +import { FaBan } from "react-icons/fa" +import { requestApi } from "utils/axios/request" +import Forbidden from "./forbidden" interface Props { story: Story @@ -29,6 +34,9 @@ export const StorySidebar = (props: Props) => { return '' } + + + return ( @@ -61,6 +69,10 @@ export const StorySidebar = (props: Props) => { icon="edit" /> } + + {isAdmin(session?.user.role) && + + } ) diff --git a/src/types/story.ts b/src/types/story.ts index cf4bb34a..e8c95cb2 100644 --- a/src/types/story.ts +++ b/src/types/story.ts @@ -5,7 +5,8 @@ import { Tag } from './tag'; export enum StoryStatus { Draft = 1, Published = 2, - Hiddent = 3 + Hidden = 3 , + Forbidden = 4 } export interface Story {