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';
const initialValues = {
email: '',
role_id: ''
}
function InviteUserForm({
// #withDialogActions
closeDialog,
@@ -23,7 +28,8 @@ function InviteUserForm({
const { dialogName, isEditMode, inviteUserMutate, userId } =
useInviteUserFormContext();
const initialValues = {
const initialFormValues = {
...initialValues,
status: 1,
...(isEditMode &&
pick(
@@ -66,7 +72,7 @@ function InviteUserForm({
return (
<Formik
validationSchema={InviteUserFormSchema}
initialValues={initialValues}
initialValues={initialFormValues}
onSubmit={handleSubmit}
>
<InviteUserFormContent />

View File

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

View File

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

View File

@@ -1,6 +1,7 @@
// @ts-nocheck
import React, { useMemo } from 'react';
import intl from 'react-intl-universal';
import styled from 'styled-components';
import {
Menu,
Popover,
@@ -9,6 +10,7 @@ import {
MenuItem,
MenuDivider,
Intent,
Tag,
} from '@blueprintjs/core';
import { Icon } from '@/components';
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() {
return useMemo(
() => [
{
Header: intl.get('currency_name'),
accessor: 'currency_name',
accessor: CurrencyNameAccessor,
width: 150,
},
{

View File

@@ -22,6 +22,14 @@ function UsersDataTable({
// #withAlertActions
openAlert,
}) {
const { mutateAsync: resendInviation } = useResendInvitation();
// Users list columns.
const columns = useUsersListColumns();
// Users list context.
const { users, isUsersLoading, isUsersFetching } = useUsersListContext();
// Handle edit user action.
const handleEditUserAction = useCallback(
(user) => {
@@ -50,9 +58,6 @@ function UsersDataTable({
},
[openAlert],
);
const { mutateAsync: resendInviation } = useResendInvitation();
const handleResendInvitation = useCallback((user) => {
resendInviation(user.id)
.then(() => {
@@ -71,17 +76,12 @@ function UsersDataTable({
AppToaster.show({
message:
'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 (
<DataTable

View File

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

View File

@@ -2228,5 +2228,8 @@
"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.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"
}