diff --git a/website/public/locales/en/message.json b/website/public/locales/en/message.json
index c65b1cfade..a531f0a4cf 100644
--- a/website/public/locales/en/message.json
+++ b/website/public/locales/en/message.json
@@ -1,5 +1,6 @@
{
"copy_message_id": "Copy message ID",
+ "copy_message_link": "Copy message link",
"label_action": "Label",
"label_title": "Label",
"message_deleted": "Message deleted",
diff --git a/website/src/components/Messages/MessageEmojiButton.stories.tsx b/website/src/components/Messages/MessageEmojiButton.stories.tsx
index d74836d500..b083c9660f 100644
--- a/website/src/components/Messages/MessageEmojiButton.stories.tsx
+++ b/website/src/components/Messages/MessageEmojiButton.stories.tsx
@@ -8,8 +8,20 @@ export default {
component: MessageEmojiButton,
};
-const Template = ({ emoji, count, checked }: { emoji: string; count: number; checked?: boolean }) => {
- return ;
+const Template = ({
+ emoji,
+ count,
+ checked,
+ showCount,
+}: {
+ emoji: string;
+ count: number;
+ checked?: boolean;
+ showCount: boolean;
+}) => {
+ return (
+
+ );
};
export const Default = Template.bind({});
@@ -17,6 +29,7 @@ Default.args = {
emoji: "+1",
count: 7,
checked: false,
+ showCount: true,
};
export const BigNumber = Template.bind({});
@@ -24,6 +37,7 @@ BigNumber.args = {
emoji: "+1",
count: 999,
checked: false,
+ showCount: true,
};
export const Checked = Template.bind({});
@@ -31,4 +45,5 @@ Checked.args = {
emoji: "+1",
count: 2,
checked: true,
+ showCount: true,
};
diff --git a/website/src/components/Messages/MessageEmojiButton.tsx b/website/src/components/Messages/MessageEmojiButton.tsx
index b6aab5bc7a..f140a789d9 100644
--- a/website/src/components/Messages/MessageEmojiButton.tsx
+++ b/website/src/components/Messages/MessageEmojiButton.tsx
@@ -6,9 +6,10 @@ interface MessageEmojiButtonProps {
emoji: MessageEmoji;
checked?: boolean;
onClick: () => void;
+ showCount: boolean;
}
-export const MessageEmojiButton = ({ emoji, checked, onClick }: MessageEmojiButtonProps) => {
+export const MessageEmojiButton = ({ emoji, checked, onClick, showCount }: MessageEmojiButtonProps) => {
const EmojiIcon = emojiIcons.get(emoji.name);
if (!EmojiIcon) return <>>;
return (
@@ -22,7 +23,7 @@ export const MessageEmojiButton = ({ emoji, checked, onClick }: MessageEmojiButt
padding="0"
>
- {emoji.count > 0 && {emoji.count}}
+ {emoji.count > 0 && showCount && {emoji.count}}
);
};
diff --git a/website/src/components/Messages/MessageTableEntry.tsx b/website/src/components/Messages/MessageTableEntry.tsx
index 236602e392..51db6d7c5e 100644
--- a/website/src/components/Messages/MessageTableEntry.tsx
+++ b/website/src/components/Messages/MessageTableEntry.tsx
@@ -15,14 +15,14 @@ import {
useToast,
} from "@chakra-ui/react";
import { boolean } from "boolean";
-import { ClipboardList, Copy, Flag, MessageSquare, MoreHorizontal, Slash, Trash, User } from "lucide-react";
+import { ClipboardList, Copy, Flag, Link, MessageSquare, MoreHorizontal, Slash, Trash, User } from "lucide-react";
import { useRouter } from "next/router";
-import { useSession } from "next-auth/react";
import { useTranslation } from "next-i18next";
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 { useHasRole } from "src/hooks/auth/useHasRole";
import { del, post, put } from "src/lib/api";
import { colors } from "src/styles/Theme/colors";
import { Message, MessageEmojis } from "src/types/Conversation";
@@ -116,6 +116,7 @@ export function MessageTableEntry({ message, enabled, highlight }: MessageTableE
key={emoji}
emoji={{ name: emoji, count }}
checked={emojiState.user_emojis.includes(emoji)}
+ showCount={emojiState.user_emojis.filter((emoji) => emoji === "+1" || emoji === "-1").length > 0}
onClick={() => react(emoji, !emojiState.user_emojis.includes(emoji))}
/>
);
@@ -170,12 +171,12 @@ const MessageActions = ({
}) => {
const toast = useToast();
const { t } = useTranslation(["message", "common"]);
- 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 { id } = message;
+ const { trigger: deleteMessage } = useSWRMutation(`/api/admin/delete_message/${id}`, del);
- const { trigger: stopTree } = useSWRMutation(`/api/admin/stop_tree/${message.id}`, put, {
+ const { trigger: stopTree } = useSWRMutation(`/api/admin/stop_tree/${id}`, put, {
onSuccess: () => {
+ const displayId = id.slice(0, CHAR_COUNT) + "..." + id.slice(-CHAR_COUNT);
toast({
title: t("common:success"),
description: t("tree_stopped", { id: displayId }),
@@ -186,9 +187,6 @@ const MessageActions = ({
},
});
- const { data: session } = useSession();
- const isAdmin = session?.user?.role === "admin";
-
const handleDelete = async () => {
await deleteMessage();
mutate((key) => typeof key === "string" && key.startsWith("/api/messages"), undefined, { revalidate: true });
@@ -198,8 +196,10 @@ const MessageActions = ({
stopTree();
};
- const handleCopyId = () => {
- navigator.clipboard.writeText(message.id);
+ const handleCopy = (text: string) => {
+ navigator.clipboard.writeText(text);
+ const displayId = text.slice(0, CHAR_COUNT) + "..." + text.slice(-CHAR_COUNT);
+
toast({
title: t("common:copied"),
description: displayId,
@@ -209,6 +209,8 @@ const MessageActions = ({
});
};
+ const isAdmin = useHasRole("admin");
+
return (