Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ahmed Bouhuolia
2020-11-11 15:21:12 +02:00
2 changed files with 73 additions and 68 deletions

View File

@@ -8,12 +8,10 @@ import {
TextArea, TextArea,
MenuItem, MenuItem,
} from '@blueprintjs/core'; } from '@blueprintjs/core';
import { pick } from 'lodash';
import * as Yup from 'yup'; import * as Yup from 'yup';
import { useFormik } from 'formik'; import { useFormik } from 'formik';
import { useQuery, queryCache } from 'react-query'; import { useQuery, queryCache } from 'react-query';
import { FormattedMessage as T, useIntl } from 'react-intl'; import { FormattedMessage as T, useIntl } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { import {
ListSelect, ListSelect,
@@ -31,16 +29,29 @@ import withItemCategoriesActions from 'containers/Items/withItemCategoriesAction
import withAccounts from 'containers/Accounts/withAccounts'; import withAccounts from 'containers/Accounts/withAccounts';
import withAccountsActions from 'containers/Accounts/withAccountsActions'; import withAccountsActions from 'containers/Accounts/withAccountsActions';
import withDialogActions from 'containers/Dialog/withDialogActions'; import withDialogActions from 'containers/Dialog/withDialogActions';
import { compose } from 'utils';
import { compose, transformToForm } from 'utils';
const defaultInitialValues = {
name: '',
description: '',
parent_category_id: '',
cost_account_id: '',
sell_account_id: '',
inventory_account_id: '',
};
/**
* Item Category form dialog content.
*/
function ItemCategoryFormDialogContent({ function ItemCategoryFormDialogContent({
// #withDialogActions // #withDialogActions
closeDialog, closeDialog,
// #withItemCategoryDetail // #withItemCategoryDetail
itemCategory, itemCategoryDetail,
// #withItemCategories // #withItemCategories
categoriesList, categoriesList,
@@ -61,41 +72,72 @@ function ItemCategoryFormDialogContent({
itemCategoryId, itemCategoryId,
dialogName, dialogName,
}) { }) {
const isNewMode = !itemCategoryId;
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
const [selectedParentCategory, setParentCategory] = useState(null); const [selectedParentCategory, setParentCategory] = useState(null);
const fetchList = useQuery(['items-categories-list'], () => // Fetches categories list.
const fetchCategoriesList = useQuery(['items-categories-list'], () =>
requestFetchItemCategories(), requestFetchItemCategories(),
); );
const fetchAccounts = useQuery(
'accounts-list', // Fetches accounts list.
() => requestFetchAccounts(), const fetchAccountsList = useQuery('accounts-list', () =>
{ enabled: false }, requestFetchAccounts(),
); );
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
name: Yup.string() name: Yup.string()
.required() .required()
.label(formatMessage({ id: 'category_name_' })), .label(formatMessage({ id: 'category_name_' })),
parent_category_id: Yup.string().nullable(), parent_category_id: Yup.number().nullable(),
cost_account_id: Yup.number().nullable(), cost_account_id: Yup.number().nullable(),
sell_account_id: Yup.number().nullable(), sell_account_id: Yup.number().nullable(),
inventory_account_id: Yup.number(), inventory_account_id: Yup.number().nullable(),
description: Yup.string().trim().nullable(), description: Yup.string().trim().nullable(),
}); });
const initialValues = useMemo( const initialValues = useMemo(
() => ({ () => ({
name: '', ...defaultInitialValues,
description: '', ...transformToForm(itemCategoryDetail, defaultInitialValues),
parent_category_id: null,
cost_account_id: null,
sell_account_id: null,
inventory_account_id: null,
}), }),
[], [],
); );
// Handles the form submit.
const handleFormSubmit = (values, { setSubmitting }) => {
setSubmitting(true);
const form = { ...values };
const afterSubmit = () => {
closeDialog(dialogName);
queryCache.invalidateQueries('items-categories-list');
queryCache.invalidateQueries('accounts-list');
};
const onSuccess = ({ response }) => {
AppToaster.show({
message: formatMessage({
id: isNewMode
? 'the_item_category_has_been_successfully_created'
: 'the_item_category_has_been_successfully_edited',
}),
intent: Intent.SUCCESS,
});
afterSubmit(response);
};
const onError = ({ response }) => {
setSubmitting(false);
};
if (isNewMode) {
requestSubmitItemCategory(form).then(onSuccess).catch(onError);
} else {
requestEditItemCategory(itemCategoryId, form)
.then(onSuccess)
.catch(onError);
}
};
// Formik // Formik
const { const {
values, values,
@@ -108,49 +150,12 @@ function ItemCategoryFormDialogContent({
} = useFormik({ } = useFormik({
enableReinitialize: true, enableReinitialize: true,
validationSchema, validationSchema,
initialValues: { initialValues,
...initialValues, onSubmit: handleFormSubmit,
...(action === 'edit' && pick(itemCategory, Object.keys(initialValues))),
},
onSubmit: (values, { setSubmitting }) => {
const afterSubmit = () => {
closeDialog(dialogName);
queryCache.invalidateQueries('items-categories-list');
queryCache.invalidateQueries('accounts-list');
};
if (action === 'edit') {
requestEditItemCategory(itemCategoryId, values)
.then((response) => {
AppToaster.show({
message: formatMessage({
id: 'the_item_category_has_been_successfully_edited',
}),
intent: Intent.SUCCESS,
});
afterSubmit(response);
})
.catch((error) => {
setSubmitting(false);
});
} else {
requestSubmitItemCategory(values)
.then((response) => {
AppToaster.show({
message: formatMessage({
id: 'the_item_category_has_been_successfully_created',
}),
intent: Intent.SUCCESS,
});
afterSubmit(response);
})
.catch((error) => {
setSubmitting(false);
});
}
},
}); });
const filterItemCategory = useCallback( // Filters Item Categories list.
const filterItemCategories = useCallback(
(query, category, _index, exactMatch) => { (query, category, _index, exactMatch) => {
const normalizedTitle = category.name.toLowerCase(); const normalizedTitle = category.name.toLowerCase();
const normalizedQuery = query.toLowerCase(); const normalizedQuery = query.toLowerCase();
@@ -200,10 +205,11 @@ function ItemCategoryFormDialogContent({
); );
return ( return (
<DialogContent isLoading={fetchList.isFetching || fetchAccounts.isFetching}> <DialogContent
isLoading={fetchCategoriesList.isFetching || fetchAccountsList.isFetching}
>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<div className={Classes.DIALOG_BODY}> <div className={Classes.DIALOG_BODY}>
{/* ----------- Category name ----------- */} {/* ----------- Category name ----------- */}
<FormGroup <FormGroup
label={<T id={'category_name'} />} label={<T id={'category_name'} />}
@@ -245,7 +251,7 @@ function ItemCategoryFormDialogContent({
items={categoriesList} items={categoriesList}
noResults={<MenuItem disabled={true} text="No results." />} noResults={<MenuItem disabled={true} text="No results." />}
itemRenderer={parentCategoryItem} itemRenderer={parentCategoryItem}
itemPredicate={filterItemCategory} itemPredicate={filterItemCategories}
popoverProps={{ minimal: true }} popoverProps={{ minimal: true }}
onItemSelect={onChangeParentCategory} onItemSelect={onChangeParentCategory}
selectedItem={values.parent_category_id} selectedItem={values.parent_category_id}
@@ -291,6 +297,7 @@ function ItemCategoryFormDialogContent({
onAccountSelected={onItemAccountSelect('cost_account_id')} onAccountSelected={onItemAccountSelect('cost_account_id')}
defaultSelectText={<T id={'select_account'} />} defaultSelectText={<T id={'select_account'} />}
selectedAccountId={values.cost_account_id} selectedAccountId={values.cost_account_id}
filterByTypes={['cost_of_goods_sold']}
/> />
</FormGroup> </FormGroup>
{/* ----------- Sell account ----------- */} {/* ----------- Sell account ----------- */}
@@ -314,6 +321,7 @@ function ItemCategoryFormDialogContent({
onAccountSelected={onItemAccountSelect('sell_account_id')} onAccountSelected={onItemAccountSelect('sell_account_id')}
defaultSelectText={<T id={'select_account'} />} defaultSelectText={<T id={'select_account'} />}
selectedAccountId={values.sell_account_id} selectedAccountId={values.sell_account_id}
filterByTypes={['income']}
/> />
</FormGroup> </FormGroup>
{/* ----------- inventory account ----------- */} {/* ----------- inventory account ----------- */}

View File

@@ -1,16 +1,13 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { import { getItemCategoryByIdFactory } from 'store/itemCategories/ItemsCategories.selectors';
getItemCategoryByIdFactory,
} from 'store/itemCategories/ItemsCategories.selectors';
export default () => { export default () => {
const getCategoryId = getItemCategoryByIdFactory(); const getCategoryId = getItemCategoryByIdFactory();
const mapStateToProps = (state, props) => { const mapStateToProps = (state, props) => {
return { return {
itemCategory: getCategoryId(state, props), itemCategoryDetail: getCategoryId(state, props),
}; };
}; };
return connect(mapStateToProps); return connect(mapStateToProps);
}; };