From 7effc7fb5946008c1bb0bddd0193f667ef4ffaaf Mon Sep 17 00:00:00 2001 From: sunface Date: Fri, 23 Jul 2021 17:05:10 +0800 Subject: [PATCH] update #56 --- pages/dashboard/tag-moderator.tsx | 28 ++++++----- server/internal/api/tag.go | 18 +++++++ server/internal/api/user.go | 6 --- server/internal/notification/notification.go | 2 +- server/internal/server.go | 1 + server/internal/storage/sql_tables.go | 9 ++++ server/internal/story/post.go | 16 +++++++ server/internal/tags/tags.go | 50 ++++++++++++++++++++ server/pkg/models/story.go | 15 ++++++ 9 files changed, 127 insertions(+), 18 deletions(-) diff --git a/pages/dashboard/tag-moderator.tsx b/pages/dashboard/tag-moderator.tsx index b96fb9eb..669092cb 100644 --- a/pages/dashboard/tag-moderator.tsx +++ b/pages/dashboard/tag-moderator.tsx @@ -1,27 +1,24 @@ -import {Text, Box, Heading, Image, Center, Button, Flex, VStack, Divider, useToast, Wrap, WrapItem, useColorModeValue, StackDivider } from "@chakra-ui/react" +import {Text, Box, Center, Button, Flex, VStack, Divider, useColorModeValue } from "@chakra-ui/react" import Card from "components/card" -import Nav from "layouts/nav/nav" -import PageContainer from "layouts/page-container" import Sidebar from "layouts/sidebar/sidebar" import React, { useEffect, useState } from "react" import {dashboardLinks} from "src/data/links" import { requestApi } from "utils/axios/request" import PageContainer1 from "layouts/page-container1" import Empty from "components/empty" -import { IDType } from "src/types/id" -import UserCard from "components/users/user-card" import userCustomTheme from "theme/user-custom" -import TagCard from "components/tags/tag-card" import SimpleTagCard from "components/tags/simple-tag-card" +import { Story } from "src/types/story" +import { Tag } from "src/types/tag" -const FollowersPage = () => { +const TagModeratorPage = () => { const [tags, setTags] = useState([]) - const borderColor = useColorModeValue(userCustomTheme.borderColor.light, userCustomTheme.borderColor.dark) + const [stories,setStories]:[Story[],any] = useState([]) + const [tag,setTag]:[Tag,any] = useState(null) const getTags = async () => { const res = await requestApi.get(`/tag/list/byUserModeratorRole`) - console.log(res) setTags(res.data) } @@ -29,6 +26,12 @@ const FollowersPage = () => { getTags() }, []) + const displayDisabledStories = async (tag:Tag) => { + setTag(tag) + const res = await requestApi.get(`/tag/disalbedStories/${tag.id}`) + setStories(res.data) + } + return ( <> @@ -45,7 +48,10 @@ const FollowersPage = () => { {tags.map(tag => - + + + + )} @@ -59,6 +65,6 @@ const FollowersPage = () => { ) } -export default FollowersPage +export default TagModeratorPage diff --git a/server/internal/api/tag.go b/server/internal/api/tag.go index b00d43ad..83af16bc 100644 --- a/server/internal/api/tag.go +++ b/server/internal/api/tag.go @@ -212,6 +212,12 @@ func RemoveTagStory(c *gin.Context) { return } + err = tags.DisableTagStory(tagID, storyID) + if err != nil { + c.JSON(err.Status, common.RespError(err.Message)) + return + } + s, err := story.GetStory(storyID, "") if err == nil { t, err := tags.GetTag(tagID, "") @@ -235,3 +241,15 @@ func GetTagListByUserModeratorRole(c *gin.Context) { c.JSON(http.StatusOK, common.RespSuccess(res)) } + +func GetTagDisabledStroies(c *gin.Context) { + tagID := c.Param("tagID") + + res, err := tags.GetDisabledStroies(tagID) + if err != nil { + c.JSON(err.Status, common.RespError(err.Message)) + return + } + + c.JSON(http.StatusOK, common.RespSuccess(res)) +} diff --git a/server/internal/api/user.go b/server/internal/api/user.go index 37a2fbf1..cdbd269e 100644 --- a/server/internal/api/user.go +++ b/server/internal/api/user.go @@ -1,7 +1,6 @@ package api import ( - "fmt" "net/http" "strings" @@ -85,7 +84,6 @@ func UpdateUser(c *gin.Context) { } func GetSession(c *gin.Context) { - fmt.Println(("get session")) sess := user.GetSession(c) c.JSON(http.StatusOK, common.RespSuccess(sess)) } @@ -200,7 +198,3 @@ func UserRegister(c *gin.Context) { user.Register(c, req.Code, req.Nickname, req.Username) } - -func GetUserModerators(c *gin.Context) { - -} diff --git a/server/internal/notification/notification.go b/server/internal/notification/notification.go index 14800c96..14ca432c 100644 --- a/server/internal/notification/notification.go +++ b/server/internal/notification/notification.go @@ -17,7 +17,7 @@ func Send(userID, orgID string, noType int, noID string, noTitle string, operato if userID != "" { _, err := db.Conn.Exec("INSERT INTO user_notification (user_id,operator_id,notifiable_type,notifiable_id,no_title,created) VALUES (?,?,?,?,?,?)", userID, operatorID, noType, noID, noTitle, time.Now()) - if err != nil { + if err != nil && !e.IsErrUniqueConstraint(err) { logger.Warn("send notification error", "error", err) } } diff --git a/server/internal/server.go b/server/internal/server.go index dd21dcb1..38fdf2e4 100644 --- a/server/internal/server.go +++ b/server/internal/server.go @@ -106,6 +106,7 @@ func (s *Server) Start() error { r.DELETE("/tag/moderator/:tagID/:userID", IsLogin(), api.DeleteModerator) r.DELETE("/tag/story/:tagID/:storyID", IsLogin(), api.RemoveTagStory) r.GET("/tag/list/byUserModeratorRole", IsLogin(), api.GetTagListByUserModeratorRole) + r.GET("/tag/disalbedStories/:tagID", IsLogin(), api.GetTagDisabledStroies) // user apis r.GET("/user/all", api.GetUsers) r.POST("/user/ids", api.GetUsersByIDs) diff --git a/server/internal/storage/sql_tables.go b/server/internal/storage/sql_tables.go index fa0218bf..2e8f2e37 100644 --- a/server/internal/storage/sql_tables.go +++ b/server/internal/storage/sql_tables.go @@ -181,6 +181,15 @@ var sqlTables = map[string]string{ ON tag_moderators (tag_id,user_id); `, + "tag_story_disabled": `CREATE TABLE IF NOT EXISTS tag_story_disabled ( + tag_id VARCHAR(255), + story_id VARCHAR(255), + created DATETIME NOT NULL + ); + CREATE UNIQUE INDEX IF NOT EXISTS tag_sd_tid_sid + ON tag_story_disabled (tag_id,story_id); + `, + "comments": `CREATE TABLE IF NOT EXISTS comments ( id VARCHAR(255) PRIMARY KEY, story_id VARCHAR(255), diff --git a/server/internal/story/post.go b/server/internal/story/post.go index d1d96863..08ea1646 100644 --- a/server/internal/story/post.go +++ b/server/internal/story/post.go @@ -2,6 +2,7 @@ package story import ( "database/sql" + "fmt" "net/http" "strings" "time" @@ -13,6 +14,7 @@ import ( "github.com/imdotdev/im.dev/server/internal/notification" "github.com/imdotdev/im.dev/server/internal/org" "github.com/imdotdev/im.dev/server/internal/tags" + "github.com/imdotdev/im.dev/server/internal/top" "github.com/imdotdev/im.dev/server/internal/user" "github.com/imdotdev/im.dev/server/pkg/config" @@ -117,6 +119,20 @@ func SubmitStory(c *gin.Context) (map[string]string, *e.Error) { return nil, e.New(http.StatusForbidden, e.NoEditorPermission) } + // check whether in tag disable list + for _, t := range post.Tags { + disabled, err := tags.IsStoryDisabled(t, post.ID) + if err != nil { + logger.Warn("check story disable error", "error", err) + return nil, e.New(http.StatusInternalServerError, e.Internal) + } + + if disabled { + t1, _ := tags.GetTag(t, "") + return nil, e.New(http.StatusForbidden, fmt.Sprintf("该文章被禁止在%s标签下发布,请联系管理员解除", t1.Title)) + } + } + if post.Status == models.StatusDraft { post.Created = now // 首次发布,需要更新创建时间 diff --git a/server/internal/tags/tags.go b/server/internal/tags/tags.go index fdf8a24c..ec801b34 100644 --- a/server/internal/tags/tags.go +++ b/server/internal/tags/tags.go @@ -336,6 +336,56 @@ func RemoveTagStory(tagID, storyID string) *e.Error { return nil } +func DisableTagStory(tagID, storyID string) *e.Error { + _, err := db.Conn.Exec("INSERT INTO tag_story_disabled (tag_id,story_id,created) VALUES (?,?,?)", tagID, storyID, time.Now()) + if err != nil { + logger.Warn("disable tag story error", "error", err) + return e.New(http.StatusInternalServerError, e.Internal) + } + + return nil +} + +func IsStoryDisabled(tagID, storyID string) (bool, error) { + var sid string + err := db.Conn.QueryRow("SELECT story_id FROM tag_story_disabled WHERE tag_id=? and story_id=?", tagID, storyID).Scan(&sid) + if err == sql.ErrNoRows { + return false, nil + } + + if err != nil { + return false, err + } + + return true, nil +} + +func GetDisabledStroies(tagID string) (models.Stories, *e.Error) { + stories := make(models.Stories, 0) + + rows, err := db.Conn.Query("SELECT story_id,created FROM tag_story_disabled WHERE tag_id=?", tagID) + if err != nil { + logger.Warn("query disabled tag story error", "error", err) + return nil, e.New(http.StatusInternalServerError, e.Internal) + } + + for rows.Next() { + var id string + var t time.Time + rows.Scan(&id, &t) + s, err := models.GetSimpleStory(id) + if err != nil { + logger.Warn("query disabled tag story error", "error", err) + continue + } + s.Created = t + stories = append(stories, s) + } + + sort.Sort(stories) + return stories, nil +} + func GetTagListByUserModeratorRole(userID string) ([]*models.Tag, *e.Error) { tags := make([]*models.Tag, 0) rows, err := db.Conn.Query("SELECT tag_id FROM tag_moderators WHERE user_id=?", userID) diff --git a/server/pkg/models/story.go b/server/pkg/models/story.go index 3287227c..175d36bd 100644 --- a/server/pkg/models/story.go +++ b/server/pkg/models/story.go @@ -115,3 +115,18 @@ func GetStoryTitle(storyID string) string { db.Conn.QueryRow("SELECT title FROM story WHERE id=?", storyID).Scan(&t) return t } + +func GetSimpleStory(id string) (*Story, error) { + s := &Story{} + err := db.Conn.QueryRow("select id,title,cover,creator,created from story where id=?", id).Scan( + &s.ID, &s.Title, &s.Cover, &s.CreatorID, &s.Created, + ) + if err != nil { + return nil, err + } + + s.Creator = &UserSimple{ID: s.CreatorID} + err = s.Creator.Query() + + return s, err +}