Merge branch 'delete-modal-fix' into 'develop'

Fix account deletion modal

See merge request soapbox-pub/soapbox!1794
This commit is contained in:
Alex Gleason 2022-09-17 21:33:37 +00:00
commit 1e6993975c
6 changed files with 96 additions and 64 deletions

View file

@ -5,6 +5,8 @@ import { fetchAccountByUsername } from 'soapbox/actions/accounts';
import { deactivateUsers, deleteUsers, deleteStatus, toggleStatusSensitivity } from 'soapbox/actions/admin'; import { deactivateUsers, deleteUsers, deleteStatus, toggleStatusSensitivity } from 'soapbox/actions/admin';
import { openModal } from 'soapbox/actions/modals'; import { openModal } from 'soapbox/actions/modals';
import snackbar from 'soapbox/actions/snackbar'; import snackbar from 'soapbox/actions/snackbar';
import OutlineBox from 'soapbox/components/outline-box';
import { Stack, Text } from 'soapbox/components/ui';
import AccountContainer from 'soapbox/containers/account_container'; import AccountContainer from 'soapbox/containers/account_container';
import { isLocal } from 'soapbox/utils/accounts'; import { isLocal } from 'soapbox/utils/accounts';
@ -43,10 +45,22 @@ const deactivateUserModal = (intl: IntlShape, accountId: string, afterConfirm =
const acct = state.accounts.get(accountId)!.acct; const acct = state.accounts.get(accountId)!.acct;
const name = state.accounts.get(accountId)!.username; const name = state.accounts.get(accountId)!.username;
const message = (
<Stack space={4}>
<OutlineBox>
<AccountContainer id={accountId} />
</OutlineBox>
<Text>
{intl.formatMessage(messages.deactivateUserPrompt, { acct })}
</Text>
</Stack>
);
dispatch(openModal('CONFIRM', { dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/user-off.svg'), icon: require('@tabler/icons/user-off.svg'),
heading: intl.formatMessage(messages.deactivateUserHeading, { acct }), heading: intl.formatMessage(messages.deactivateUserHeading, { acct }),
message: intl.formatMessage(messages.deactivateUserPrompt, { acct }), message,
confirm: intl.formatMessage(messages.deactivateUserConfirm, { name }), confirm: intl.formatMessage(messages.deactivateUserConfirm, { name }),
onConfirm: () => { onConfirm: () => {
dispatch(deactivateUsers([accountId])).then(() => { dispatch(deactivateUsers([accountId])).then(() => {
@ -64,22 +78,21 @@ const deleteUserModal = (intl: IntlShape, accountId: string, afterConfirm = () =
const account = state.accounts.get(accountId)!; const account = state.accounts.get(accountId)!;
const acct = account.acct; const acct = account.acct;
const name = account.username; const name = account.username;
const favicon = account.pleroma.get('favicon');
const local = isLocal(account); const local = isLocal(account);
const message = (<> const message = (
<AccountContainer id={accountId} /> <Stack space={4}>
{intl.formatMessage(messages.deleteUserPrompt, { acct })} <OutlineBox>
</>); <AccountContainer id={accountId} />
</OutlineBox>
const confirm = (<> <Text>
{favicon && {intl.formatMessage(messages.deleteUserPrompt, { acct })}
<div className='submit__favicon'> </Text>
<img src={favicon} alt='' /> </Stack>
</div>} );
{intl.formatMessage(messages.deleteUserConfirm, { name })}
</>);
const confirm = intl.formatMessage(messages.deleteUserConfirm, { name });
const checkbox = local ? intl.formatMessage(messages.deleteLocalUserCheckbox) : false; const checkbox = local ? intl.formatMessage(messages.deleteLocalUserCheckbox) : false;
dispatch(openModal('CONFIRM', { dispatch(openModal('CONFIRM', {

View file

@ -0,0 +1,21 @@
import classNames from 'clsx';
import React from 'react';
interface IOutlineBox extends React.HTMLAttributes<HTMLDivElement> {
children: React.ReactNode,
className?: string,
}
/** Wraps children in a container with an outline. */
const OutlineBox: React.FC<IOutlineBox> = ({ children, className, ...rest }) => {
return (
<div
className={classNames('p-4 rounded-lg border border-solid border-gray-300 dark:border-gray-800', className)}
{...rest}
>
{children}
</div>
);
};
export default OutlineBox;

View file

@ -9,6 +9,8 @@ import AccountContainer from 'soapbox/containers/account_container';
import { useSettings } from 'soapbox/hooks'; import { useSettings } from 'soapbox/hooks';
import { defaultMediaVisibility } from 'soapbox/utils/status'; import { defaultMediaVisibility } from 'soapbox/utils/status';
import OutlineBox from './outline-box';
import type { Account as AccountEntity, Status as StatusEntity } from 'soapbox/types/entities'; import type { Account as AccountEntity, Status as StatusEntity } from 'soapbox/types/entities';
const messages = defineMessages({ const messages = defineMessages({
@ -123,38 +125,41 @@ const QuotedStatus: React.FC<IQuotedStatus> = ({ status, onCancel, compose }) =>
} }
return ( return (
<Stack <OutlineBox
data-testid='quoted-status' data-testid='quoted-status'
space={2} className={classNames('mt-3 cursor-pointer', {
className={classNames('mt-3 p-4 rounded-lg border border-solid border-gray-300 dark:border-gray-800 cursor-pointer', {
'hover:bg-gray-100 dark:hover:bg-gray-800': !compose, 'hover:bg-gray-100 dark:hover:bg-gray-800': !compose,
})} })}
onClick={handleExpandClick}
> >
<AccountContainer <Stack
{...actions} space={2}
id={account.id} onClick={handleExpandClick}
timestamp={status.created_at} >
withRelationship={false} <AccountContainer
showProfileHoverCard={!compose} {...actions}
withLinkToProfile={!compose} id={account.id}
/> timestamp={status.created_at}
withRelationship={false}
showProfileHoverCard={!compose}
withLinkToProfile={!compose}
/>
{renderReplyMentions()} {renderReplyMentions()}
<Text <Text
className='break-words status__content status__content--quote' className='break-words status__content status__content--quote'
size='sm' size='sm'
dangerouslySetInnerHTML={{ __html: status.contentHtml }} dangerouslySetInnerHTML={{ __html: status.contentHtml }}
/> />
<StatusMedia <StatusMedia
status={status} status={status}
muted={compose} muted={compose}
showMedia={showMedia} showMedia={showMedia}
onToggleVisibility={handleToggleMediaVisibility} onToggleVisibility={handleToggleMediaVisibility}
/> />
</Stack> </Stack>
</OutlineBox>
); );
}; };

View file

@ -1,8 +1,8 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import { Modal, Text } from 'soapbox/components/ui'; import List, { ListItem } from 'soapbox/components/list';
import { SimpleForm, FieldsGroup, Checkbox } from 'soapbox/features/forms'; import { Modal, Stack, Text, Toggle } from 'soapbox/components/ui';
interface IConfirmationModal { interface IConfirmationModal {
heading: React.ReactNode, heading: React.ReactNode,
@ -60,23 +60,23 @@ const ConfirmationModal: React.FC<IConfirmationModal> = ({
secondaryText={secondary} secondaryText={secondary}
secondaryAction={onSecondary && handleSecondary} secondaryAction={onSecondary && handleSecondary}
> >
<Text> <Stack space={4}>
{message} <Text>
</Text> {message}
</Text>
<div className='mt-2'> {checkbox && (
{checkbox && <div className='confirmation-modal__checkbox'> <List>
<SimpleForm> <ListItem label={checkbox}>
<FieldsGroup> <Toggle
<Checkbox
onChange={handleCheckboxChange}
label={checkbox}
checked={checked} checked={checked}
onChange={handleCheckboxChange}
required
/> />
</FieldsGroup> </ListItem>
</SimpleForm> </List>
</div>} )}
</div> </Stack>
</Modal> </Modal>
); );
}; };

View file

@ -13,6 +13,7 @@ import snackbar from 'soapbox/actions/snackbar';
import Account from 'soapbox/components/account'; import Account from 'soapbox/components/account';
import List, { ListItem } from 'soapbox/components/list'; import List, { ListItem } from 'soapbox/components/list';
import MissingIndicator from 'soapbox/components/missing_indicator'; import MissingIndicator from 'soapbox/components/missing_indicator';
import OutlineBox from 'soapbox/components/outline-box';
import { Button, Text, HStack, Modal, Stack, Toggle } from 'soapbox/components/ui'; import { Button, Text, HStack, Modal, Stack, Toggle } from 'soapbox/components/ui';
import { useAppDispatch, useAppSelector, useFeatures, useOwnAccount } from 'soapbox/hooks'; import { useAppDispatch, useAppSelector, useFeatures, useOwnAccount } from 'soapbox/hooks';
import { makeGetAccount } from 'soapbox/selectors'; import { makeGetAccount } from 'soapbox/selectors';
@ -109,14 +110,14 @@ const AccountModerationModal: React.FC<IAccountModerationModal> = ({ onClose, ac
onClose={handleClose} onClose={handleClose}
> >
<Stack space={4}> <Stack space={4}>
<div className='p-4 rounded-lg border border-solid border-gray-300 dark:border-gray-800'> <OutlineBox>
<Account <Account
account={account} account={account}
showProfileHoverCard={false} showProfileHoverCard={false}
withLinkToProfile={false} withLinkToProfile={false}
hideActions hideActions
/> />
</div> </OutlineBox>
<List> <List>
{(ownAccount.admin && isLocal(account)) && ( {(ownAccount.admin && isLocal(account)) && (

View file

@ -331,14 +331,6 @@
} }
} }
.confirmation-modal__checkbox {
padding: 0 30px;
.simple_form {
margin-top: -14px;
}
}
.reply-mentions-modal__accounts { .reply-mentions-modal__accounts {
display: block; display: block;
flex-direction: row; flex-direction: row;