From 3b61a26c9cb5ee05344a6763df2767a524bfa796 Mon Sep 17 00:00:00 2001 From: Richard Macarthy Date: Sun, 5 Feb 2023 06:09:39 +0000 Subject: [PATCH] Add halt tree, and copy message id features (#1088) --- website/public/locales/en/common.json | 8 +-- website/public/locales/en/message.json | 6 ++- .../components/Messages/MessageTableEntry.tsx | 54 ++++++++++++++++--- website/src/lib/api.ts | 2 + website/src/lib/oasst_api_client.ts | 7 +++ website/src/pages/api/admin/stop_tree/[id].ts | 15 ++++++ 6 files changed, 81 insertions(+), 11 deletions(-) create mode 100644 website/src/pages/api/admin/stop_tree/[id].ts diff --git a/website/public/locales/en/common.json b/website/public/locales/en/common.json index f1783669..abc9fb21 100644 --- a/website/public/locales/en/common.json +++ b/website/public/locales/en/common.json @@ -2,14 +2,17 @@ "about": "About", "account_settings": "Account", "admin_dashboard": "Admin Dashboard", + "copied": "Copied", "connect": "Connect", "conversational": "Conversational AI for everyone.", + "dark_mode": "Dark Mode", "dashboard": "Dashboard", "delete": "Delete", "discord": "Discord", "docs": "Docs", "github": "GitHub", "legal": "Legal", + "light_mode": "Light Mode", "loading": "Loading...", "more_information": "More Information", "no": "No", @@ -17,9 +20,8 @@ "report_a_bug": "Report a Bug", "sign_in": "Sign In", "sign_out": "Sign Out", + "success": "Success", "terms_of_service": "Terms of Service", "title": "Open Assistant", - "yes": "Yes", - "dark_mode": "Dark Mode", - "light_mode": "Light Mode" + "yes": "Yes" } diff --git a/website/public/locales/en/message.json b/website/public/locales/en/message.json index ac9689a2..c65b1cfa 100644 --- a/website/public/locales/en/message.json +++ b/website/public/locales/en/message.json @@ -1,16 +1,20 @@ { + "copy_message_id": "Copy message ID", "label_action": "Label", "label_title": "Label", + "message_deleted": "Message deleted", "message": "Message", "open_new_tab_action": "Open in new tab", "parent": "Parent", "reactions": "Reactions", + "recent_messages": "Recent Messages", "report_action": "Report", "report_placeholder": "Why should this message be reviewed?", "report_title": "Report", "send_report": "Send", + "stop_tree": "Stop tree", "submit_labels": "Submit", + "tree_stopped": "Tree stopped {{id}}", "view_user": "View user", - "recent_messages": "Recent Messages", "your_recent_messages": "Your Recent Messages" } diff --git a/website/src/components/Messages/MessageTableEntry.tsx b/website/src/components/Messages/MessageTableEntry.tsx index cec724e5..3fb8d59a 100644 --- a/website/src/components/Messages/MessageTableEntry.tsx +++ b/website/src/components/Messages/MessageTableEntry.tsx @@ -12,9 +12,10 @@ import { useBreakpointValue, useColorModeValue, useDisclosure, + useToast, } from "@chakra-ui/react"; import { boolean } from "boolean"; -import { ClipboardList, Flag, MessageSquare, MoreHorizontal, Trash, User } from "lucide-react"; +import { ClipboardList, Copy, Flag, MessageSquare, MoreHorizontal, Slash, Trash, User } from "lucide-react"; import { useRouter } from "next/router"; import { useSession } from "next-auth/react"; import { useTranslation } from "next-i18next"; @@ -22,7 +23,7 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { LabelMessagePopup } from "src/components/Messages/LabelPopup"; import { MessageEmojiButton } from "src/components/Messages/MessageEmojiButton"; import { ReportPopup } from "src/components/Messages/ReportPopup"; -import { del, post } from "src/lib/api"; +import { del, post, put } from "src/lib/api"; import { colors } from "src/styles/Theme/colors"; import { Message, MessageEmojis } from "src/types/Conversation"; import { emojiIcons, isKnownEmoji } from "src/types/Emoji"; @@ -142,6 +143,8 @@ const EmojiMenuItem = ({ ); }; +const CHAR_COUNT = 10; + const MessageActions = ({ react, userEmoji, @@ -155,16 +158,47 @@ const MessageActions = ({ onReport: () => void; message: Message; }) => { + const toast = useToast(); const { t } = useTranslation(["message", "common"]); - const { trigger } = useSWRMutation(`/api/admin/delete_message/${message.id}`, del); - const { data } = useSession() || {}; - const role = data?.user?.role; + const id = message.id; + const displayId = id.slice(0, CHAR_COUNT) + "..." + id.slice(-CHAR_COUNT); + const { trigger: deleteMessage } = useSWRMutation(`/api/admin/delete_message/${message.id}`, del); + + const { trigger: stopTree } = useSWRMutation(`/api/admin/stop_tree/${message.id}`, put, { + onSuccess: () => { + toast({ + title: t("common:success"), + description: t("tree_stopped", { id: displayId }), + status: "success", + duration: 5000, + isClosable: true, + }); + }, + }); + + const { data: session } = useSession(); + const isAdmin = session?.user?.role === "admin"; const handleDelete = async () => { - await trigger(); + await deleteMessage(); mutate((key) => typeof key === "string" && key.startsWith("/api/messages"), undefined, { revalidate: true }); }; + const handleStop = () => { + stopTree(); + }; + + const handleCopyId = () => { + navigator.clipboard.writeText(message.id); + toast({ + title: t("common:copied"), + description: displayId, + status: "info", + duration: 5000, + isClosable: true, + }); + }; + return ( @@ -189,15 +223,21 @@ const MessageActions = ({ }> {t("open_new_tab_action")} - {role === "admin" && ( + {!!isAdmin && ( <> + }> + {t("copy_message_id")} + }> {t("view_user")} }> {t("common:delete")} + }> + {t("stop_tree")} + )} diff --git a/website/src/lib/api.ts b/website/src/lib/api.ts index 6c3bd900..27b1b811 100644 --- a/website/src/lib/api.ts +++ b/website/src/lib/api.ts @@ -19,6 +19,8 @@ export const post = (url: string, { arg: data }) => api.post(url, data).then((re export const del = (url: string) => api.delete(url).then((res) => res.data); +export const put = (url: string, { arg: data }) => api.put(url, data).then((res) => res.data); + api.interceptors.response.use( (response) => response, (error) => { diff --git a/website/src/lib/oasst_api_client.ts b/website/src/lib/oasst_api_client.ts index f8307854..30fb9885 100644 --- a/website/src/lib/oasst_api_client.ts +++ b/website/src/lib/oasst_api_client.ts @@ -167,6 +167,13 @@ export class OasstApiClient { return this.delete(`/api/v1/messages/${message_id}`); } + /** + * Stop message tree + */ + async stop_tree(message_id: string): Promise { + return this.put(`/api/v1/messages/${message_id}/tree/state?halt=true`); + } + /** * Send a report about a message */ diff --git a/website/src/pages/api/admin/stop_tree/[id].ts b/website/src/pages/api/admin/stop_tree/[id].ts new file mode 100644 index 00000000..ade751b3 --- /dev/null +++ b/website/src/pages/api/admin/stop_tree/[id].ts @@ -0,0 +1,15 @@ +import { withRole } from "src/lib/auth"; +import { createApiClient } from "src/lib/oasst_client_factory"; + +const handler = withRole("admin", async (req, res, token) => { + const { id } = req.query; + try { + const client = await createApiClient(token); + await client.stop_tree(id as string); + res.status(200).json({ message: `Tree ${id} stopped`, id }); + } catch (e) { + res.status(500).json(e); + } +}); + +export default handler;