diff --git a/src/components/communitySettings/communityPlatforms/TcCommunityPlatforms.tsx b/src/components/communitySettings/communityPlatforms/TcCommunityPlatforms.tsx index cd32ac76..4a59d7be 100644 --- a/src/components/communitySettings/communityPlatforms/TcCommunityPlatforms.tsx +++ b/src/components/communitySettings/communityPlatforms/TcCommunityPlatforms.tsx @@ -55,6 +55,10 @@ function TcCommunityPlatforms() { const [activeTab, setActiveTab] = useState(0); const [hivemindManageIsLoading, setHivemindManageIsLoading] = useState(false); + const [ + violationDetectionManageIsLoading, + setViolationDetectionManageIsLoading, + ] = useState(false); const router = useRouter(); const communityId = @@ -119,6 +123,31 @@ function TcCommunityPlatforms() { } }; + const handleViolationDetectionModule = async () => { + try { + setViolationDetectionManageIsLoading(true); + const hivemindModules = await retrieveModules({ + community: communityId, + name: 'violationDetection', + }); + + if (hivemindModules.results.length > 0) { + router.push('/community-settings/violation-detection'); + } else { + await createModule({ + name: 'violationDetection', + community: communityId, + }); + router.push('/community-settings/violation-detection'); + } + setViolationDetectionManageIsLoading(false); + } catch (error) { + console.log('error', error); + } finally { + setViolationDetectionManageIsLoading(false); + } + }; + const handleUpdateCommunityPlatform = async () => { await fetchPlatformsByType(); }; @@ -246,25 +275,50 @@ function TcCommunityPlatforms() { /> - - - - ) : ( - 'Manage' - ) - } - variant='text' - onClick={() => handleManageHivemindModule()} - /> - - } - /> +
+ + + + ) : ( + 'Manage' + ) + } + variant='text' + onClick={() => handleManageHivemindModule()} + /> +
+ } + /> + + + + ) : ( + 'Manage' + ) + } + variant='text' + onClick={() => handleViolationDetectionModule()} + /> + + } + /> + ); diff --git a/src/pages/community-settings/violation-detection/index.tsx b/src/pages/community-settings/violation-detection/index.tsx new file mode 100644 index 00000000..03a07d0f --- /dev/null +++ b/src/pages/community-settings/violation-detection/index.tsx @@ -0,0 +1,276 @@ +/* eslint-disable react/jsx-key */ +import { + Alert, + AlertTitle, + Autocomplete, + Chip, + CircularProgress, + FormControl, + FormControlLabel, + FormHelperText, + FormLabel, + Switch, + TextField, + Typography, +} from '@mui/material'; +import router from 'next/router'; +import React, { useEffect, useState } from 'react'; + +import TcButton from '@/components/shared/TcButton'; + +import useAppStore from '@/store/useStore'; + +import { useSnackbar } from '@/context/SnackbarContext'; +import { useToken } from '@/context/TokenContext'; +import { StorageService } from '@/services/StorageService'; +import { IDiscordModifiedCommunity, IPlatformProps } from '@/utils/interfaces'; + +import SEO from '../../../components/global/SEO'; +import TcBoxContainer from '../../../components/shared/TcBox/TcBoxContainer'; +import TcBreadcrumbs from '../../../components/shared/TcBreadcrumbs'; +import { defaultLayout } from '../../../layouts/defaultLayout'; +import { withRoles } from '../../../utils/withRoles'; + +function Index() { + const { retrieveModules, patchModule } = useAppStore(); + const [isLoading, setIsLoading] = useState(false); + const [emails, setEmails] = useState([]); + const [activePlatform, setActivePlatform] = useState( + null + ); + const [violationModules, setViolationModules] = useState([]); + const [isViolationDetectionOn, setIsViolationDetectionOn] = + useState(false); + const [emailError, setEmailError] = useState(null); + + const { community } = useToken(); + const { showMessage } = useSnackbar(); + + const fetchDiscourseViolation = async () => { + const communityId = + StorageService.readLocalStorage( + 'community' + )?.id; + + const discoursePlatform = community?.platforms.find( + (platform) => + platform.name === 'discourse' && platform.disconnectedAt === null + ) as unknown as IPlatformProps; + + setActivePlatform(discoursePlatform); + + if (communityId) { + const { results } = await retrieveModules({ + community: communityId, + name: 'violationDetection', + }); + + setViolationModules(results); + + if (results.length > 0) { + setEmails( + results[0].options.platforms[0].metadata.selectedEmails || [] + ); + + const hasActiveModerators = + results[0].options.platforms[0].metadata.selectedEmails.length > 0; + setIsViolationDetectionOn(hasActiveModerators ? true : false); + } else { + setEmails([]); + setIsViolationDetectionOn(false); + } + } + }; + + useEffect(() => { + fetchDiscourseViolation(); + }, []); + + const validateEmail = (email: string) => { + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return emailRegex.test(email); + }; + + const handleEmailChange = (event: any, newValue: string[] | null) => { + if (newValue) { + const invalidEmail = newValue.find((email) => !validateEmail(email)); + if (invalidEmail) { + setEmailError(`Invalid email: ${invalidEmail}`); + } else { + setEmailError(null); + setEmails(newValue); + } + } + }; + + const handleDiscourseViolation = async () => { + if (!activePlatform) return; + + const updatedEmails = isViolationDetectionOn ? emails : []; + + const payload = { + platforms: [ + { + platform: activePlatform.id, + name: activePlatform.name, + metadata: { + selectedEmails: updatedEmails, + fromDate: activePlatform.metadata.period, + toDate: null, + selectedResources: [], + }, + }, + ], + }; + + try { + setIsLoading(true); + const data = await patchModule({ + moduleId: violationModules[0].id, + payload, + }); + + if (data) { + router.push('/community-settings'); + showMessage( + 'Violation detection settings updated successfully', + 'success' + ); + } + } catch (error) { + console.error('Error updating violation module:', error); + } finally { + setIsLoading(false); + } + }; + + return ( + <> + +
+ + +
+ + Violation Detection Settings + + + Configure the settings for the violation detection system. + This system will automatically detect and take action on any + violations of the community guidelines. You can configure the + system to automatically take action on violations or to notify + moderators for manual review. + + + Module working for discourse only + This module is currently only available for Discourse. + + + + + setIsViolationDetectionOn(event.target.checked) + } + /> + } + label='Violation Detection' + /> + + Activate/Deactivate the violation detection module. + + + + {isViolationDetectionOn && ( + + Moderator Emails + ( + + )} + options={[]} + renderTags={(value, getTagProps) => { + return value.map((option, index) => ( + + )); + }} + /> + + Enter the email addresses of the moderators who should be + notified when a violation is detected. + + + )} + +
+ router.push('/community-settings')} + /> + + ) : ( + 'Save Changes' + ) + } + disabled={isLoading || !!emailError} + variant='contained' + className='md:w-1/4' + onClick={handleDiscourseViolation} + /> +
+
+
+ } + /> + + + ); +} + +Index.pageLayout = defaultLayout; + +export default withRoles(Index, ['admin']);