Merge remote-tracking branch 'origin/_tasks'

This commit is contained in:
Ahmed Bouhuolia
2020-07-01 15:01:08 +02:00
30 changed files with 533 additions and 266 deletions

View File

@@ -25,15 +25,31 @@ function Customer({
requestFetchCustomers({}),
);
const fetchCustomerDatails =useQuery(id && ['customer-detail',id],()=>requestFetchCustomers())
const fetchCustomerDatails = useQuery(id && ['customer-detail', id], () =>
requestFetchCustomers(),
);
const handleFormSubmit = useCallback(
(payload) => {
payload.redirect && history.push('/customers');
},
[history],
);
const handleCancel = useCallback(() => {
history.goBack();
}, [history]);
return (
<DashboardInsider
// formik={formik}
loading={ fetchCustomerDatails.isFetching || fetchCustomers.isFetching}
loading={fetchCustomerDatails.isFetching || fetchCustomers.isFetching}
name={'customer-form'}
>
<CustomerForm customerId={id} />
<CustomerForm
onFormSubmit={handleFormSubmit}
customerId={id}
onCancelForm={handleCancel}
/>
</DashboardInsider>
);
}

View File

@@ -0,0 +1,57 @@
import React from 'react';
import { Intent, Button } from '@blueprintjs/core';
import { FormattedMessage as T } from 'react-intl';
export default function CustomerFloatingFooter({
formik: { isSubmitting, resetForm },
onSubmitClick,
onCancelClick,
customer,
}) {
return (
<div className={'form__floating-footer'}>
<Button
intent={Intent.PRIMARY}
disabled={isSubmitting}
type="submit"
onClick={() => {
onSubmitClick({ publish: true, redirect: true });
}}
>
{customer && customer.id ? <T id={'edit'} /> : <T id={'save'} />}
</Button>
<Button
disabled={isSubmitting}
intent={Intent.PRIMARY}
className={'ml1'}
name={'save_and_new'}
onClick={() => {
onSubmitClick({ publish: true, redirect: false });
}}
>
<T id={'save_new'} />
</Button>
<Button
className={'ml1'}
disabled={isSubmitting}
onClick={() => {
onSubmitClick({ publish: false, redirect: false });
}}
>
<T id={'save_as_draft'} />
</Button>
<Button
className={'ml1'}
onClick={() => {
onCancelClick && onCancelClick();
}}
>
<T id={'close'} />
</Button>
</div>
);
}

View File

@@ -31,6 +31,7 @@ import withCustomers from 'containers/Customers//withCustomers';
import useMedia from 'hooks/useMedia';
import { compose } from 'utils';
import CustomerFloatingFooter from './CustomerFooter';
function CustomerForm({
// #withDashboardActions
@@ -40,7 +41,7 @@ function CustomerForm({
customers,
//#withCustomerDetail
customerDetail,
customer,
//#withCustomersActions
requestSubmitCustomer,
@@ -50,9 +51,13 @@ function CustomerForm({
// #withMediaActions
requestSubmitMedia,
requestDeleteMedia,
//#Props
onFormSubmit,
onCancelForm,
}) {
const { formatMessage } = useIntl();
const history = useHistory();
const [payload, setPayload] = useState({});
const {
setFiles,
@@ -127,22 +132,30 @@ function CustomerForm({
const initialValues = useMemo(
() => ({
...(customerDetail
...(customer
? {
...pick(customerDetail, Object.keys(defaultInitialValues)),
...pick(customer, Object.keys(defaultInitialValues)),
}
: {
...defaultInitialValues,
}),
}),
[customerDetail, defaultInitialValues],
[customer, defaultInitialValues],
);
const saveInvokeSubmit = useCallback(
(payload) => {
onFormSubmit && onFormSubmit(payload);
},
[onFormSubmit],
);
useEffect(() => {
customerDetail && customerDetail.id
customer && customer.id
? changePageTitle(formatMessage({ id: 'edit_customer_details' }))
: changePageTitle(formatMessage({ id: 'new_customer' }));
}, [changePageTitle, customerDetail, formatMessage]);
}, [changePageTitle, customer, formatMessage]);
const formik = useFormik({
enableReinitialize: true,
@@ -152,9 +165,9 @@ function CustomerForm({
},
onSubmit: (values, { setSubmitting, resetForm, setErrors }) => {
const formValues = { ...values };
if (customerDetail && customerDetail.id) {
requestEditCustomer(customerDetail.id, formValues)
const formValues = { ...values, status: payload.publish };
if (customer && customer.id) {
requestEditCustomer(customer.id, formValues)
.then((response) => {
AppToaster.show({
message: formatMessage({
@@ -163,8 +176,9 @@ function CustomerForm({
intent: Intent.SUCCESS,
});
setSubmitting(false);
history.push('/customers');
// history.push('/customers');
resetForm();
saveInvokeSubmit({ action: 'update', ...payload });
})
.catch((errors) => {
setSubmitting(false);
@@ -178,7 +192,9 @@ function CustomerForm({
}),
intent: Intent.SUCCESS,
});
history.push('/customers');
// history.push('/customers');
setSubmitting(false);
saveInvokeSubmit({ action: 'new', ...payload });
})
.catch((errors) => {
setSubmitting(false);
@@ -202,8 +218,8 @@ function CustomerForm({
);
const initialAttachmentFiles = useMemo(() => {
return customerDetail && customerDetail.media
? customerDetail.media.map((attach) => ({
return customer && customer.media
? customer.media.map((attach) => ({
preview: attach.attachment_file,
upload: true,
metadata: { ...attach },
@@ -224,11 +240,20 @@ function CustomerForm({
},
[setDeletedFiles, deletedFiles],
);
const handleSubmitClick = useCallback(
(payload) => {
setPayload(payload);
formik.handleSubmit();
},
[setPayload, formik],
);
const handleCancelClickBtn = () => {
history.goBack();
};
const handleCancelClick = useCallback(
(payload) => {
onCancelForm && onCancelForm(payload);
},
[onCancelForm],
);
return (
<div className={'customer-form'}>
<form onSubmit={formik.handleSubmit}>
@@ -396,34 +421,14 @@ function CustomerForm({
</FormGroup>
<CustomersTabs formik={formik} />
<div class="form__floating-footer">
<Button intent={Intent.PRIMARY} disabled={isSubmitting} type="submit">
{customerDetail && customerDetail.id ? (
<T id={'edit'} />
) : (
<T id={'save'} />
)}
</Button>
<Button
disabled={isSubmitting}
intent={Intent.PRIMARY}
className={'ml1'}
name={'save_and_new'}
>
<T id={'save_new'} />
</Button>
<Button className={'ml1'} disabled={isSubmitting}>
<T id={'save_as_draft'} />
</Button>
<Button className={'ml1'} onClick={handleCancelClickBtn}>
<T id={'close'} />
</Button>
</div>
</form>
<CustomerFloatingFooter
formik={formik}
onSubmitClick={handleSubmitClick}
customer={customer}
onCancelClick={handleCancelClick}
/>
</div>
);
}

View File

@@ -137,21 +137,21 @@ function CustomersList({
[fetchCustomers],
);
// Handle items bulk delete button click.,
// Handle Customers bulk delete button click.,
const handleBulkDelete = useCallback(
(itemsIds) => {
setBulkDelete(itemsIds);
(customersIds) => {
setBulkDelete(customersIds);
},
[setBulkDelete],
);
// Handle cancel accounts bulk delete.
// Handle cancel cusomters bulk delete.
const handleCancelBulkDelete = useCallback(() => {
setBulkDelete(false);
}, []);
// Handle confirm items bulk delete.
// Handle confirm customers bulk delete.
const handleConfirmBulkDelete = useCallback(() => {
requestDeleteBulkCustomers(bulkDelete)
.then(() => {
@@ -163,7 +163,7 @@ function CustomersList({
intent: Intent.SUCCESS,
});
})
.catch((errors) => {
.catch((error) => {
setBulkDelete(false);
});
}, [requestDeleteBulkCustomers, bulkDelete, formatMessage]);

View File

@@ -2,7 +2,7 @@ import { connect } from 'react-redux';
import { getCustomerById } from 'store/customers/customers.reducer';
const mapStateToProps = (state, props) => ({
customerDetail: getCustomerById(state, props.customerId),
customer: getCustomerById(state, props.customerId),
});
export default connect(mapStateToProps);

View File

@@ -4,13 +4,14 @@ import {
submitCustomer,
editCustomer,
deleteCustomer,
deleteBulkCustomers
} from 'store/customers/customers.actions';
import t from 'store/types';
export const mapDispatchToProps = (dispatch) => ({
requestFetchCustomers: (query) => dispatch(fetchCustomers({ query })),
requestDeleteCustomer: (id) => dispatch(deleteCustomer({ id })),
// requestDeleteBulkCustomers:(ids)=>dispatch(deleteBulkCustomers({ids})),
requestDeleteBulkCustomers:(ids)=>dispatch(deleteBulkCustomers({ids})),
requestSubmitCustomer: (form) => dispatch(submitCustomer({ form })),
requestEditCustomer: (id, form) => dispatch(editCustomer({ id, form })),

View File

@@ -39,10 +39,10 @@ function ExpensesDataTable({
changeCurrentView,
changePageSubtitle,
setTopbarEditView,
// #withView
viewMeta,
// #ownProps
loading,
onFetchData,
@@ -99,10 +99,9 @@ function ExpensesDataTable({
const actionMenuList = useCallback(
(expense) => (
<Menu>
<MenuItem
text={formatMessage({ id: 'view_details' })} />
<MenuItem text={formatMessage({ id: 'view_details' })} />
<MenuDivider />
<If condition={expense.published}>
<If condition={!expense.published}>
<MenuItem
text={formatMessage({ id: 'publish_expense' })}
onClick={handlePublishExpense(expense)}
@@ -120,23 +119,35 @@ function ExpensesDataTable({
/>
</Menu>
),
[handleEditExpense, handleDeleteExpense, handlePublishExpense, formatMessage],
[
handleEditExpense,
handleDeleteExpense,
handlePublishExpense,
formatMessage,
],
);
const onRowContextMenu = useCallback((cell) => {
return actionMenuList(cell.row.original);
}, [actionMenuList]);
const onRowContextMenu = useCallback(
(cell) => {
return actionMenuList(cell.row.original);
},
[actionMenuList],
);
const expenseAccountAccessor = (expense) => {
if (expense.categories.length === 1) {
return expense.categories[0].expense_account.name;
} else if (expense.categories.length > 1) {
const mutliCategories = expense.categories.map(category =>
(<div>- {category.expense_account.name} ${ category.amount }</div>)
const expenseAccountAccessor = (_expense) => {
if (_expense.categories.length === 1) {
return _expense.categories[0].expense_account.name;
} else if (_expense.categories.length > 1) {
const mutliCategories = _expense.categories.map((category) => (
<div>
- {category.expense_account.name} ${category.amount}
</div>
));
return (
<Tooltip content={mutliCategories}>{'- Multi Categories -'}</Tooltip>
);
return <Tooltip content={mutliCategories}>{ '- Multi Categories -' }</Tooltip>;
}
}
};
const columns = useMemo(
() => [
@@ -180,7 +191,7 @@ function ExpensesDataTable({
id: 'publish',
Header: formatMessage({ id: 'publish' }),
accessor: (r) => {
return !r.published ? (
return r.published ? (
<Tag minimal={true}>
<T id={'published'} />
</Tag>
@@ -279,5 +290,5 @@ export default compose(
expensesLoading,
expensesPagination,
})),
withViewDetails,
withViewDetails(),
)(ExpensesDataTable);

View File

@@ -2,42 +2,56 @@ import React from 'react';
import { Intent, Button } from '@blueprintjs/core';
import { FormattedMessage as T } from 'react-intl';
export default function ExpenseFooter({
export default function ExpenseFloatingFooter({
formik: { isSubmitting },
onSubmitClick,
onCancelClick,
expense,
}) {
return (
<div className={'form__floating-footer'}>
<Button
disabled={isSubmitting}
intent={Intent.PRIMARY}
className={'ml1'}
name={'save'}
disabled={isSubmitting}
type="submit"
onClick={() => {
onSubmitClick({ publish: true, redirect: true });
}}
>
<T id={'save'} />
{expense && expense.id ? <T id={'edit'} /> : <T id={'save'} />}
</Button>
<Button
disabled={isSubmitting}
className={'button-secondary ml1'}
intent={Intent.PRIMARY}
className={'ml1'}
name={'save_and_new'}
onClick={() => {
onSubmitClick({ publish: true, redirect: false });
}}
>
<T id={'save_as_draft'} />
<T id={'save_new'} />
</Button>
<Button
className={'button-secondary ml1'}
className={'ml1'}
disabled={isSubmitting}
onClick={() => {
onCancelClick && onCancelClick({ publish: false, redirect: false });
onSubmitClick({ publish: false, redirect: false });
}}
>
<T id={'cancel'} />
<T id={'save_as_draft'} />
</Button>
<Button
className={'ml1'}
onClick={() => {
onCancelClick && onCancelClick();
}}
>
<T id={'close'} />
</Button>
</div>
);
};
}

View File

@@ -11,15 +11,13 @@ import moment from 'moment';
import { Intent, FormGroup, TextArea } from '@blueprintjs/core';
import { FormattedMessage as T, useIntl } from 'react-intl';
import { pick } from 'lodash';
import { useQuery } from 'react-query';
import { Col, Row } from 'react-grid-system';
import ExpenseFormHeader from './ExpenseFormHeader';
import ExpenseTable from './ExpenseTable';
import ExpenseFloatingFooter from './ExpenseFooter';
import withExpensesActions from 'containers/Expenses/withExpensesActions';
import withExpneseDetail from 'containers/Expenses/withExpenseDetail';
import withExpenseDetail from 'containers/Expenses/withExpenseDetail';
import withAccountsActions from 'containers/Accounts/withAccountsActions';
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
import withMediaActions from 'containers/Media/withMediaActions';
@@ -44,13 +42,14 @@ function ExpenseForm({
changePageSubtitle,
//#withExpenseDetail
// @todo expenseDetail to expense
expenseDetail,
expense,
// #own Props
expenseId,
onFormSubmit,
onCancelForm,
onClickAddNewRow,
onClickRemoveRow,
}) {
const { formatMessage } = useIntl();
const [payload, setPayload] = useState({});
@@ -75,18 +74,17 @@ function ExpenseForm({
};
useEffect(() => {
if (expenseDetail && expenseDetail.id) {
if (expense && expense.id) {
changePageTitle(formatMessage({ id: 'edit_expense' }));
// changePageSubtitle(`No. ${expenseDetail.payment_account_id}`);
} else {
changePageTitle(formatMessage({ id: 'new_expense' }));
}
// @todo not functions just states.
}, [changePageTitle, changePageSubtitle, expenseDetail, formatMessage]);
}, [changePageTitle, changePageSubtitle, expense, formatMessage]);
const validationSchema = Yup.object().shape({
beneficiary: Yup.string()
// .required()
.label(formatMessage({ id: 'beneficiary' })),
payment_account_id: Yup.string()
.required()
@@ -104,8 +102,12 @@ function ExpenseForm({
Yup.object().shape({
index: Yup.number().nullable(),
amount: Yup.number().nullable(),
// @todo expense_account_id is required.
expense_account_id: Yup.number().nullable(),
expense_account_id: Yup.number()
.nullable()
.when(['amount'], {
is: (amount) => amount,
then: Yup.number().required(),
}),
description: Yup.string().nullable(),
}),
),
@@ -115,6 +117,7 @@ function ExpenseForm({
(payload) => {
onFormSubmit && onFormSubmit(payload);
},
[onFormSubmit],
);
@@ -146,32 +149,41 @@ function ExpenseForm({
[defaultCategory],
);
const orderingCategoriesIndex = (categories) => {
return categories.map((category, index) => ({
...category,
index: index + 1,
}));
};
const initialValues = useMemo(
() => ({
...(expenseDetail
...(expense
? {
...pick(expenseDetail, Object.keys(defaultInitialValues)),
categories: expenseDetail.categories.map((category) => ({
...pick(expense, Object.keys(defaultInitialValues)),
categories: expense.categories.map((category) => ({
...pick(category, Object.keys(defaultCategory)),
}),
),
})),
}
: {
...defaultInitialValues,
categories: orderingCategoriesIndex(
defaultInitialValues.categories,
),
}),
}),
[expenseDetail, defaultInitialValues, defaultCategory],
[expense, defaultInitialValues, defaultCategory],
);
const initialAttachmentFiles = useMemo(() => {
return expenseDetail && expenseDetail.media
? expenseDetail.media.map((attach) => ({
return expense && expense.media
? expense.media.map((attach) => ({
preview: attach.attachment_file,
uploaded: true,
metadata: { ...attach },
}))
: [];
}, [expenseDetail]);
}, [expense]);
const formik = useFormik({
enableReinitialize: true,
@@ -181,11 +193,12 @@ function ExpenseForm({
},
onSubmit: async (values, { setSubmitting, setErrors, resetForm }) => {
const categories = values.categories.filter(
(category) => category.amount || category.index,
(category) =>
category.amount && category.index && category.expense_account_id,
);
const form = {
...values,
published: payload.publish,
publish: payload.publish,
categories,
};
@@ -193,8 +206,8 @@ function ExpenseForm({
new Promise((resolve, reject) => {
const requestForm = { ...form, media_ids: mdeiaIds };
if (expenseDetail && expenseDetail.id) {
requestEditExpense(expenseDetail.id, requestForm)
if (expense && expense.id) {
requestEditExpense(expense.id, requestForm)
.then((response) => {
AppToaster.show({
message: formatMessage(
@@ -207,10 +220,8 @@ function ExpenseForm({
saveInvokeSubmit({ action: 'update', ...payload });
clearSavedMediaIds([]);
resetForm();
resolve(response);
})
.catch((errors) => {
// @todo handle errors.
if (errors.find((e) => e.type === 'TOTAL.AMOUNT.EQUALS.ZERO')) {
}
setErrors(
@@ -234,10 +245,11 @@ function ExpenseForm({
intent: Intent.SUCCESS,
});
setSubmitting(false);
formik.resetForm();
saveInvokeSubmit({ action: 'new', ...payload });
clearSavedMediaIds();
resetForm();
resolve(response);
// resolve(response);
})
.catch((errors) => {
setSubmitting(false);
@@ -260,6 +272,7 @@ function ExpenseForm({
const handleSubmitClick = useCallback(
(payload) => {
setPayload(payload);
formik.resetForm();
formik.handleSubmit();
},
[setPayload, formik],
@@ -313,13 +326,13 @@ function ExpenseForm({
hint={'Attachments: Maxiumum size: 20MB'}
/>
</div>
<ExpenseFloatingFooter
formik={formik}
onSubmitClick={handleSubmitClick}
onCancelClick={handleCancelClick}
/>
</form>
<ExpenseFloatingFooter
formik={formik}
onSubmitClick={handleSubmitClick}
expense={expense}
onCancelClick={handleCancelClick}
/>
</div>
);
}
@@ -329,5 +342,5 @@ export default compose(
withAccountsActions,
withDashboardActions,
withMediaActions,
withExpneseDetail(),
withExpenseDetail(),
)(ExpenseForm);

View File

@@ -28,6 +28,7 @@ function ExpenseFormHeader({
formik: { errors, touched, setFieldValue, getFieldProps, values },
currenciesList,
accounts,
accountsTypes,
}) {
const [selectedItems, setSelectedItems] = useState({});
@@ -102,7 +103,6 @@ function ExpenseFormHeader({
const onItemsSelect = useCallback(
(filedName) => {
return (filed) => {
// @todo @mohamed
setSelectedItems({
...selectedItems,
[filedName]: filed,
@@ -256,8 +256,9 @@ function ExpenseFormHeader({
}
export default compose(
withAccounts(({ accounts }) => ({
withAccounts(({ accounts, accountsTypes }) => ({
accounts,
accountsTypes,
})),
withCurrencies(({ currenciesList }) => ({
currenciesList,

View File

@@ -41,15 +41,20 @@ function ExpenseTable({
(rowIndex, columnId, value) => {
const newRows = rows.map((row, index) => {
if (index === rowIndex) {
return { ...rows[rowIndex], [columnId]: value };
return {
...rows[rowIndex],
[columnId]: value,
};
}
return { ...row };
});
setRow(newRows);
setFieldValue(
'categories',
newRows.map((row) => ({
newRows.map((row, index) => ({
...omit(row, ['rowType']),
index: index + 1,
})),
);
},
@@ -60,15 +65,28 @@ function ExpenseTable({
const handleRemoveRow = useCallback(
(rowIndex) => {
const removeIndex = parseInt(rowIndex, 10);
const newRows = rows.filter((row, index) => index !== removeIndex);
const newRows = rows.filter((row, index) => index !== removeIndex);
setRow([...newRows]);
setFieldValue(
'categories',
newRows
.filter((row) => row.rowType === 'editor')
.map((row) => ({ ...omit(row, ['rowType']) })),
.map((row, index) => ({
...omit(row, ['rowType']),
index: index + 1,
})),
);
// const newRows = rows.filter((row, index) => index !== removeIndex);
// setRow([...newRows]);
// setFieldValue(
// 'categories',
// newRows
// .filter((row) => row.rowType === 'editor')
// .map((row) => ({ ...omit(row, ['rowType']) })),
// );
onClickRemoveRow && onClickRemoveRow(removeIndex);
},
[rows, setFieldValue, onClickRemoveRow],
@@ -82,7 +100,7 @@ function ExpenseTable({
data,
payload,
}) => {
if (data.length <= index + 2) {
if (data.length <= index + 1) {
return '';
}
const onClickRemoveRole = () => {
@@ -104,7 +122,7 @@ function ExpenseTable({
// Total text cell renderer.
const TotalExpenseCellRenderer = (chainedComponent) => (props) => {
if (props.data.length === props.row.index + 2) {
if (props.data.length <= props.row.index + 1) {
return (
<span>
{formatMessage({ id: 'total_currency' }, { currency: 'USD' })}
@@ -115,14 +133,14 @@ function ExpenseTable({
};
const NoteCellRenderer = (chainedComponent) => (props) => {
if (props.data.length === props.row.index + 2) {
if (props.data.length === props.row.index + 1) {
return '';
}
return chainedComponent(props);
};
const TotalAmountCellRenderer = (chainedComponent, type) => (props) => {
if (props.data.length === props.row.index + 2) {
if (props.data.length === props.row.index + 1) {
const total = props.data.reduce((total, entry) => {
const amount = parseInt(entry[type], 10);
const computed = amount ? total + amount : total;
@@ -147,7 +165,12 @@ function ExpenseTable({
disableSortBy: true,
},
{
Header: (<>{ formatMessage({ id: 'expense_category' }) }<Hint /></>),
Header: (
<>
{formatMessage({ id: 'expense_category' })}
<Hint />
</>
),
id: 'expense_account_id',
accessor: 'expense_account_id',
Cell: TotalExpenseCellRenderer(AccountsListFieldCell),
@@ -193,7 +216,7 @@ function ExpenseTable({
const rowClassNames = useCallback(
(row) => ({
'row--total': rows.length === row.index + 2,
'row--total': rows.length === row.index + 1,
}),
[rows],
);

View File

@@ -96,11 +96,11 @@ const withExpensesViewTabs = connect(mapStateToProps);
export default compose(
withRouter,
withViewDetails(),
withExpensesViewTabs,
withExpensesActions,
withDashboardActions,
withViewDetails(),
withExpenses(({ expensesViews }) => ({
expensesViews,
})),
withExpensesActions,
withDashboardActions,
)(ExpenseViewTabs);

View File

@@ -14,6 +14,7 @@ import { compose } from 'utils';
function Expenses({
// #withwithAccountsActions
requestFetchAccounts,
requestFetchAccountTypes,
// #withExpensesActions
requestFetchExpense,
@@ -24,18 +25,17 @@ function Expenses({
const history = useHistory();
const { id } = useParams();
// @todo
const fetchAccounts = useQuery('accounts-expense-list', (key) =>
const fetchAccounts = useQuery('accounts-list', (key) =>
requestFetchAccounts(),
);
// @todo
const fetchExpense = useQuery(id && ['expense', id], (key, expense_Id) =>
requestFetchExpense(expense_Id),
const fetchExpense = useQuery(
['expense', id],
(key, _id) => requestFetchExpense(_id),
{ enabled: !!id },
);
// @todo
const fetchCurrencies = useQuery('currencies-expense-list', () =>
const fetchCurrencies = useQuery('currencies', () =>
requestFetchCurrencies(),
);
const handleFormSubmit = useCallback(
@@ -46,7 +46,7 @@ function Expenses({
);
const handleCancel = useCallback(() => {
history.push('/expenses-list');
history.goBack();
}, [history]);
return (
@@ -56,6 +56,7 @@ function Expenses({
fetchAccounts.isFetching ||
fetchCurrencies.isFetching
}
name={'expense-form'}
>
<ExpenseForm
onFormSubmit={handleFormSubmit}

View File

@@ -19,7 +19,6 @@ import withViewsActions from 'containers/Views/withViewsActions';
import { compose } from 'utils';
function ExpensesList({
// #withDashboardActions
changePageTitle,
@@ -223,7 +222,7 @@ function ExpensesList({
</p>
</Alert>
{/* <Alert
<Alert
cancelButtonText={<T id={'cancel'} />}
confirmButtonText={
<T id={'delete_count'} values={{ count: selectedRowsCount }} />
@@ -236,10 +235,10 @@ function ExpensesList({
>
<p>
<T
id={'once_delete_these_journalss_you_will_not_able_restore_them'}
id={'once_delete_these_expenses_you_will_not_able_restore_them'}
/>
</p>
</Alert> */}
</Alert>
</DashboardPageContent>
</DashboardInsider>
);
@@ -248,7 +247,7 @@ function ExpensesList({
export default compose(
withDashboardActions,
withExpensesActions,
withExpenses(({ expensesTableQuery }) => ({ expensesTableQuery })),
withViewsActions,
withResourceActions
withResourceActions,
withExpenses(({ expensesTableQuery }) => ({ expensesTableQuery })),
)(ExpensesList);

View File

@@ -14,7 +14,6 @@ export default (mapState) => {
const mapStateToProps = (state, props) => {
const query = getExpensesTableQuery(state, props);
const mapped = {
expensesCurrentPage: getExpensesItems(state, props, query),
expensesViews: getResourceViews(state, props, 'expenses'),

View File

@@ -10,7 +10,7 @@ import {
} from 'store/expenses/expenses.actions';
import t from 'store/types';
export const mapDispatchToProps = (dispatch) => ({
const mapDispatchToProps = (dispatch) => ({
requestSubmitExpense: (form) => dispatch(submitExpense({ form })),
requestFetchExpense: (id) => dispatch(fetchExpense({ id })),
requestEditExpense: (id, form) => dispatch(editExpense({ id, form })),

View File

@@ -49,7 +49,7 @@ const ItemCategoryList = ({
}, [id, changePageTitle, formatMessage]);
const fetchCategories = useQuery(
['items-categories-table', filter],
['items-categories-list', filter],
(key, query) => requestFetchItemCategories(query),
);
@@ -183,7 +183,9 @@ const ItemCategoryList = ({
>
<p>
<FormattedHTMLMessage
id={'once_delete_these_item_categories_you_will_not_able_restore_them'}
id={
'once_delete_these_item_categories_you_will_not_able_restore_them'
}
/>
</p>
</Alert>

View File

@@ -1,5 +1,5 @@
import React, {useCallback } from 'react';
import { useParams,useHistory } from 'react-router-dom';
import React, { useCallback } from 'react';
import { useParams, useHistory } from 'react-router-dom';
import { useQuery } from 'react-query';
import DashboardInsider from 'components/Dashboard/DashboardInsider';
@@ -12,7 +12,6 @@ import withItemsActions from './withItemsActions';
import { compose } from 'utils';
const ItemFormContainer = ({
// #withDashboardActions
changePageTitle,
@@ -22,6 +21,7 @@ const ItemFormContainer = ({
// #withItemsActions
requestFetchItems,
requestFetchItem,
// #withItemCategoriesActions
requestFetchItemCategories,
@@ -29,35 +29,47 @@ const ItemFormContainer = ({
const { id } = useParams();
const history = useHistory();
const fetchAccounts = useQuery('accounts-list',
(key) => requestFetchAccounts());
const fetchAccounts = useQuery('accounts-list', (key) =>
requestFetchAccounts(),
);
const fetchCategories = useQuery('item-categories-list',
(key) => requestFetchItemCategories());
const fetchCategories = useQuery('item-categories-list', (key) =>
requestFetchItemCategories(),
);
const fetchItemDetail = useQuery(
id && ['item-detail-list', id],
(key) => requestFetchItems());
const fetchItemDetail = useQuery(
['item', id],
(key, _id) => requestFetchItem(_id),
{
enabled: !!id,
},
);
const handleFormSubmit =useCallback((payload)=>{
const handleFormSubmit = useCallback(
(payload) => {
payload.redirect && history.push('/items');
},
[history],
);
payload.redirect && history.push('/items/new');
},[history])
const handleCancel =useCallback(()=>{
history.push('/items/new');
},[history])
const handleCancel = useCallback(() => {
// history.push('/items');
history.goBack();
}, [history]);
return (
<DashboardInsider
loading={fetchItemDetail.isFetching || fetchAccounts.isFetching || fetchCategories.isFetching }
name={'item-form'}>
<ItemForm
itemId={id}
onFormSubmit={handleFormSubmit}
onCancelForm={handleCancel}
loading={
fetchItemDetail.isFetching ||
fetchAccounts.isFetching ||
fetchCategories.isFetching
}
name={'item-form'}
>
<ItemForm
onFormSubmit={handleFormSubmit}
itemId={id}
onCancelForm={handleCancel}
/>
</DashboardInsider>
);
@@ -67,5 +79,5 @@ export default compose(
withDashboardActions,
withAccountsActions,
withItemCategoriesActions,
withItemsActions
withItemsActions,
)(ItemFormContainer);

View File

@@ -0,0 +1,56 @@
import React from 'react';
import { Intent, Button } from '@blueprintjs/core';
import { FormattedMessage as T } from 'react-intl';
export default function ItemFloatingFooter({
formik: { isSubmitting },
onSubmitClick,
onCancelClick,
itemDetail,
}) {
return (
<div class="form__floating-footer">
<Button
intent={Intent.PRIMARY}
disabled={isSubmitting}
type="submit"
onClick={() => {
onSubmitClick({ publish: true, redirect: true });
}}
>
{itemDetail && itemDetail.id ? <T id={'edit'} /> : <T id={'save'} />}
</Button>
<Button
disabled={isSubmitting}
intent={Intent.PRIMARY}
className={'ml1'}
name={'save_and_new'}
onClick={() => {
onSubmitClick({ publish: true, redirect: false });
}}
>
<T id={'save_new'} />
</Button>
<Button
className={'ml1'}
disabled={isSubmitting}
onClick={() => {
onSubmitClick({ publish: false, redirect: false });
}}
>
<T id={'save_as_draft'} />
</Button>
<Button
className={'ml1'}
onClick={() => {
onCancelClick && onCancelClick();
}}
>
<T id={'close'} />
</Button>
</div>
);
}

View File

@@ -1,6 +1,7 @@
import {connect} from 'react-redux';
import {
fetchItems,
fetchItem,
deleteItem,
submitItem,
editItem,
@@ -10,6 +11,7 @@ import t from 'store/types';
export const mapDispatchToProps = (dispatch) => ({
requestFetchItems: (query) => dispatch(fetchItems({ query })),
requestFetchItem: (id) => dispatch(fetchItem({ id })),
requestDeleteItem: (id) => dispatch(deleteItem({ id })),
requestDeleteBulkItems:(ids)=>dispatch(deleteBulkItems({ids})),
requestSubmitItem: (form) => dispatch(submitItem({ form })),