From 00f8fea9295427b64055f32667de6f152dea5ea7 Mon Sep 17 00:00:00 2001 From: Gabe Kangas Date: Sat, 16 Jul 2022 17:30:05 -0700 Subject: [PATCH] WIP of chat moderation menu, actions and modal --- .../chat/ChatModerationActionMenu.tsx | 6 - .../ChatModerationActionMenu.module.scss | 3 + .../ChatModerationActionMenu.tsx | 153 ++++++++++++++++++ .../ChatModerationDetailsModal.module.scss | 10 ++ .../ChatModerationDetailsModal.tsx | 27 ++++ .../chat/ChatModerationDetailsModal.tsx | 6 - .../ChatModerationActionMenu.stories.tsx | 9 +- .../ChatModerationDetailsModal.stories.tsx | 4 +- 8 files changed, 202 insertions(+), 16 deletions(-) delete mode 100644 web/components/chat/ChatModerationActionMenu.tsx create mode 100644 web/components/chat/ChatModerationActionMenu/ChatModerationActionMenu.module.scss create mode 100644 web/components/chat/ChatModerationActionMenu/ChatModerationActionMenu.tsx create mode 100644 web/components/chat/ChatModerationActionMenu/ChatModerationDetailsModal.module.scss create mode 100644 web/components/chat/ChatModerationActionMenu/ChatModerationDetailsModal.tsx delete mode 100644 web/components/chat/ChatModerationDetailsModal.tsx diff --git a/web/components/chat/ChatModerationActionMenu.tsx b/web/components/chat/ChatModerationActionMenu.tsx deleted file mode 100644 index a8877c0d5..000000000 --- a/web/components/chat/ChatModerationActionMenu.tsx +++ /dev/null @@ -1,6 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -interface Props {} - -export default function ChatModerationActionMenu(props: Props) { - return
Moderation popup menu goes here
; -} diff --git a/web/components/chat/ChatModerationActionMenu/ChatModerationActionMenu.module.scss b/web/components/chat/ChatModerationActionMenu/ChatModerationActionMenu.module.scss new file mode 100644 index 000000000..f5e3169c5 --- /dev/null +++ b/web/components/chat/ChatModerationActionMenu/ChatModerationActionMenu.module.scss @@ -0,0 +1,3 @@ +.icon { + padding-right: 10px; +} diff --git a/web/components/chat/ChatModerationActionMenu/ChatModerationActionMenu.tsx b/web/components/chat/ChatModerationActionMenu/ChatModerationActionMenu.tsx new file mode 100644 index 000000000..6da4799b4 --- /dev/null +++ b/web/components/chat/ChatModerationActionMenu/ChatModerationActionMenu.tsx @@ -0,0 +1,153 @@ +import { + CloseCircleOutlined, + ExclamationCircleOutlined, + EyeInvisibleOutlined, + SmallDashOutlined, +} from '@ant-design/icons'; +import { Dropdown, Menu, MenuProps, Space, Modal } from 'antd'; +import { useState } from 'react'; +import ChatModerationDetailsModal from './ChatModerationDetailsModal'; +import s from './ChatModerationActionMenu.module.scss'; + +const { confirm } = Modal; + +const HIDE_MESSAGE_ENDPOINT = `/api/chat/messagevisibility`; +const BAN_USER_ENDPOINT = `/api/chat/users/setenabled`; + +/* eslint-disable @typescript-eslint/no-unused-vars */ +interface Props { + accessToken: string; + messageID: string; + userID: string; + userDisplayName: string; +} + +export default function ChatModerationActionMenu(props: Props) { + const { messageID, userID, userDisplayName, accessToken } = props; + const [showUserDetailsModal, setShowUserDetailsModal] = useState(false); + + const handleBanUser = async () => { + const url = new URL(BAN_USER_ENDPOINT); + url.searchParams.append('accessToken', accessToken); + const hideMessageUrl = url.toString(); + + const options = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ userID }), + }; + + try { + await fetch(hideMessageUrl, options); + } catch (e) { + console.error(e); + } + }; + + const handleHideMessage = async () => { + const url = new URL(HIDE_MESSAGE_ENDPOINT); + url.searchParams.append('accessToken', accessToken); + const hideMessageUrl = url.toString(); + + const options = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ idArray: [messageID] }), + }; + + try { + await fetch(hideMessageUrl, options); + } catch (e) { + console.error(e); + } + }; + + const confirmHideMessage = async () => { + confirm({ + icon: , + content: `Are you sure you want to remove this message from ${userDisplayName}?`, + onOk() { + handleHideMessage(); + }, + }); + }; + + const confirmBanUser = async () => { + confirm({ + icon: , + content: `Are you sure you want to ban ${userDisplayName} from chat?`, + onOk() { + handleBanUser(); + }, + }); + }; + + const onMenuClick: MenuProps['onClick'] = ({ key }) => { + if (key === 'hide-message') { + confirmHideMessage(); + } else if (key === 'ban-user') { + confirmBanUser(); + } else if (key === 'more-info') { + setShowUserDetailsModal(true); + } + }; + + const menu = ( + + + + + Hide Message + + ), + key: 'hide-message', + }, + { + label: ( +
+ + + + Ban User +
+ ), + key: 'ban-user', + }, + { + label:
More Info...
, + key: 'more-info', + }, + ]} + /> + ); + + return ( + <> + + + + { + setShowUserDetailsModal(false); + }} + > + + + + ); +} diff --git a/web/components/chat/ChatModerationActionMenu/ChatModerationDetailsModal.module.scss b/web/components/chat/ChatModerationActionMenu/ChatModerationDetailsModal.module.scss new file mode 100644 index 000000000..46db7b394 --- /dev/null +++ b/web/components/chat/ChatModerationActionMenu/ChatModerationDetailsModal.module.scss @@ -0,0 +1,10 @@ +.modalContainer { + padding: 10px; +} + +.chatHistory { + margin: 10px; + padding: 15px; + border: 1px solid #ccc; + border-radius: 5px; +} diff --git a/web/components/chat/ChatModerationActionMenu/ChatModerationDetailsModal.tsx b/web/components/chat/ChatModerationActionMenu/ChatModerationDetailsModal.tsx new file mode 100644 index 000000000..79e850bf7 --- /dev/null +++ b/web/components/chat/ChatModerationActionMenu/ChatModerationDetailsModal.tsx @@ -0,0 +1,27 @@ +import { Col, Row } from 'antd'; +import s from './ChatModerationDetailsModal.module.scss'; + +/* eslint-disable @typescript-eslint/no-unused-vars */ +interface Props { + // userID: string; +} + +export default function ChatModerationDetailsModal(props: Props) { + return ( +
+ + User created + xxxx + + + + Previous names + xxxx + + +

Recent Chat Messages

+ +
+
+ ); +} diff --git a/web/components/chat/ChatModerationDetailsModal.tsx b/web/components/chat/ChatModerationDetailsModal.tsx deleted file mode 100644 index d5fda17c9..000000000 --- a/web/components/chat/ChatModerationDetailsModal.tsx +++ /dev/null @@ -1,6 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -interface Props {} - -export default function ChatModerationDetailsModal(props: Props) { - return
Moderation details modal goes here
; -} diff --git a/web/stories/ChatModerationActionMenu.stories.tsx b/web/stories/ChatModerationActionMenu.stories.tsx index 9061d76f2..f9825bb1b 100644 --- a/web/stories/ChatModerationActionMenu.stories.tsx +++ b/web/stories/ChatModerationActionMenu.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { ComponentStory, ComponentMeta } from '@storybook/react'; -import ChatModerationActionMenu from '../components/chat/ChatModerationActionMenu'; +import ChatModerationActionMenu from '../components/chat/ChatModerationActionMenu/ChatModerationActionMenu'; export default { title: 'owncast/Chat/Moderation menu', @@ -20,7 +20,12 @@ export default { // eslint-disable-next-line @typescript-eslint/no-unused-vars const Template: ComponentStory = args => ( - + ); // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/web/stories/ChatModerationDetailsModal.stories.tsx b/web/stories/ChatModerationDetailsModal.stories.tsx index 9150efa6b..c0d3cff1e 100644 --- a/web/stories/ChatModerationDetailsModal.stories.tsx +++ b/web/stories/ChatModerationDetailsModal.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { ComponentStory, ComponentMeta } from '@storybook/react'; -import ChatModerationDetailsModal from '../components/chat/ChatModerationDetailsModal'; +import ChatModerationDetailsModal from '../components/chat/ChatModerationActionMenu/ChatModerationDetailsModal'; export default { title: 'owncast/Chat/Moderation modal', @@ -24,4 +24,4 @@ const Template: ComponentStory = args => ( ); // eslint-disable-next-line @typescript-eslint/no-unused-vars -export const Basic = Template.bind({}); +export const Example = Template.bind({});