Configure with i18n

api-accept
Justin 2 years ago
parent 86fb9bf704
commit 2607a55380

@ -6,7 +6,10 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { blockAccount } from 'soapbox/actions/accounts';
import { submitReport, cancelReport, submitReportSuccess, submitReportFail } from 'soapbox/actions/reports';
import { expandAccountTimeline } from 'soapbox/actions/timelines';
import { Modal, ProgressBar, Stack } from 'soapbox/components/ui';
import AttachmentThumbs from 'soapbox/components/attachment_thumbs';
import StatusContent from 'soapbox/components/status_content';
import { Modal, ProgressBar, Stack, Text } from 'soapbox/components/ui';
import AccountContainer from 'soapbox/containers/account_container';
import { useAccount, useAppDispatch, useAppSelector } from 'soapbox/hooks';
import ConfirmationStep from './steps/confirmation-step';
@ -14,6 +17,9 @@ import OtherActionsStep from './steps/other-actions-step';
import ReasonStep from './steps/reason-step';
const messages = defineMessages({
blankslate: { id: 'report.reason.blankslate', defaultMessage: 'You have removed all statuses from being selected.' },
done: { id: 'report.done', defaultMessage: 'Done' },
next: { id: 'report.next', defaultMessage: 'Next' },
close: { id: 'lightbox.close', defaultMessage: 'Close' },
placeholder: { id: 'report.placeholder', defaultMessage: 'Additional comments' },
submit: { id: 'report.submit', defaultMessage: 'Submit' },
@ -31,6 +37,39 @@ const reportSteps = {
THREE: ConfirmationStep,
};
const SelectedStatus = ({ statusId }: { statusId: string }) => {
const status = useAppSelector((state) => state.statuses.get(statusId));
if (!status) {
return null;
}
return (
<Stack space={2} className='p-4 rounded-lg bg-gray-100 dark:bg-slate-700'>
<AccountContainer
id={status.get('account') as any}
showProfileHoverCard={false}
timestamp={status.get('created_at')}
hideActions
/>
<StatusContent
status={status}
expanded
collapsable
/>
{status.get('media_attachments').size > 0 && (
<AttachmentThumbs
compact
media={status.get('media_attachments')}
sensitive={status.get('sensitive')}
/>
)}
</Stack>
);
};
interface IReportModal {
onClose: () => void
}
@ -84,14 +123,27 @@ const ReportModal = ({ onClose }: IReportModal) => {
}
};
const renderSelectedStatuses = useCallback(() => {
switch (selectedStatusIds.size) {
case 0:
return (
<div className='bg-gray-100 dark:bg-slate-700 p-4 rounded-lg flex items-center justify-center w-full'>
<Text theme='muted'>{intl.formatMessage(messages.blankslate)}</Text>
</div>
);
default:
return <SelectedStatus statusId={selectedStatusIds.first()} />;
}
}, [selectedStatusIds.size]);
const confirmationText = useMemo(() => {
switch (currentStep) {
case Steps.TWO:
return intl.formatMessage(messages.submit);
case Steps.THREE:
return 'Done';
return intl.formatMessage(messages.done);
default:
return 'Next';
return intl.formatMessage(messages.next);
}
}, [currentStep]);
@ -141,6 +193,8 @@ const ReportModal = ({ onClose }: IReportModal) => {
<Stack space={4}>
<ProgressBar progress={calculateProgress()} />
{currentStep !== Steps.THREE && renderSelectedStatuses()}
<StepToRender account={account} />
</Stack>
</Modal>

@ -1,23 +1,52 @@
import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { getSoapboxConfig } from 'soapbox/actions/soapbox';
import { Stack, Text } from 'soapbox/components/ui';
import { useAppSelector } from 'soapbox/hooks';
import type { ReducerAccount } from 'soapbox/reducers/accounts';
const messages = defineMessages({
title: { id: 'report.confirmation.title', defaultMessage: 'Thanks for submitting your report.' },
content: { id: 'report.confirmation.content', defaultMessage: 'If we find that this account is violating the {link} we will take further action on the matter.' },
});
interface IOtherActionsStep {
account: ReducerAccount
}
const termsOfServiceText = (<FormattedMessage
id='shared.tos'
defaultMessage='Terms of Service'
/>);
const renderTermsOfServiceLink = (href: string) => (
<a
href={href}
target='_blank'
className='hover:underline text-primary-600 dark:text-primary-400 hover:text-primary-800 dark:hover:text-primary-500'
>
{termsOfServiceText}
</a>
);
const ConfirmationStep = ({ account }: IOtherActionsStep) => {
const intl = useIntl();
const links = useAppSelector((state) => getSoapboxConfig(state).get('links') as any);
return (
<Stack space={1}>
<Text weight='semibold' tag='h1' size='xl'>
Thanks for submitting your report.
{intl.formatMessage(messages.title)}
</Text>
<Text>
If we find that this account is violating the TRUTH Terms of Service we
will take further action on the matter.
{intl.formatMessage(messages.content, {
link: links.get('termsOfService') ?
renderTermsOfServiceLink(links.get('termsOfService')) :
termsOfServiceText,
})}
</Text>
</Stack>
);

@ -1,53 +1,25 @@
import { OrderedSet, Set as ImmutableSet } from 'immutable';
import React, { useCallback, useEffect, useState } from 'react';
import { FormattedMessage } from 'react-intl';
import { OrderedSet } from 'immutable';
import React, { useEffect, useState } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { useDispatch } from 'react-redux';
import Toggle from 'react-toggle';
import { changeReportBlock, changeReportForward } from 'soapbox/actions/reports';
import { fetchRules } from 'soapbox/actions/rules';
import AttachmentThumbs from 'soapbox/components/attachment_thumbs';
import StatusContent from 'soapbox/components/status_content';
import { Button, FormGroup, HStack, Stack, Text } from 'soapbox/components/ui';
import AccountContainer from 'soapbox/containers/account_container';
import StatusCheckBox from 'soapbox/features/report/containers/status_check_box_container';
import { useAppSelector, useFeatures } from 'soapbox/hooks';
import { isRemote, getDomain } from 'soapbox/utils/accounts';
import type { ReducerAccount } from 'soapbox/reducers/accounts';
const SelectedStatus = ({ statusId }: { statusId: string }) => {
const status = useAppSelector((state) => state.statuses.get(statusId));
if (!status) {
return null;
}
return (
<Stack space={2} className='p-4 rounded-lg bg-gray-100 dark:bg-slate-700'>
<AccountContainer
id={status.get('account') as any}
showProfileHoverCard={false}
timestamp={status.get('created_at')}
hideActions
/>
<StatusContent
status={status}
expanded
collapsable
/>
{status.get('media_attachments').size > 0 && (
<AttachmentThumbs
compact
media={status.get('media_attachments')}
sensitive={status.get('sensitive')}
/>
)}
</Stack>
);
};
const messages = defineMessages({
addAdditionalStatuses: { id: 'report.otherActions.addAdditionl', defaultMessage: 'Would you like to add additional statuses to this report?' },
addMore: { id: 'report.otherActions.addMore', defaultMessage: 'Add more' },
furtherActions: { id: 'report.otherActions.furtherActions', defaultMessage: 'Further actions:' },
hideAdditonalStatuses: { id: 'report.otherActions.hideAdditional', defaultMessage: 'Hide additional statuses' },
otherStatuses: { id: 'report.otherActions.otherStatuses', defaultMessage: 'Include other statuses?' },
});
interface IOtherActionsStep {
account: ReducerAccount
@ -56,8 +28,8 @@ interface IOtherActionsStep {
const OtherActionsStep = ({ account }: IOtherActionsStep) => {
const dispatch = useDispatch();
const features = useFeatures();
const intl = useIntl();
const selectedStatusIds = useAppSelector((state) => state.reports.getIn(['new', 'status_ids']) as ImmutableSet<string>);
const statusIds = useAppSelector((state) => OrderedSet(state.timelines.getIn([`account:${account.id}:with_replies`, 'items'])).union(state.reports.getIn(['new', 'status_ids']) as Iterable<unknown>) as OrderedSet<string>);
const isBlocked = useAppSelector((state) => state.reports.getIn(['new', 'block']) as boolean);
const isForward = useAppSelector((state) => state.reports.getIn(['reports', 'forward']) as boolean);
@ -66,19 +38,6 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => {
const [showAdditionalStatuses, setShowAdditionalStatuses] = useState<boolean>(false);
const renderSelectedStatuses = useCallback(() => {
switch (selectedStatusIds.size) {
case 0:
return (
<div className='bg-gray-100 dark:bg-slate-700 p-4 rounded-lg flex items-center justify-center w-full'>
<Text theme='muted'>You have removed all statuses from being selected.</Text>
</div>
);
default:
return <SelectedStatus statusId={selectedStatusIds.first()} />;
}
}, [selectedStatusIds.size]);
const handleBlockChange = (event: React.ChangeEvent<HTMLInputElement>) => {
dispatch(changeReportBlock(event.target.checked));
};
@ -93,15 +52,13 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => {
return (
<Stack space={4}>
{renderSelectedStatuses()}
{features.reportMultipleStatuses && (
<Stack space={2}>
<Text tag='h1' size='xl' weight='semibold'>Include other statuses?</Text>
<Text tag='h1' size='xl' weight='semibold'>
{intl.formatMessage(messages.otherStatuses)}
</Text>
<FormGroup
labelText='Would you like to add additional statuses to this report?'
>
<FormGroup labelText={intl.formatMessage(messages.addAdditionalStatuses)}>
{showAdditionalStatuses ? (
<Stack space={2}>
<div className='bg-gray-100 rounded-lg p-4'>
@ -115,7 +72,7 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => {
size='sm'
onClick={() => setShowAdditionalStatuses(false)}
>
Hide additional statuses
{intl.formatMessage(messages.hideAdditonalStatuses)}
</Button>
</div>
</Stack>
@ -126,7 +83,7 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => {
size='sm'
onClick={() => setShowAdditionalStatuses(true)}
>
Add more
{intl.formatMessage(messages.addMore)}
</Button>
)}
</FormGroup>
@ -134,7 +91,9 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => {
)}
<Stack space={2}>
<Text tag='h1' size='xl' weight='semibold'>Further actions:</Text>
<Text tag='h1' size='xl' weight='semibold'>
{intl.formatMessage(messages.furtherActions)}
</Text>
<FormGroup
labelText={<FormattedMessage id='report.block_hint' defaultMessage='Do you also want to block this account?' />}

@ -1,56 +1,20 @@
import classNames from 'classnames';
import { Set as ImmutableSet } from 'immutable';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useDispatch } from 'react-redux';
import { changeReportComment, changeReportRule } from 'soapbox/actions/reports';
import { fetchRules } from 'soapbox/actions/rules';
import AttachmentThumbs from 'soapbox/components/attachment_thumbs';
import StatusContent from 'soapbox/components/status_content';
import { FormGroup, HStack, Stack, Text, Textarea } from 'soapbox/components/ui';
import AccountContainer from 'soapbox/containers/account_container';
import { FormGroup, Stack, Text, Textarea } from 'soapbox/components/ui';
import { useAppSelector } from 'soapbox/hooks';
import type { ReducerAccount } from 'soapbox/reducers/accounts';
const messages = defineMessages({
placeholder: { id: 'report.placeholder', defaultMessage: 'Additional comments' },
reasonForReporting: { id: 'report.reason.title', defaultMessage: 'Reason for reporting' },
});
const SelectedStatus = ({ statusId }: { statusId: string }) => {
const status = useAppSelector((state) => state.statuses.get(statusId));
if (!status) {
return null;
}
return (
<Stack space={2} className='p-4 rounded-lg bg-gray-100 dark:bg-slate-700'>
<AccountContainer
id={status.get('account') as any}
showProfileHoverCard={false}
timestamp={status.get('created_at')}
hideActions
/>
<StatusContent
status={status}
expanded
collapsable
/>
{status.get('media_attachments').size > 0 && (
<AttachmentThumbs
compact
media={status.get('media_attachments')}
sensitive={status.get('sensitive')}
/>
)}
</Stack>
);
};
interface IReasonStep {
account: ReducerAccount
}
@ -64,25 +28,11 @@ const ReasonStep = (_props: IReasonStep) => {
const [isNearBottom, setNearBottom] = useState<boolean>(false);
const [isNearTop, setNearTop] = useState<boolean>(true);
const selectedStatusIds = useAppSelector((state) => state.reports.getIn(['new', 'status_ids']) as ImmutableSet<string>);
const comment = useAppSelector((state) => state.reports.getIn(['new', 'comment']) as string);
const rules = useAppSelector((state) => state.rules.items);
const ruleId = useAppSelector((state) => state.reports.getIn(['new', 'rule_id']) as boolean);
const shouldRequireRule = rules.length > 0;
const renderSelectedStatuses = useCallback(() => {
switch (selectedStatusIds.size) {
case 0:
return (
<div className='bg-gray-100 dark:bg-slate-700 p-4 rounded-lg flex items-center justify-center w-full'>
<Text theme='muted'>You have removed all statuses from being selected.</Text>
</div>
);
default:
return <SelectedStatus statusId={selectedStatusIds.first()} />;
}
}, [selectedStatusIds.size]);
const handleCommentChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
dispatch(changeReportComment(event.target.value));
};
@ -111,11 +61,11 @@ const ReasonStep = (_props: IReasonStep) => {
return (
<Stack space={4}>
{renderSelectedStatuses()}
{shouldRequireRule && (
<Stack space={2}>
<Text size='xl' weight='semibold' tag='h1'>Reason for reporting</Text>
<Text size='xl' weight='semibold' tag='h1'>
{intl.formatMessage(messages.reasonForReporting)}
</Text>
<div className='relative'>
<div
@ -138,16 +88,17 @@ const ReasonStep = (_props: IReasonStep) => {
'bg-gray-50 dark:bg-slate-900': isSelected,
})}
>
<div className='mr-3 flex flex-col'>
<Stack className='mr-3'>
<Text
tag='span'
size='sm'
weight='medium'
theme={isSelected ? 'primary' : 'default'}
>
{rule.text}
</Text>
<Text theme='muted' size='sm'>{rule.subtext}</Text>
</div>
<Text tag='span' theme='muted' size='sm'>{rule.subtext}</Text>
</Stack>
<input
name='reason'

@ -920,6 +920,7 @@
"settings.save.success": "Your preferences have been saved!",
"settings.security": "Security",
"settings.settings": "Settings",
"shared.tos": "Terms of Service",
"signup_panel.subtitle": "Sign up now to discuss.",
"signup_panel.title": "New to {site_title}?",
"snackbar.view": "View",

Loading…
Cancel
Save