From bc63942425bf79c9fcdfc299e921dab9ae23dfcd Mon Sep 17 00:00:00 2001 From: sunface Date: Fri, 9 Apr 2021 16:15:31 +0800 Subject: [PATCH] update --- pages/admin/navbar.tsx | 60 +++++++++++++++---- pages/admin/tag/[id].tsx | 67 ++++++++++++++++------ pages/settings/navbar.tsx | 66 ++++++++++++++++----- server/internal/api/tag.go | 2 +- server/pkg/models/role.go | 4 ++ src/components/story/manage-story-card.tsx | 44 +++++++++++--- 6 files changed, 192 insertions(+), 51 deletions(-) diff --git a/pages/admin/navbar.tsx b/pages/admin/navbar.tsx index a3298309..68bfed1b 100644 --- a/pages/admin/navbar.tsx +++ b/pages/admin/navbar.tsx @@ -1,4 +1,4 @@ -import { Text, Box, Heading, Image, Center, Button, Flex, VStack, Divider, useToast, FormControl, FormLabel, FormHelperText, Input, FormErrorMessage, HStack, Wrap, useMediaQuery, Avatar, Textarea, Table, Thead, Tr, Th, Tbody, Td, IconButton, useDisclosure, Modal, ModalOverlay, ModalContent, ModalHeader, ModalBody, ModalFooter, Select, NumberInput, NumberInputField, NumberInputStepper, NumberIncrementStepper, NumberDecrementStepper } from "@chakra-ui/react" +import { Text, Box, Heading, Image, Center, Button, Flex, VStack, Divider, useToast, FormControl, FormLabel, FormHelperText, Input, FormErrorMessage, HStack, Wrap, useMediaQuery, Avatar, Textarea, Table, Thead, Tr, Th, Tbody, Td, IconButton, useDisclosure, Modal, ModalOverlay, ModalContent, ModalHeader, ModalBody, ModalFooter, Select, NumberInput, NumberInputField, NumberInputStepper, NumberIncrementStepper, NumberDecrementStepper ,AlertDialog, AlertDialogOverlay, AlertDialogContent, AlertDialogHeader, AlertDialogBody, AlertDialogFooter} from "@chakra-ui/react" import Card from "components/card" import PageContainer from "layouts/page-container" import Sidebar from "layouts/sidebar/sidebar" @@ -103,15 +103,7 @@ const UserNavbarPage = () => { { - navbars.map((nv,i) => - {nv.label} - {nv.value} - {nv.weight} - - onEditNavbar(nv)}/> - onDeleteNavbar(nv.id)} /> - - ) + navbars.map((nv,i) => ) } @@ -133,7 +125,7 @@ const UserNavbarPage = () => { Value - { currentNavbar.value = e.currentTarget.value; onNavbarChange() }} placeholder="enter a url, e.g /search"/> + { currentNavbar.value = e.currentTarget.value; onNavbarChange() }} placeholder="enter a url, e.g /search/posts"/> @@ -156,3 +148,49 @@ const UserNavbarPage = () => { } export default UserNavbarPage + +const NV = ({ nv, onEdit, onDelete }) => { + const [isOpen, setIsOpen] = React.useState(false) + const onClose = () => setIsOpen(false) + const cancelRef = React.useRef() + + return ( + <> + + {nv.label} + {nv.value} + {nv.weight} + + onEdit(nv)}/> + setIsOpen(true)} /> + + + + + + + 删除菜单 - {nv.label} + + + + Are you sure? You can't undo this action afterwards. + + + + + + + + + + + ) +} \ No newline at end of file diff --git a/pages/admin/tag/[id].tsx b/pages/admin/tag/[id].tsx index 0a599970..9948559f 100644 --- a/pages/admin/tag/[id].tsx +++ b/pages/admin/tag/[id].tsx @@ -1,4 +1,4 @@ -import { Box, Button, Flex, useColorMode, useColorModeValue, useDisclosure, useRadioGroup, useToast, chakra, Input, HStack, IconButton, Heading, Divider } from '@chakra-ui/react'; +import { Box, Button, Flex, useColorMode, useColorModeValue, useDisclosure, useRadioGroup, useToast, chakra, Input, HStack, IconButton, Heading, Divider, AlertDialog, AlertDialogOverlay, AlertDialogContent, AlertDialogHeader, AlertDialogBody, AlertDialogFooter, Text } from '@chakra-ui/react'; import React, { useEffect, useState } from 'react'; import { MarkdownEditor } from 'components/markdown-editor/editor'; import PageContainer from 'layouts/page-container'; @@ -16,13 +16,14 @@ import RadioCard from 'components/radio-card'; import { useViewportScroll } from 'framer-motion'; import Card from 'components/card'; import { Tag } from 'src/types/tag'; +import { ReserveUrls } from 'src/data/reserve-urls'; function PostEditPage() { const router = useRouter() const { id } = router.query const [editMode, setEditMode] = useState(EditMode.Edit) - const [tag, setTag]:[Tag,any] = useState({ + const [tag, setTag]: [Tag, any] = useState({ md: `标签介绍,支持markdown`, title: '' }) @@ -84,26 +85,26 @@ function PostEditPage() { } - - - Title + + + Title - { tag.title = e.target.value; onChange()}} mt="4" variant="flushed" size="sm" placeholder="Tag title..." focusBorderColor="teal.400" /> + { tag.title = e.target.value; onChange() }} mt="4" variant="flushed" size="sm" placeholder="Tag title..." focusBorderColor="teal.400" /> - - Name + + Name - { tag.name = e.target.value; onChange()}} mt="4" variant="flushed" size="sm" placeholder="Tag name..." focusBorderColor="teal.400" /> + { tag.name = e.target.value; onChange() }} mt="4" variant="flushed" size="sm" placeholder="Tag name..." focusBorderColor="teal.400" /> - - 封面 + + 封面 - { tag.cover = e.target.value; onChange()}} mt="4" variant="flushed" size="sm" placeholder="图片链接,你可以用github当图片存储服务" focusBorderColor="teal.400" /> + { tag.cover = e.target.value; onChange() }} mt="4" variant="flushed" size="sm" placeholder="图片链接,你可以用github当图片存储服务" focusBorderColor="teal.400" /> - - 图标 + + 图标 - { tag.icon = e.target.value; onChange()}} mt="4" variant="flushed" size="sm" placeholder="图片链接" focusBorderColor="teal.400" /> + { tag.icon = e.target.value; onChange() }} mt="4" variant="flushed" size="sm" placeholder="图片链接" focusBorderColor="teal.400" /> @@ -113,10 +114,12 @@ function PostEditPage() { export default PostEditPage function HeaderContent(props: any) { + const [delOpen, setDelOpen] = React.useState(false) + const cancelRef = React.useRef() const { toggleColorMode: toggleMode } = useColorMode() const text = useColorModeValue("dark", "light") const SwitchIcon = useColorModeValue(FaMoon, FaSun) - + const router = useRouter() const editOptions = [EditMode.Edit, EditMode.Preview] const { getRootProps, getRadioProps } = useRadioGroup({ name: "framework", @@ -128,8 +131,10 @@ function HeaderContent(props: any) { const group = getRootProps() const onDelete = async () => { await requestApi.delete(`/tag/${props.tagID}`) + setDelOpen(false) + router.push(`${ReserveUrls.Admin}/tags`) } - + return ( <> @@ -171,9 +176,35 @@ function HeaderContent(props: any) { icon={} /> - + + setDelOpen(false)} + > + + + + Delete Tag + + + + 删除Tag将删除所有相关的信息,同时该操作不可逆,请慎重 + + + + + + + + + ) } diff --git a/pages/settings/navbar.tsx b/pages/settings/navbar.tsx index 830195d3..f172163d 100644 --- a/pages/settings/navbar.tsx +++ b/pages/settings/navbar.tsx @@ -1,4 +1,4 @@ -import { Text, Box, Heading, Image, Center, Button, Flex, VStack, Divider, useToast, FormControl, FormLabel, FormHelperText, Input, FormErrorMessage, HStack, Wrap, useMediaQuery, Avatar, Textarea, Table, Thead, Tr, Th, Tbody, Td, IconButton, useDisclosure, Modal, ModalOverlay, ModalContent, ModalHeader, ModalBody, ModalFooter, Select, NumberInput, NumberInputField, NumberInputStepper, NumberIncrementStepper, NumberDecrementStepper } from "@chakra-ui/react" +import { Text, Box, Heading, Image, Center, Button, Flex, VStack, Divider, useToast, FormControl, FormLabel, FormHelperText, Input, FormErrorMessage, HStack, Wrap, useMediaQuery, Avatar, Textarea, Table, Thead, Tr, Th, Tbody, Td, IconButton, useDisclosure, Modal, ModalOverlay, ModalContent, ModalHeader, ModalBody, ModalFooter, Select, NumberInput, NumberInputField, NumberInputStepper, NumberIncrementStepper, NumberDecrementStepper,AlertDialog, AlertDialogOverlay, AlertDialogContent, AlertDialogHeader, AlertDialogBody, AlertDialogFooter } from "@chakra-ui/react" import Card from "components/card" import PageContainer from "layouts/page-container" import Sidebar from "layouts/sidebar/sidebar" @@ -39,7 +39,7 @@ export const NavbarEditor = ({ orgID = "" }) => { }, []) const getNavbars = async () => { - const res = await requestApi.get(`/user/navbars/${orgID ? orgID : 0}`) + const res = await requestApi.get(`/user/navbars/${orgID ? orgID : 0}`) setNavbars(res.data) } @@ -76,7 +76,7 @@ export const NavbarEditor = ({ orgID = "" }) => { } if (orgID) { - await requestApi.post(`/org/navbar/${orgID}`,currentNavbar) + await requestApi.post(`/org/navbar/${orgID}`, currentNavbar) } else { await requestApi.post(`/user/navbar`, currentNavbar) } @@ -122,7 +122,7 @@ export const NavbarEditor = ({ orgID = "" }) => { } const onDeleteNavbar = async id => { - await requestApi.delete(`/${orgID?'org':'user'}/navbar/${id}`) + await requestApi.delete(`/${orgID ? 'org' : 'user'}/navbar/${id}`) getNavbars() } @@ -145,16 +145,7 @@ export const NavbarEditor = ({ orgID = "" }) => { { - navbars.map((nv, i) => - {nv.label} - {nv.type === NavbarType.Link ? "link" : "series"} - {nv.type === NavbarType.Link ? nv.value : getSeriesTitle(nv.value)} - {nv.weight} - - onEditNavbar(nv)} /> - onDeleteNavbar(nv.id)} /> - - ) + navbars.map((nv, i) => ) } @@ -204,4 +195,51 @@ export const NavbarEditor = ({ orgID = "" }) => { ) +} + +const NV = ({ nv, onEdit, onDelete, getSeriesTitle }) => { + const [isOpen, setIsOpen] = React.useState(false) + const onClose = () => setIsOpen(false) + const cancelRef = React.useRef() + + return ( + <> + + {nv.label} + {nv.type === NavbarType.Link ? "link" : "series"} + {nv.type === NavbarType.Link ? nv.value : getSeriesTitle(nv.value)} + {nv.weight} + + onEdit(nv)} /> + setIsOpen(true)} /> + + + + + + + 删除菜单 - {nv.label} + + + + Are you sure? You can't undo this action afterwards. + + + + + + + + + + + ) } \ No newline at end of file diff --git a/server/internal/api/tag.go b/server/internal/api/tag.go index 718a31e5..a4f71812 100644 --- a/server/internal/api/tag.go +++ b/server/internal/api/tag.go @@ -94,7 +94,7 @@ func DeleteTag(c *gin.Context) { } user := user.CurrentUser(c) - if !user.Role.IsAdmin() { + if !user.Role.IsSuperAdmin() { c.JSON(http.StatusForbidden, common.RespError(e.NoPermission)) } diff --git a/server/pkg/models/role.go b/server/pkg/models/role.go index 16170d4c..5bc122e8 100644 --- a/server/pkg/models/role.go +++ b/server/pkg/models/role.go @@ -14,6 +14,10 @@ func (r RoleType) IsValid() bool { return r == ROLE_NORMAL || r == ROLE_EDITOR || r == ROLE_ADMIN || r == ROLE_SUPER_ADMIN } +func (r RoleType) IsSuperAdmin() bool { + return r == ROLE_SUPER_ADMIN +} + func (r RoleType) IsAdmin() bool { return r == ROLE_ADMIN || r == ROLE_SUPER_ADMIN } diff --git a/src/components/story/manage-story-card.tsx b/src/components/story/manage-story-card.tsx index 471bab94..08285bc0 100644 --- a/src/components/story/manage-story-card.tsx +++ b/src/components/story/manage-story-card.tsx @@ -1,5 +1,5 @@ import React from "react" -import { chakra, Heading, VStack, Text, HStack, Button, Flex, PropsOf, Tag, useMediaQuery, IconButton, Tooltip } from "@chakra-ui/react" +import { chakra, Heading, VStack, Text, HStack, Button, Flex, PropsOf, Tag, useMediaQuery, IconButton, Tooltip, AlertDialog, AlertDialogOverlay, AlertDialogContent, AlertDialogHeader, AlertDialogBody, AlertDialogFooter } from "@chakra-ui/react" import { Story } from "src/types/story" import moment from 'moment' import { IDType } from "src/types/id" @@ -17,11 +17,15 @@ type Props = PropsOf & { // 文章卡片,展示需要被管理的文章 export const ManageStoryCard = (props: Props) => { - const { story, onEdit, onDelete, showSource = true,onPin, ...rest } = props + const { story, onEdit, onDelete, showSource = true, onPin, ...rest } = props const [isSmallScreen] = useMediaQuery("(max-width: 768px)") const Lay = isSmallScreen ? VStack : Flex const gap = moment(story.created).fromNow() + const [isOpen, setIsOpen] = React.useState(false) + const onClose = () => setIsOpen(false) + const cancelRef = React.useRef() + const showActions = onEdit || onDelete || onPin return ( //@ts-ignore @@ -34,18 +38,18 @@ export const ManageStoryCard = (props: Props) => { 发布于{gap} {showActions && - {onPin && + {onPin && } onClick={() => onPin(story.id)} - color={story.pinned? "teal" : null} + color={story.pinned ? "teal" : null} /> } - {onEdit&& + {onEdit && { /> } - {onDelete&& + {onDelete && } - onClick={() => props.onDelete(story.id)} + onClick={() => setIsOpen(true)} /> } } + + + + + 删除文章 - {story.title} + + + + Are you sure? You can't undo this action afterwards. + + + + + + + + + ) }