feat: fix a bunch of bugs.

This commit is contained in:
Ahmed Bouhuolia
2020-04-28 04:01:10 +02:00
parent 6d0ad42582
commit 0cfa1126c5
41 changed files with 591 additions and 187 deletions

View File

@@ -12,7 +12,7 @@ import {
import RegisterFromConnect from 'connectors/RegisterForm.connect';
import ErrorMessage from 'components/ErrorMessage';
import AppToaster from 'components/AppToaster';
import { compose, regExpCollection } from 'utils';
import { compose } from 'utils';
function Register({
requestSubmitRegister,
@@ -29,7 +29,6 @@ function Register({
last_name: Yup.string().required(),
email: Yup.string().email().required(),
phone_number: Yup.string()
.matches(regExpCollection.phoneNumber)
.required(intl.formatMessage({ id: 'required' })),
password: Yup.string()
.min(4, 'Password has to be longer than 8 characters!')

View File

@@ -2,8 +2,6 @@ import React, { useEffect, useState, useCallback } from 'react';
import {
Route,
Switch,
useParams,
useRouteMatch
} from 'react-router-dom';
import useAsync from 'hooks/async';
import { Alert, Intent } from '@blueprintjs/core';
@@ -21,56 +19,71 @@ import { compose } from 'utils';
function AccountsChart({
changePageTitle,
requestFetchAccounts,
requestDeleteAccount,
requestInactiveAccount,
fetchResourceViews,
fetchResourceFields,
getResourceFields,
requestFetchAccountsTable,
addAccountsTableQueries
addAccountsTableQueries,
requestDeleteBulkAccounts,
setDashboardRequestLoading,
setDashboardRequestCompleted,
}) {
const [state, setState] = useState({
deleteAlertActive: false,
restoreAlertActive: false,
inactiveAlertActive: false,
targetAccount: {},
});
const [deleteAccount, setDeleteAccount] = useState(false);
const [inactiveAccount, setInactiveAccount] = useState(false);
const [bulkDelete, setBulkDelete] = useState(false);
const [selectedRows, setSelectedRows] = useState([]);
// Fetch accounts resource views and fields.
const fetchHook = useAsync(async () => {
setDashboardRequestLoading();
await Promise.all([
fetchResourceViews('accounts'),
fetchResourceFields('accounts'),
]);
setDashboardRequestCompleted();
});
// Fetch accounts list according to the given custom view id.
const fetchAccountsHook = useAsync(async () => {
setDashboardRequestLoading();
await Promise.all([
requestFetchAccountsTable(),
]);
setDashboardRequestCompleted();
}, false);
useEffect(() => {
changePageTitle('Chart of Accounts');
}, []);
}, [changePageTitle]);
// Handle click and cancel/confirm account delete
const handleDeleteAccount = (account) => { setDeleteAccount(account); };
// handle cancel delete account alert.
const handleCancelAccountDelete = () => { setDeleteAccount(false); };
const handleCancelAccountDelete = useCallback(() => { setDeleteAccount(false); }, []);
// Handle confirm account delete
const handleConfirmAccountDelete = useCallback(() => {
requestDeleteAccount(deleteAccount.id).then(() => {
setDeleteAccount(false);
fetchAccountsHook.execute();
AppToaster.show({ message: 'the_account_has_been_deleted' });
}).catch(errors => {
setDeleteAccount(false);
if (errors.find((e) => e.type === 'ACCOUNT.PREDEFINED')) {
AppToaster.show({
message: 'cannot_delete_predefined_account'
});
}
if (errors.find((e) => e.type === 'ACCOUNT.HAS.ASSOCIATED.TRANSACTIONS')) {
AppToaster.show({
message: 'cannot_delete_account_has_associated_transactions'
});
}
});
}, [deleteAccount]);
}, [deleteAccount, requestDeleteAccount]);
// Handle cancel/confirm account inactive.
const handleInactiveAccount = useCallback((account) => {
@@ -91,13 +104,7 @@ function AccountsChart({
});
}, [inactiveAccount]);
/**
* Handle cancel/confirm account restore.
*/
const handleCancelAccountRestore = () => {
};
const handleEditAccount = (account) => {
};
@@ -106,22 +113,43 @@ function AccountsChart({
};
const handleConfirmAccountRestore = (account) => {
const handleBulkDelete = useCallback((accountsIds) => {
setBulkDelete(accountsIds);
}, [setBulkDelete]);
};
const handleDeleteBulkAccounts = (accounts) => {
const handleConfirmBulkDelete = useCallback(() => {
requestDeleteBulkAccounts(bulkDelete).then(() => {
setBulkDelete(false);
AppToaster.show({ message: 'the_accounts_have_been_deleted' });
}).catch((error) => {
setBulkDelete(false);
});
}, [requestDeleteBulkAccounts, bulkDelete]);
};
const handleCancelBulkDelete = useCallback(() => {
setBulkDelete(false);
}, []);
const handleSelectedRowsChange = (accounts) => {
console.log(accounts);
};
const handleBulkArchive = useCallback((accounts) => {
}, []);
// Handle selected rows change.
const handleSelectedRowsChange = useCallback((accounts) => {
setSelectedRows(accounts);
}, [setSelectedRows]);
// Refetches accounts data table when current custom view changed.
const handleFilterChanged = useCallback(() => {
fetchAccountsHook.execute();
}, [fetchAccountsHook]);
const handleViewChanged = useCallback(() => { fetchAccountsHook.execute(); }, []);
// Refetch accounts data table when current custom view changed.
const handleViewChanged = useCallback(() => {
fetchAccountsHook.execute();
}, [fetchAccountsHook]);
// Handle fetch data of accounts datatable.
const handleFetchData = useCallback(({ pageIndex, pageSize, sortBy }) => {
addAccountsTableQueries({
...(sortBy.length > 0) ? {
@@ -135,26 +163,29 @@ function AccountsChart({
return (
<DashboardInsider loading={fetchHook.pending} name={'accounts-chart'}>
<DashboardActionsBar
onFilterChanged={handleFilterChanged} />
selectedRows={selectedRows}
onFilterChanged={handleFilterChanged}
onBulkDelete={handleBulkDelete}
onBulkArchive={handleBulkArchive} />
<DashboardPageContent>
<Switch>
<Route
exact={true}
path={[
'/dashboard/accounts/:custom_view_id/custom_view',
'/dashboard/accounts'
'/dashboard/accounts',
]}>
<AccountsViewsTabs
onViewChanged={handleViewChanged}
onDeleteBulkAccounts={handleDeleteBulkAccounts} />
onViewChanged={handleViewChanged} />
<AccountsDataTable
onSelectedRowsChange={handleSelectedRowsChange}
onDeleteAccount={handleDeleteAccount}
onInactiveAccount={handleInactiveAccount}
onRestoreAccount={handleRestoreAccount}
onEditAccount={handleEditAccount}
onFetchData={handleFetchData} />
onFetchData={handleFetchData}
onSelectedRowsChange={handleSelectedRowsChange} />
</Route>
</Switch>
@@ -185,6 +216,20 @@ function AccountsChart({
but it will become private to you.
</p>
</Alert>
<Alert
cancelButtonText="Cancel"
confirmButtonText="Delete"
icon="trash"
intent={Intent.DANGER}
isOpen={bulkDelete}
onCancel={handleCancelBulkDelete}
onConfirm={handleConfirmBulkDelete}>
<p>
Are you sure you want to move <b>filename</b> to Trash? You will be able to restore it later,
but it will become private to you.
</p>
</Alert>
</DashboardPageContent>
</DashboardInsider>
);

View File

@@ -38,7 +38,7 @@ function AccountFormDialog({
closeDialog,
requestSubmitAccount,
requestEditAccount,
getAccountById
getAccountById,
}) {
const intl = useIntl();
const accountFormValidationSchema = Yup.object().shape({
@@ -57,12 +57,23 @@ function AccountFormDialog({
}), []);
const [selectedAccountType, setSelectedAccountType] = useState(null);
const [selectedSubaccount, setSelectedSubaccount] = useState(null);
const [selectedSubaccount, setSelectedSubaccount] = useState(
payload.action === 'new_child' ?
accounts.find(a => a.id === payload.id) : null,
);
const editAccount = useMemo(() =>
payload.action === 'edit' ? getAccountById(payload.id) : null,
[payload, getAccountById]);
const transformApiErrors = (errors) => {
const fields = {};
if (errors.find(e => e.type === 'NOT_UNIQUE_CODE')) {
fields.code = 'Account code is not unqiue.'
}
return fields;
};
// Formik
const formik = useFormik({
enableReinitialize: true,
@@ -71,21 +82,22 @@ function AccountFormDialog({
? editAccount : initialValues,
},
validationSchema: accountFormValidationSchema,
onSubmit: (values, { setSubmitting }) => {
onSubmit: (values, { setSubmitting, setErrors }) => {
const exclude = ['subaccount'];
if (payload.action === 'edit') {
requestEditAccount({
payload: payload.id,
form: { ...omit(values, exclude) }
form: { ...omit(values, [...exclude, 'account_type_id']) }
}).then(response => {
closeDialog(name);
AppToaster.show({
message: 'the_account_has_been_edited'
});
setSubmitting(false);
}).catch(() => {
}).catch((errors) => {
setSubmitting(false);
setErrors(transformApiErrors(errors));
});
} else {
requestSubmitAccount({ form: { ...omit(values, exclude) } }).then(response => {
@@ -94,8 +106,9 @@ function AccountFormDialog({
message: 'the_account_has_been_submit'
});
setSubmitting(false);
}).catch(() => {
}).catch((errors) => {
setSubmitting(false);
setErrors(transformApiErrors(errors));
});
}
}
@@ -187,9 +200,7 @@ function AccountFormDialog({
return (<span>{'Sub account?'} <Icon icon="info-circle" iconSize={12} /></span>);
}, []);
const requiredSpan = useMemo(() => (
<span class="required">*</span>
), []);
const requiredSpan = useMemo(() => (<span class="required">*</span>), []);
return (
<Dialog
@@ -232,6 +243,7 @@ function AccountFormDialog({
rightIcon='caret-down'
text={selectedAccountType ?
selectedAccountType.name : 'Select account type'}
disabled={payload.action === 'edit'}
/>
</Select>
</FormGroup>