Skip to content

Commit

Permalink
feat: ✨ Implement label tooltip in the user creation page email field
Browse files Browse the repository at this point in the history
Implemented a tooltip in the email verification field of the user creation contextual bar that explains what toggling on this field will do. Also implemented a way to use a single value in order to controll the setRandomPassword radios instead of two and added the necessary entries in the i18n to follow the aforementioned changes.
  • Loading branch information
rique223 committed Oct 11, 2023
1 parent 28ececa commit 35a1e49
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 46 deletions.
59 changes: 37 additions & 22 deletions apps/meteor/client/views/admin/users/AdminUserForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
FieldRow,
FieldError,
FieldHint,
Icon,
} from '@rocket.chat/fuselage';
import type { SelectOption } from '@rocket.chat/fuselage';
import { useUniqueId, useMutableCallback } from '@rocket.chat/fuselage-hooks';
Expand Down Expand Up @@ -48,10 +49,7 @@ type AdminUserFormProps = {
setCreatedUsersCount: React.Dispatch<React.SetStateAction<number>>;
};

export type userFormProps = Omit<
UserCreateParamsPOST & { setPasswordManually: boolean; avatar: AvatarObject; passwordConfirmation: string },
'fields'
>;
export type userFormProps = Omit<UserCreateParamsPOST & { avatar: AvatarObject; passwordConfirmation: string }, 'fields'>;

const getInitialValue = ({
data,
Expand All @@ -72,8 +70,7 @@ const getInitialValue = ({
nickname: data?.nickname ?? '',
email: (data?.emails?.length && data.emails[0].address) || '',
verified: (data?.emails?.length && data.emails[0].verified) || false,
setRandomPassword: isNewUserPage,
setPasswordManually: !isNewUserPage,
setRandomPassword: isNewUserPage && isSmtpEnabled,
requirePasswordChange: data?.requirePasswordChange || false,
customFields: data?.customFields ?? {},
statusText: data?.statusText ?? '',
Expand All @@ -93,6 +90,7 @@ const UserForm = ({ userData, onReload, setCreatedUsersCount, ...props }: AdminU
const requiresPasswordConfirmation = useSetting('Accounts_RequirePasswordConfirmation');
const passwordPlaceholder = String(useSetting('Accounts_PasswordPlaceholder'));
const passwordConfirmationPlaceholder = String(useSetting('Accounts_ConfirmPasswordPlaceholder'));
const isVerificationNeeded = useSetting('Accounts_EmailVerification');

const defaultUserRoles = parseCSV(defaultRoles);
const { data } = useSmtpQuery();
Expand All @@ -103,7 +101,6 @@ const UserForm = ({ userData, onReload, setCreatedUsersCount, ...props }: AdminU
watch,
handleSubmit,
formState: { errors, isDirty },
setValue,
resetField,
} = useForm({
defaultValues: getInitialValue({ data: userData, defaultUserRoles, isSmtpEnabled, isNewUserPage: !userData?._id }),
Expand All @@ -115,6 +112,11 @@ const UserForm = ({ userData, onReload, setCreatedUsersCount, ...props }: AdminU
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isSmtpEnabled]);

useEffect(() => {
resetField('setRandomPassword', { defaultValue: !userData?._id && isSmtpEnabled });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isSmtpEnabled, userData?._id]);

const eventStats = useEndpointAction('POST', '/v1/statistics.telemetry');
const updateUserAction = useEndpoint('POST', '/v1/users.update');
const createUserAction = useEndpoint('POST', '/v1/users.create');
Expand Down Expand Up @@ -158,7 +160,7 @@ const UserForm = ({ userData, onReload, setCreatedUsersCount, ...props }: AdminU
});

const handleSaveUser = useMutableCallback(async (userFormPayload: userFormProps) => {
const { avatar, setPasswordManually, passwordConfirmation, ...userFormData } = userFormPayload;
const { avatar, passwordConfirmation, ...userFormData } = userFormPayload;
if (userData?._id) {
return handleUpdateUser.mutateAsync({ userId: userData?._id, data: userFormData });
}
Expand Down Expand Up @@ -232,15 +234,33 @@ const UserForm = ({ userData, onReload, setCreatedUsersCount, ...props }: AdminU
</FieldError>
)}
<FieldRow mbs={12}>
<FieldLabel htmlFor={verifiedId} p={0}>
{t('Mark_email_as_verified')}
</FieldLabel>
<Box display='flex' alignItems='center'>
<FieldLabel htmlFor={verifiedId} p={0} disabled={!isSmtpEnabled || !isVerificationNeeded}>
{t('Mark_email_as_verified')}
</FieldLabel>
<Icon name='info-circled' size='x21' mis={8} title={t('Activate_to_bypass_email_verification')} color='default' />
</Box>
<Controller
control={control}
name='verified'
render={({ field: { onChange, value } }) => <ToggleSwitch id={verifiedId} checked={value} onChange={onChange} />}
render={({ field: { onChange, value } }) => (
<ToggleSwitch id={verifiedId} checked={value} onChange={onChange} disabled={!isSmtpEnabled || !isVerificationNeeded} />
)}
/>
</FieldRow>
{/* <FieldHint id={`${verifiedId}-hint`} dangerouslySetInnerHTML={{ __html: t('Activate_to_bypass_email_verification') }} /> */}
{isVerificationNeeded && !isSmtpEnabled && (
<FieldHint
id={`${verifiedId}-hint`}
dangerouslySetInnerHTML={{ __html: t('Send_Email_SMTP_Warning', { url: 'admin/settings/Email' }) }}
/>
)}
{!isVerificationNeeded && (
<FieldHint
id={`${verifiedId}-hint`}
dangerouslySetInnerHTML={{ __html: t('Email_verification_isnt_required', { url: 'admin/settings/Accounts' }) }}
/>
)}
</Field>
<Field>
<FieldLabel htmlFor={nameId}>{t('Name')}</FieldLabel>
Expand Down Expand Up @@ -300,15 +320,7 @@ const UserForm = ({ userData, onReload, setCreatedUsersCount, ...props }: AdminU
setRandomPasswordId={setRandomPasswordId}
control={control}
isSmtpEnabled={isSmtpEnabled || false}
setRandomPassword={setRandomPassword || false}
setValue={setValue}
/>
{!isSmtpEnabled && (
<FieldHint
id={`${setRandomPasswordId}-hint`}
dangerouslySetInnerHTML={{ __html: t('Send_Email_SMTP_Warning', { url: 'admin/settings/Email' }) }}
/>
)}
{!setRandomPassword && (
<>
<Box display='flex' flexDirection='row' alignItems='center' justifyContent='space-between' flexGrow={1} mbe={8} mbs={12}>
Expand Down Expand Up @@ -424,8 +436,10 @@ const UserForm = ({ userData, onReload, setCreatedUsersCount, ...props }: AdminU
</Box>
</Field>
<Field>
<Box display='flex' flexDirection='row' alignItems='center' justifyContent='space-between' flexGrow={1}>
<FieldLabel htmlFor={sendWelcomeEmailId}>{t('Send_welcome_email')}</FieldLabel>
<Box display='flex' flexDirection='row' alignItems='center' justifyContent='space-between' flexGrow={1} mbe={8}>
<FieldLabel htmlFor={sendWelcomeEmailId} disabled={!isSmtpEnabled}>
{t('Send_welcome_email')}
</FieldLabel>
<FieldRow>
<Controller
control={control}
Expand All @@ -446,6 +460,7 @@ const UserForm = ({ userData, onReload, setCreatedUsersCount, ...props }: AdminU
<FieldHint
id={`${sendWelcomeEmailId}-hint`}
dangerouslySetInnerHTML={{ __html: t('Send_Email_SMTP_Warning', { url: 'admin/settings/Email' }) }}
mbs={0}
/>
)}
</Field>
Expand Down
39 changes: 16 additions & 23 deletions apps/meteor/client/views/admin/users/AdminUserSetRandomPassword.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
import { Box, FieldLabel, FieldRow, RadioButton } from '@rocket.chat/fuselage';
import { Box, FieldHint, FieldLabel, FieldRow, RadioButton } from '@rocket.chat/fuselage';
import { useUniqueId } from '@rocket.chat/fuselage-hooks';
import { useTranslation } from '@rocket.chat/ui-contexts';
import React from 'react';
import type { Control, UseFormSetValue } from 'react-hook-form';
import type { Control } from 'react-hook-form';
import { Controller } from 'react-hook-form';

import type { userFormProps } from './AdminUserForm';

type AdminUserSetRandomPasswordProps = {
control: Control<userFormProps, any>;
isSmtpEnabled: boolean;
setRandomPassword: boolean;
setValue: UseFormSetValue<userFormProps>;
setRandomPasswordId: string;
};

const AdminUserSetRandomPassword = ({
control,
isSmtpEnabled,
setRandomPassword,
setValue,
setRandomPasswordId,
}: AdminUserSetRandomPasswordProps) => {
const AdminUserSetRandomPassword = ({ control, isSmtpEnabled, setRandomPasswordId }: AdminUserSetRandomPasswordProps) => {
const t = useTranslation();

const setPasswordManuallyId = useUniqueId();
Expand All @@ -39,35 +31,36 @@ const AdminUserSetRandomPassword = ({
id={setRandomPasswordId}
aria-describedby={`${setRandomPasswordId}-hint`}
checked={value}
onChange={() => {
setValue('setPasswordManually', false);
onChange(true);
}}
onChange={() => onChange(true)}
disabled={!isSmtpEnabled}
/>
)}
/>
</FieldRow>
<FieldLabel htmlFor={setRandomPasswordId} alignSelf='center' fontScale='p2'>
<FieldLabel htmlFor={setRandomPasswordId} alignSelf='center' fontScale='p2' disabled={!isSmtpEnabled}>
{t('Set_randomly_and_send_by_email')}
</FieldLabel>
</Box>
{!isSmtpEnabled && (
<FieldHint
id={`${setRandomPasswordId}-hint`}
dangerouslySetInnerHTML={{ __html: t('Send_Email_SMTP_Warning', { url: 'admin/settings/Email' }) }}
mbe={16}
mbs={0}
/>
)}
<Box display='flex' flexDirection='row' alignItems='center' flexGrow={1}>
<FieldRow mie={8}>
<Controller
control={control}
name='setPasswordManually'
name='setRandomPassword'
render={({ field: { ref, onChange, value } }) => (
<RadioButton
ref={ref}
id={setPasswordManuallyId}
aria-describedby={`${setPasswordManuallyId}-hint`}
checked={value || !setRandomPassword}
onChange={() => {
setValue('setRandomPassword', false);
onChange(true);
}}
disabled={!isSmtpEnabled}
checked={!value}
onChange={() => onChange(false)}
/>
)}
/>
Expand Down
4 changes: 3 additions & 1 deletion apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@
"Action_Available_After_Custom_Content_Added": "This action will become available after the custom content has been added",
"Action_Available_After_Custom_Content_Added_And_Visible": "This action will become available after the custom content has been added and made visible to everyone",
"Activate": "Activate",
"Activate_to_bypass_email_verification": "Activate to bypass email verification",
"Active": "Active",
"Active_users": "Active users",
"Activity": "Activity",
Expand Down Expand Up @@ -1843,6 +1844,7 @@
"Email_subject": "Email Subject",
"Email_verified": "Email verified",
"Email_sent": "Email sent",
"Email_verification_isnt_required": "Email verification is not required. Change this registration option in <a href=\"{{url}}\">accounts settings</a> to enable.",
"Emoji": "Emoji",
"Emoji_picker": "Emoji picker",
"EmojiCustomFilesystem": "Custom Emoji Filesystem",
Expand Down Expand Up @@ -4613,7 +4615,7 @@
"Send_confirmation_email": "Send confirmation email",
"Send_data_into_RocketChat_in_realtime": "Send data into Rocket.Chat in real-time.",
"Send_email": "Send Email",
"Send_Email_SMTP_Warning": "To send this email you need to <a href=\"{{url}}\">setup SMTP emailing server</a>",
"Send_Email_SMTP_Warning": "Set up the SMTP server in <a href=\"{{url}}\">email settings</a> to enable",
"Send_invitation_email": "Send invitation email",
"Send_invitation_email_error": "You haven't provided any valid email address.",
"Send_invitation_email_info": "You can send multiple email invitations at once.",
Expand Down

0 comments on commit 35a1e49

Please sign in to comment.