bigbuffet-rw/app/soapbox/features/admin/components/report.tsx

159 lines
5.2 KiB
TypeScript
Raw Normal View History

import React, { useCallback, useState } from 'react';
2022-04-28 11:35:52 -07:00
import { useIntl, FormattedMessage, defineMessages } from 'react-intl';
import { Link } from 'react-router-dom';
import { closeReports } from 'soapbox/actions/admin';
import { deactivateUserModal, deleteUserModal } from 'soapbox/actions/moderation';
2022-11-15 12:46:23 -08:00
import HoverRefWrapper from 'soapbox/components/hover-ref-wrapper';
import { Accordion, Avatar, Button, Stack, HStack, Text } from 'soapbox/components/ui';
2022-11-15 08:13:54 -08:00
import DropdownMenu from 'soapbox/containers/dropdown-menu-container';
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
import { makeGetReport } from 'soapbox/selectors';
2022-12-20 07:47:46 -08:00
import toast from 'soapbox/toast';
2022-04-28 11:35:52 -07:00
2022-11-15 09:23:36 -08:00
import ReportStatus from './report-status';
2022-04-28 11:35:52 -07:00
import type { List as ImmutableList } from 'immutable';
import type { Account, AdminReport, Status } from 'soapbox/types/entities';
2022-04-28 11:35:52 -07:00
const messages = defineMessages({
reportClosed: { id: 'admin.reports.report_closed_message', defaultMessage: 'Report on @{name} was closed' },
deactivateUser: { id: 'admin.users.actions.deactivate_user', defaultMessage: 'Deactivate @{name}' },
deleteUser: { id: 'admin.users.actions.delete_user', defaultMessage: 'Delete @{name}' },
});
interface IReport {
id: string;
2022-04-28 11:35:52 -07:00
}
const Report: React.FC<IReport> = ({ id }) => {
2022-04-28 11:35:52 -07:00
const intl = useIntl();
const dispatch = useAppDispatch();
const getReport = useCallback(makeGetReport(), []);
const report = useAppSelector((state) => getReport(state, id) as AdminReport | undefined);
2022-04-28 11:35:52 -07:00
const [accordionExpanded, setAccordionExpanded] = useState(false);
if (!report) return null;
const account = report.account as Account;
const targetAccount = report.target_account as Account;
2022-04-28 11:35:52 -07:00
const makeMenu = () => {
return [{
text: intl.formatMessage(messages.deactivateUser, { name: targetAccount.username }),
2022-04-28 11:35:52 -07:00
action: handleDeactivateUser,
icon: require('@tabler/icons/hourglass-empty.svg'),
2022-04-28 11:35:52 -07:00
}, {
text: intl.formatMessage(messages.deleteUser, { name: targetAccount.username }),
2022-04-28 11:35:52 -07:00
action: handleDeleteUser,
icon: require('@tabler/icons/trash.svg'),
destructive: true,
2022-04-28 11:35:52 -07:00
}];
};
const handleCloseReport = () => {
dispatch(closeReports([report.id])).then(() => {
const message = intl.formatMessage(messages.reportClosed, { name: targetAccount.username as string });
2022-12-20 07:47:46 -08:00
toast.success(message);
2022-04-28 11:35:52 -07:00
}).catch(() => {});
};
const handleDeactivateUser = () => {
const accountId = targetAccount.id;
2022-04-28 11:35:52 -07:00
dispatch(deactivateUserModal(intl, accountId, () => handleCloseReport()));
};
const handleDeleteUser = () => {
const accountId = targetAccount.id as string;
2022-04-28 11:35:52 -07:00
dispatch(deleteUserModal(intl, accountId, () => handleCloseReport()));
};
const handleAccordionToggle = (setting: boolean) => {
setAccordionExpanded(setting);
};
const menu = makeMenu();
const statuses = report.statuses as ImmutableList<Status>;
2022-04-28 11:35:52 -07:00
const statusCount = statuses.count();
const acct = targetAccount.acct as string;
const reporterAcct = account.acct as string;
2022-04-28 11:35:52 -07:00
return (
2022-11-27 11:12:40 -08:00
<HStack space={3} className='p-3' key={report.id}>
<HoverRefWrapper accountId={targetAccount.id} inline>
<Link to={`/@${acct}`} title={acct}>
<Avatar src={targetAccount.avatar} size={32} className='overflow-hidden' />
2022-11-27 11:12:40 -08:00
</Link>
</HoverRefWrapper>
2022-11-28 07:41:19 -08:00
<Stack space={3} className='overflow-hidden' grow>
<Text tag='h4' weight='bold'>
2022-04-28 11:35:52 -07:00
<FormattedMessage
id='admin.reports.report_title'
defaultMessage='Report on {acct}'
2022-04-28 19:55:02 -07:00
values={{ acct: (
2022-11-27 11:12:40 -08:00
<HoverRefWrapper accountId={account.id} inline>
2022-04-28 19:55:02 -07:00
<Link to={`/@${acct}`} title={acct}>@{acct}</Link>
</HoverRefWrapper>
) }}
2022-04-28 11:35:52 -07:00
/>
2022-11-27 11:12:40 -08:00
</Text>
{statusCount > 0 && (
<Accordion
headline={`Reported posts (${statusCount})`}
expanded={accordionExpanded}
onToggle={handleAccordionToggle}
>
<Stack space={4}>
{statuses.map(status => (
<ReportStatus
key={status.id}
report={report}
status={status}
/>
))}
</Stack>
</Accordion>
)}
<Stack>
{(report.comment || '').length > 0 && (
2022-11-27 11:12:40 -08:00
<Text
tag='blockquote'
dangerouslySetInnerHTML={{ __html: report.comment }}
/>
2022-04-28 19:36:28 -07:00
)}
2022-11-27 11:12:40 -08:00
<HStack space={1}>
<Text theme='muted' tag='span'>&mdash;</Text>
<HoverRefWrapper accountId={account.id} inline>
<Link
to={`/@${reporterAcct}`}
title={reporterAcct}
className='text-primary-600 dark:text-accent-blue hover:underline'
>
@{reporterAcct}
</Link>
2022-04-28 19:55:02 -07:00
</HoverRefWrapper>
2022-11-27 11:12:40 -08:00
</HStack>
</Stack>
</Stack>
<HStack space={2} alignItems='start' className='flex-none'>
2022-04-28 11:35:52 -07:00
<Button onClick={handleCloseReport}>
<FormattedMessage id='admin.reports.actions.close' defaultMessage='Close' />
</Button>
<DropdownMenu items={menu} src={require('@tabler/icons/dots-vertical.svg')} />
2022-04-28 19:36:28 -07:00
</HStack>
2022-11-27 11:12:40 -08:00
</HStack>
2022-04-28 11:35:52 -07:00
);
};
export default Report;