Merge pull request #111 from bigcapitalhq/improve-webapp-users

refactor(webapp): invite and user form with new blueprintjs-formik components
This commit is contained in:
Ahmed Bouhuolia
2023-04-14 03:53:11 +02:00
committed by GitHub
7 changed files with 70 additions and 37 deletions

View File

@@ -16,6 +16,11 @@ import { transformApiErrors } from './utils';
import { compose, objectKeysTransform } from '@/utils'; import { compose, objectKeysTransform } from '@/utils';
const initialValues = {
email: '',
role_id: ''
}
function InviteUserForm({ function InviteUserForm({
// #withDialogActions // #withDialogActions
closeDialog, closeDialog,
@@ -23,7 +28,8 @@ function InviteUserForm({
const { dialogName, isEditMode, inviteUserMutate, userId } = const { dialogName, isEditMode, inviteUserMutate, userId } =
useInviteUserFormContext(); useInviteUserFormContext();
const initialValues = { const initialFormValues = {
...initialValues,
status: 1, status: 1,
...(isEditMode && ...(isEditMode &&
pick( pick(
@@ -66,7 +72,7 @@ function InviteUserForm({
return ( return (
<Formik <Formik
validationSchema={InviteUserFormSchema} validationSchema={InviteUserFormSchema}
initialValues={initialValues} initialValues={initialFormValues}
onSubmit={handleSubmit} onSubmit={handleSubmit}
> >
<InviteUserFormContent /> <InviteUserFormContent />

View File

@@ -6,6 +6,8 @@ import {
ListSelect, ListSelect,
FieldRequiredHint, FieldRequiredHint,
FormattedMessage as T, FormattedMessage as T,
FFormGroup,
FInputGroup,
} from '@/components'; } from '@/components';
import { CLASSES } from '@/constants/classes'; import { CLASSES } from '@/constants/classes';
import classNames from 'classnames'; import classNames from 'classnames';
@@ -32,19 +34,13 @@ function InviteUserFormContent({
<T id={'your_access_to_your_team'} /> <T id={'your_access_to_your_team'} />
</p> </p>
{/* ----------- Email ----------- */} {/* ----------- Email ----------- */}
<FastField name={'email'}> <FFormGroup
{({ field, meta: { error, touched } }) => ( name={'email'}
<FormGroup label={<T id={'invite_user.label.email'} />}
label={<T id={'email'} />}
labelInfo={<FieldRequiredHint />} labelInfo={<FieldRequiredHint />}
className={classNames('form-group--email', CLASSES.FILL)}
intent={inputIntent({ error, touched })}
helperText={<ErrorMessage name="email" />}
> >
<InputGroup medium={true} {...field} /> <FInputGroup name={'email'} />
</FormGroup> </FFormGroup>
)}
</FastField>
{/* ----------- Role name ----------- */} {/* ----------- Role name ----------- */}
<FastField name={'role_id'}> <FastField name={'role_id'}>
{({ form, field: { value }, meta: { error, touched } }) => ( {({ form, field: { value }, meta: { error, touched } }) => (
@@ -78,7 +74,13 @@ function InviteUserFormContent({
<T id={'cancel'} /> <T id={'cancel'} />
</Button> </Button>
<Button intent={Intent.PRIMARY} type="submit" disabled={isSubmitting}> <Button
intent={Intent.PRIMARY}
type="submit"
disabled={isSubmitting}
loading={isSubmitting}
style={{ minWidth: '95px' }}
>
{isEditMode ? <T id={'edit'} /> : <T id={'invite'} />} {isEditMode ? <T id={'edit'} /> : <T id={'invite'} />}
</Button> </Button>
</div> </div>

View File

@@ -41,17 +41,29 @@ function UserFormContent({
<UserFormCalloutAlerts calloutCodes={calloutCode} /> <UserFormCalloutAlerts calloutCodes={calloutCode} />
{/* ----------- Email ----------- */} {/* ----------- Email ----------- */}
<FFormGroup name={'email'} label={<T id={'email'} />}> <FFormGroup
name={'email'}
label={<T id={'email'} />}
labelInfo={<FieldRequiredHint />}
>
<FInputGroup name={'email'} /> <FInputGroup name={'email'} />
</FFormGroup> </FFormGroup>
{/* ----------- First name ----------- */} {/* ----------- First name ----------- */}
<FFormGroup name={'first_name'} label={<T id={'first_name'} />}> <FFormGroup
name={'first_name'}
label={<T id={'first_name'} />}
labelInfo={<FieldRequiredHint />}
>
<FInputGroup name={'first_name'} /> <FInputGroup name={'first_name'} />
</FFormGroup> </FFormGroup>
{/* ----------- Last name ----------- */} {/* ----------- Last name ----------- */}
<FFormGroup name={'last_name'} label={<T id={'last_name'} />}> <FFormGroup
name={'last_name'}
label={<T id={'last_name'} />}
labelInfo={<FieldRequiredHint />}
>
<FInputGroup name={'last_name'} /> <FInputGroup name={'last_name'} />
</FFormGroup> </FFormGroup>
@@ -94,6 +106,7 @@ function UserFormContent({
type="submit" type="submit"
disabled={isSubmitting} disabled={isSubmitting}
loading={isSubmitting} loading={isSubmitting}
style={{ minWidth: '85px' }}
> >
<T id={'edit'} /> <T id={'edit'} />
</Button> </Button>

View File

@@ -1,6 +1,7 @@
// @ts-nocheck // @ts-nocheck
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import intl from 'react-intl-universal'; import intl from 'react-intl-universal';
import styled from 'styled-components';
import { import {
Menu, Menu,
Popover, Popover,
@@ -9,6 +10,7 @@ import {
MenuItem, MenuItem,
MenuDivider, MenuDivider,
Intent, Intent,
Tag,
} from '@blueprintjs/core'; } from '@blueprintjs/core';
import { Icon } from '@/components'; import { Icon } from '@/components';
import { safeCallback } from '@/utils'; import { safeCallback } from '@/utils';
@@ -52,12 +54,25 @@ export const ActionsCell = (props) => {
); );
}; };
export const CurrencyNameAccessor = (value) => {
return (
<CurrencyNameRoot>
{value.currency_name} {value.is_base_currency && <Tag>Base Currency</Tag>}
</CurrencyNameRoot>
);
};
const CurrencyNameRoot = styled.div`
display: flex;
gap: 8px;
`;
export function useCurrenciesTableColumns() { export function useCurrenciesTableColumns() {
return useMemo( return useMemo(
() => [ () => [
{ {
Header: intl.get('currency_name'), Header: intl.get('currency_name'),
accessor: 'currency_name', accessor: CurrencyNameAccessor,
width: 150, width: 150,
}, },
{ {

View File

@@ -22,6 +22,14 @@ function UsersDataTable({
// #withAlertActions // #withAlertActions
openAlert, openAlert,
}) { }) {
const { mutateAsync: resendInviation } = useResendInvitation();
// Users list columns.
const columns = useUsersListColumns();
// Users list context.
const { users, isUsersLoading, isUsersFetching } = useUsersListContext();
// Handle edit user action. // Handle edit user action.
const handleEditUserAction = useCallback( const handleEditUserAction = useCallback(
(user) => { (user) => {
@@ -50,9 +58,6 @@ function UsersDataTable({
}, },
[openAlert], [openAlert],
); );
const { mutateAsync: resendInviation } = useResendInvitation();
const handleResendInvitation = useCallback((user) => { const handleResendInvitation = useCallback((user) => {
resendInviation(user.id) resendInviation(user.id)
.then(() => { .then(() => {
@@ -71,17 +76,12 @@ function UsersDataTable({
AppToaster.show({ AppToaster.show({
message: message:
'This person was recently invited. No need to invite them again just yet.', 'This person was recently invited. No need to invite them again just yet.',
intent: Intent.DANGER, intent: Intent.WARNING,
}); });
} }
}, },
); );
}); });
// Users list columns.
const columns = useUsersListColumns();
// Users list context.
const { users, isUsersLoading, isUsersFetching } = useUsersListContext();
return ( return (
<DataTable <DataTable

View File

@@ -132,15 +132,9 @@ export const useUsersListColumns = () => {
{ {
id: 'role_name', id: 'role_name',
Header: intl.get('users.column.role_name'), Header: intl.get('users.column.role_name'),
accessor: 'role.name', accessor: 'role_name',
width: 120, width: 120,
}, },
// {
// id: 'phone_number',
// Header: intl.get('phone_number'),
// accessor: 'phone_number',
// width: 120,
// },
{ {
id: 'status', id: 'status',
Header: intl.get('status'), Header: intl.get('status'),

View File

@@ -2228,5 +2228,8 @@
"project_billable_entries.dialog.show": "Show", "project_billable_entries.dialog.show": "Show",
"project_billable_entries.alert.there_is_no_billable_entries": "There is no billable entries for that project.", "project_billable_entries.alert.there_is_no_billable_entries": "There is no billable entries for that project.",
"project_billable_entries.billable_type": "Billable {value}", "project_billable_entries.billable_type": "Billable {value}",
"add_billable_entries": "Add Billable Entries" "add_billable_entries": "Add Billable Entries",
"invite_user.label.email": "Email",
"invite_user.label.role_name": "Role name"
} }