Skip to content

Commit

Permalink
feat: custom fields component to registration form (RocketChat#29202)
Browse files Browse the repository at this point in the history
Co-authored-by: Douglas Fabris <[email protected]>
  • Loading branch information
hugocostadev and dougfabris authored Jun 23, 2023
1 parent bc11505 commit e14ec50
Show file tree
Hide file tree
Showing 28 changed files with 209 additions and 331 deletions.
10 changes: 10 additions & 0 deletions .changeset/custom-fields.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@rocket.chat/meteor": patch
"@rocket.chat/core-typings": patch
"@rocket.chat/rest-typings": patch
"@rocket.chat/ui-client": patch
"@rocket.chat/ui-contexts": patch
"@rocket.chat/web-ui-registration": patch
---

Added and Improved Custom Fields form to Registration Flow
13 changes: 13 additions & 0 deletions apps/meteor/app/api/server/v1/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,15 @@ API.v1.addRoute(
}

const { secret: secretURL, ...params } = this.bodyParams;

if (this.bodyParams.customFields) {
try {
await validateCustomFields(this.bodyParams.customFields);
} catch (e) {
return API.v1.failure(e);
}
}

// Register the user
const userId = await Meteor.callAsync('registerUser', {
...params,
Expand All @@ -579,6 +588,10 @@ API.v1.addRoute(
return API.v1.failure('User not found');
}

if (this.bodyParams.customFields) {
await saveCustomFields(userId, this.bodyParams.customFields);
}

return API.v1.success({ user });
},
},
Expand Down

This file was deleted.

This file was deleted.

152 changes: 0 additions & 152 deletions apps/meteor/client/components/CustomFieldsForm.js

This file was deleted.

45 changes: 39 additions & 6 deletions apps/meteor/client/views/account/profile/AccountProfileForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
import type { IUser } from '@rocket.chat/core-typings';
import { Field, FieldGroup, TextInput, TextAreaInput, Box, Icon, PasswordInput, Button } from '@rocket.chat/fuselage';
import { useDebouncedCallback, useSafely } from '@rocket.chat/fuselage-hooks';
import { PasswordVerifier } from '@rocket.chat/ui-client';
import { CustomFieldsForm, PasswordVerifier } from '@rocket.chat/ui-client';
import { useAccountsCustomFields, useVerifyPassword, useToastMessageDispatch, useTranslation, useEndpoint } from '@rocket.chat/ui-contexts';
import type { TranslationKey } from '@rocket.chat/ui-contexts';
import { useVerifyPassword, useToastMessageDispatch, useTranslation, useEndpoint } from '@rocket.chat/ui-contexts';
import type { Dispatch, ReactElement, SetStateAction } from 'react';
import React, { useCallback, useMemo, useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';

import { validateEmail } from '../../../../lib/emailValidator';
import { getUserEmailAddress } from '../../../../lib/getUserEmailAddress';
import CustomFieldsForm from '../../../components/CustomFieldsForm';
import UserStatusMenu from '../../../components/UserStatusMenu';
import UserAvatarEditor from '../../../components/avatar/UserAvatarEditor';
import { USER_STATUS_TEXT_MAX_LENGTH, BIO_TEXT_MAX_LENGTH } from '../../../lib/constants';
Expand All @@ -33,6 +33,8 @@ const AccountProfileForm = ({ values, handlers, user, settings, onSaveStateChang
const getAvatarSuggestions = useEndpoint('GET', '/v1/users.getAvatarSuggestion');
const sendConfirmationEmail = useEndpoint('POST', '/v1/users.sendConfirmationEmail');

const customFieldsMetadata = useAccountsCustomFields();

const [usernameError, setUsernameError] = useState<string | undefined>();
const [avatarSuggestions, setAvatarSuggestions] = useSafely(
useState<{
Expand Down Expand Up @@ -71,10 +73,19 @@ const AccountProfileForm = ({ values, handlers, user, settings, onSaveStateChang
handleStatusText,
handleStatusType,
handleBio,
handleCustomFields,
handleNickname,
handleCustomFields,
} = handlers;

const {
control,
watch,
formState: { errors: customFieldsErrors },
} = useForm({
defaultValues: { customFields: { ...customFields } },
mode: 'onBlur',
});

const previousEmail = user ? getUserEmailAddress(user) : '';

const handleSendConfirmationEmail = useCallback(async () => {
Expand Down Expand Up @@ -123,6 +134,11 @@ const AccountProfileForm = ({ values, handlers, user, settings, onSaveStateChang
[namesRegex, t, user?.username, checkUsernameAvailability, setUsernameError],
);

useEffect(() => {
const subscription = watch((value) => handleCustomFields({ ...value.customFields }));
return () => subscription.unsubscribe();
}, [watch, handleCustomFields]);

useEffect(() => {
const getSuggestions = async (): Promise<void> => {
const { suggestions } = await getAvatarSuggestions();
Expand Down Expand Up @@ -166,9 +182,25 @@ const AccountProfileForm = ({ values, handlers, user, settings, onSaveStateChang
return undefined;
}, [bio, t]);

const customFieldsError = useMemo(() => {
if (customFieldsErrors) {
return customFieldsErrors;
}

return undefined;
}, [customFieldsErrors]);

const verified = user?.emails?.[0]?.verified ?? false;

const canSave = !(!!passwordError || !!emailError || !!usernameError || !!nameError || !!statusTextError || !!bioError);
const canSave = !(
!!passwordError ||
!!emailError ||
!!usernameError ||
!!nameError ||
!!statusTextError ||
!!bioError ||
!customFieldsError
);

useEffect(() => {
onSaveStateChange(canSave);
Expand Down Expand Up @@ -358,7 +390,8 @@ const AccountProfileForm = ({ values, handlers, user, settings, onSaveStateChang
passwordVerifications,
],
)}
<CustomFieldsForm jsonCustomFields={undefined} customFieldsData={customFields} setCustomFieldsData={handleCustomFields} />

{customFieldsMetadata && <CustomFieldsForm formName='customFields' formControl={control} metadata={customFieldsMetadata} />}
</FieldGroup>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ const AccountProfilePage = (): ReactElement => {
<Page>
<Page.Header title={t('Profile')}>
<ButtonGroup>
<Button danger disabled={!hasUnsavedChanges} onClick={reset}>
<Button disabled={!hasUnsavedChanges} onClick={reset}>
{t('Reset')}
</Button>
<Button data-qa='AccountProfilePageSaveButton' primary disabled={!hasUnsavedChanges || !canSave || loggingOut} onClick={onSave}>
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/client/views/admin/users/AddUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ const AddUser = ({ onReload, ...props }) => {
<Button flexGrow={1} disabled={!hasUnsavedChanges} onClick={reset} mie='x4'>
{t('Cancel')}
</Button>
<Button flexGrow={1} disabled={!hasUnsavedChanges} onClick={handleSave}>
<Button primary flexGrow={1} disabled={!hasUnsavedChanges} onClick={handleSave}>
{t('Save')}
</Button>
</Box>
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/client/views/admin/users/EditUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ function EditUser({ data, roles, onReload, ...props }) {
<Button flexGrow={1} type='reset' disabled={!canSaveOrReset} onClick={reset}>
{t('Reset')}
</Button>
<Button mie='none' flexGrow={1} disabled={!canSaveOrReset} onClick={handleSave}>
<Button primary mie='none' flexGrow={1} disabled={!canSaveOrReset} onClick={handleSave}>
{t('Save')}
</Button>
</Margins>
Expand Down
Loading

0 comments on commit e14ec50

Please sign in to comment.