From d299785bfbef93e197f2dba0bf44c13d9a096c53 Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Tue, 1 Dec 2020 15:14:05 +0200 Subject: [PATCH 1/7] feat: auto-focus first fields. --- .../Customers/CustomerFormPrimarySection.js | 7 +++++-- .../AccountFormDialogContent.js | 4 ++-- .../AccountFormDialog/AccountFormDialogFields.js | 10 ++++++++-- .../ItemCategoryDialog/ItemCategoryForm.js | 10 +++++++++- .../containers/Items/ItemFormPrimarySection.js | 16 ++++++++++++++-- .../Vendors/VendorFormPrimarySection.js | 5 +++++ client/src/hooks/index.js | 6 +++--- client/src/hooks/useAutofocus.js | 13 +++++++++++++ 8 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 client/src/hooks/useAutofocus.js diff --git a/client/src/containers/Customers/CustomerFormPrimarySection.js b/client/src/containers/Customers/CustomerFormPrimarySection.js index 46afad8a1..d29410a23 100644 --- a/client/src/containers/Customers/CustomerFormPrimarySection.js +++ b/client/src/containers/Customers/CustomerFormPrimarySection.js @@ -12,12 +12,14 @@ import { import CustomerTypeRadioField from 'containers/Customers/CustomerTypeRadioField'; import { CLASSES } from 'common/classes'; import { inputIntent } from 'utils'; +import { useAutofocus } from 'hooks'; /** * Customer form primary section. */ -export default function CustomerFormPrimarySection({ -}) { +export default function CustomerFormPrimarySection({}) { + const firstNameFieldRef = useAutofocus(); + return (
{/**-----------Customer type. -----------*/} @@ -54,6 +56,7 @@ export default function CustomerFormPrimarySection({ placeholder={'First Name'} intent={inputIntent({ error, touched })} className={classNames('input-group--first-name')} + inputRef={(ref) => (firstNameFieldRef.current = ref)} {...field} /> )} diff --git a/client/src/containers/Dialogs/AccountFormDialog/AccountFormDialogContent.js b/client/src/containers/Dialogs/AccountFormDialog/AccountFormDialogContent.js index 310343e1a..c90d5f999 100644 --- a/client/src/containers/Dialogs/AccountFormDialog/AccountFormDialogContent.js +++ b/client/src/containers/Dialogs/AccountFormDialog/AccountFormDialogContent.js @@ -1,8 +1,8 @@ -import React, { useCallback, useMemo, useEffect } from 'react'; +import React, { useCallback } from 'react'; import { Intent } from '@blueprintjs/core'; import { Formik } from 'formik'; import { FormattedMessage as T, useIntl } from 'react-intl'; -import { pick, omit } from 'lodash'; +import { omit } from 'lodash'; import { useQuery, queryCache } from 'react-query'; import { AppToaster, DialogContent } from 'components'; diff --git a/client/src/containers/Dialogs/AccountFormDialog/AccountFormDialogFields.js b/client/src/containers/Dialogs/AccountFormDialog/AccountFormDialogFields.js index e4eecc585..68f8b4178 100644 --- a/client/src/containers/Dialogs/AccountFormDialog/AccountFormDialogFields.js +++ b/client/src/containers/Dialogs/AccountFormDialog/AccountFormDialogFields.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import { Form, FastField, Field, ErrorMessage, useFormikContext } from 'formik'; import classNames from 'classnames'; import { FormattedMessage as T } from 'react-intl'; @@ -22,6 +22,7 @@ import withAccounts from 'containers/Accounts/withAccounts'; import { inputIntent } from 'utils'; import { compose } from 'redux'; +import { useAutofocus } from 'hooks'; /** * Account form dialogs fields. @@ -36,6 +37,7 @@ function AccountFormDialogFields({ accountsTypes, }) { const { values, isSubmitting } = useFormikContext(); + const accountNameFieldRef = useAutofocus(); return (
@@ -75,7 +77,11 @@ function AccountFormDialogFields({ helperText={} inline={true} > - + (accountNameFieldRef.current = ref)} + {...field} + /> )} diff --git a/client/src/containers/Dialogs/ItemCategoryDialog/ItemCategoryForm.js b/client/src/containers/Dialogs/ItemCategoryDialog/ItemCategoryForm.js index 09dad964b..a55fbf414 100644 --- a/client/src/containers/Dialogs/ItemCategoryDialog/ItemCategoryForm.js +++ b/client/src/containers/Dialogs/ItemCategoryDialog/ItemCategoryForm.js @@ -19,6 +19,8 @@ import { } from 'components'; import { inputIntent } from 'utils'; +import { useAutofocus } from 'hooks'; + export default function ItemCategoryForm({ itemCategoryId, accountsList, @@ -26,6 +28,8 @@ export default function ItemCategoryForm({ isSubmitting, onClose, }) { + const categoryNameFieldRef = useAutofocus(); + // Filters Item Categories list. const filterItemCategories = useCallback( (query, category, _index, exactMatch) => { @@ -68,7 +72,11 @@ export default function ItemCategoryForm({ helperText={} inline={true} > - + (categoryNameFieldRef.current = ref)} + {...field} + /> )} diff --git a/client/src/containers/Items/ItemFormPrimarySection.js b/client/src/containers/Items/ItemFormPrimarySection.js index d35bcc4fc..441834160 100644 --- a/client/src/containers/Items/ItemFormPrimarySection.js +++ b/client/src/containers/Items/ItemFormPrimarySection.js @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react'; +import React, { useEffect, useRef } from 'react'; import { FormGroup, InputGroup, @@ -40,6 +40,14 @@ function ItemFormPrimarySection({ // #ownProps itemType, }) { + const nameFieldRef = useRef(null); + + useEffect(() => { + // Auto focus item name field once component mount. + if (nameFieldRef.current) { + nameFieldRef.current.focus(); + } + }, []); const itemTypeHintContent = ( <> @@ -112,7 +120,11 @@ function ItemFormPrimarySection({ helperText={} inline={true} > - + (nameFieldRef.current = ref)} + /> )} diff --git a/client/src/containers/Vendors/VendorFormPrimarySection.js b/client/src/containers/Vendors/VendorFormPrimarySection.js index e68cd3e34..c1bf1830e 100644 --- a/client/src/containers/Vendors/VendorFormPrimarySection.js +++ b/client/src/containers/Vendors/VendorFormPrimarySection.js @@ -13,10 +13,14 @@ import { import { CLASSES } from 'common/classes'; import { inputIntent } from 'utils'; +import { useAutofocus } from 'hooks'; + /** * Vendor form primary section. */ function VendorFormPrimarySection() { + const firstNameFieldRef = useAutofocus(); + return (
{/**----------- Vendor name -----------*/} @@ -50,6 +54,7 @@ function VendorFormPrimarySection() { placeholder={'First Name'} intent={inputIntent({ error, touched })} className={classNames('input-group--first-name')} + inputRef={(ref) => (firstNameFieldRef.current = ref)} {...field} /> )} diff --git a/client/src/hooks/index.js b/client/src/hooks/index.js index 9f654ad77..66a6c87bf 100644 --- a/client/src/hooks/index.js +++ b/client/src/hooks/index.js @@ -1,5 +1,6 @@ import {useRef, useEffect} from 'react'; import useAsync from './async'; +import useAutofocus from './useAutofocus'; // import use from 'async'; @@ -34,8 +35,7 @@ export function useIsValuePassed(value, compatatorValue) { return cache.current.indexOf(compatatorValue) !== -1; } - -export default { +export { useAsync, - useUpdateEffect, + useAutofocus, } \ No newline at end of file diff --git a/client/src/hooks/useAutofocus.js b/client/src/hooks/useAutofocus.js new file mode 100644 index 000000000..0546956f2 --- /dev/null +++ b/client/src/hooks/useAutofocus.js @@ -0,0 +1,13 @@ +import { useRef, useEffect } from 'react'; + +export default function useAutofocus() { + const ref = useRef(); + + useEffect(() => { + if (ref.current) { + ref.current.focus(); + } + }, [ref]); + + return ref; +} From 7a11b4255c439f2345df2fdca4c426d0c5bbc1d4 Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Tue, 1 Dec 2020 18:00:26 +0200 Subject: [PATCH 2/7] fix: Expense & FloatingActions. --- .../Expenses/ExpenseFloatingActions.js | 17 ++-- client/src/containers/Expenses/ExpenseForm.js | 78 +++++++++++++------ 2 files changed, 60 insertions(+), 35 deletions(-) diff --git a/client/src/containers/Expenses/ExpenseFloatingActions.js b/client/src/containers/Expenses/ExpenseFloatingActions.js index e66af0918..e04999ad1 100644 --- a/client/src/containers/Expenses/ExpenseFloatingActions.js +++ b/client/src/containers/Expenses/ExpenseFloatingActions.js @@ -23,13 +23,11 @@ export default function ExpenseFloatingFooter({ isSubmitting, onSubmitClick, onCancelClick, - onDraftClick, - onClearClick, - onSubmitForm, - onResetForm, expense, expensePublished, }) { + const { submitForm, resetForm } = useFormikContext(); + const handleSubmitPublishBtnClick = (event) => { saveInvoke(onSubmitClick, event, { redirect: true, @@ -38,7 +36,7 @@ export default function ExpenseFloatingFooter({ }; const handleSubmitPublishAndNewBtnClick = (event) => { - onSubmitForm(); + submitForm(); saveInvoke(onSubmitClick, event, { redirect: false, publish: true, @@ -47,7 +45,7 @@ export default function ExpenseFloatingFooter({ }; const handleSubmitPublishContinueEditingBtnClick = (event) => { - onSubmitForm(); + submitForm(); saveInvoke(onSubmitClick, event, { redirect: false, publish: true, @@ -62,7 +60,7 @@ export default function ExpenseFloatingFooter({ }; const handleSubmitDraftAndNewBtnClick = (event) => { - onSubmitForm(); + submitForm(); saveInvoke(onSubmitClick, event, { redirect: false, publish: false, @@ -71,7 +69,7 @@ export default function ExpenseFloatingFooter({ }; const handleSubmitDraftContinueEditingBtnClick = (event) => { - onSubmitForm(); + submitForm(); saveInvoke(onSubmitClick, event, { redirect: false, publish: false, @@ -84,9 +82,8 @@ export default function ExpenseFloatingFooter({ const handleClearBtnClick = (event) => { // saveInvoke(onClearClick, event); - onResetForm(); + resetForm(); }; - return (
{/* ----------- Save And Publish ----------- */} diff --git a/client/src/containers/Expenses/ExpenseForm.js b/client/src/containers/Expenses/ExpenseForm.js index b78985d15..2abffd6bc 100644 --- a/client/src/containers/Expenses/ExpenseForm.js +++ b/client/src/containers/Expenses/ExpenseForm.js @@ -1,13 +1,11 @@ -import React, { - useMemo, - useEffect, -} from 'react'; +import React, { useMemo, useEffect,useState,useCallback } from 'react'; import { Intent } from '@blueprintjs/core'; import { useIntl } from 'react-intl'; import { defaultTo, pick } from 'lodash'; import { Formik, Form } from 'formik'; import moment from 'moment'; import classNames from 'classnames'; +import { useHistory } from 'react-router-dom'; import { CLASSES } from 'common/classes'; import ExpenseFormHeader from './ExpenseFormHeader'; @@ -28,9 +26,7 @@ import { CreateExpenseFormSchema, EditExpenseFormSchema, } from './ExpenseForm.schema'; -import { - transformErrors, -} from './utils'; +import { transformErrors } from './utils'; import { compose, repeatValue, orderingLinesIndexes } from 'utils'; const MIN_LINES_NUMBER = 4; @@ -49,6 +45,7 @@ const defaultInitialValues = { description: '', reference_no: '', currency_code: '', + is_published:'', categories: [...repeatValue(defaultCategory, MIN_LINES_NUMBER)], }; @@ -82,12 +79,14 @@ function ExpenseForm({ onCancelForm, }) { const isNewMode = !expenseId; + const [submitPayload, setSubmitPayload] = useState({}); const { formatMessage } = useIntl(); + const history = useHistory(); const validationSchema = isNewMode ? CreateExpenseFormSchema : EditExpenseFormSchema; - + useEffect(() => { if (isNewMode) { changePageTitle(formatMessage({ id: 'new_expense' })); @@ -115,9 +114,7 @@ function ExpenseForm({ } : { ...defaultInitialValues, - categories: orderingLinesIndexes( - defaultInitialValues.categories, - ), + categories: orderingLinesIndexes(defaultInitialValues.categories), }), }), [expense, baseCurrency, preferredPaymentAccount], @@ -146,22 +143,30 @@ function ExpenseForm({ const form = { ...values, - publish: 1, + is_published: submitPayload.publish, categories, }; // Handle request success. const handleSuccess = (response) => { AppToaster.show({ message: formatMessage( - { id: isNewMode ? - 'the_expense_has_been_successfully_created' : - 'the_expense_has_been_successfully_edited' }, + { + id: isNewMode + ? 'the_expense_has_been_successfully_created' + : 'the_expense_has_been_successfully_edited', + }, { number: values.payment_account_id }, ), intent: Intent.SUCCESS, }); setSubmitting(false); - resetForm(); + + if (submitPayload.redirect) { + history.push('/expenses'); + } + if (submitPayload.resetForm) { + resetForm(); + } }; // Handle request error @@ -172,16 +177,30 @@ function ExpenseForm({ if (isNewMode) { requestSubmitExpense(form).then(handleSuccess).catch(handleError); } else { - requestEditExpense(expense.id, form).then(handleSuccess).catch(handleError); + requestEditExpense(expense.id, form) + .then(handleSuccess) + .catch(handleError); } }; - + const handleCancelClick = useCallback(() => { + history.goBack(); + }, [history]); + + const handleSubmitClick = useCallback( + (event, payload) => { + setSubmitPayload({ ...payload }); + }, + [setSubmitPayload], + ); + return ( -
+
- + )} @@ -208,6 +233,9 @@ export default compose( withExpenseDetail(), withSettings(({ organizationSettings, expenseSettings }) => ({ baseCurrency: organizationSettings?.baseCurrency, - preferredPaymentAccount: parseInt(expenseSettings?.preferredPaymentAccount, 10), + preferredPaymentAccount: parseInt( + expenseSettings?.preferredPaymentAccount, + 10, + ), })), )(ExpenseForm); From 7947aadfb525847cda8f94bf78fda3137bd03d18 Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Tue, 1 Dec 2020 18:01:26 +0200 Subject: [PATCH 3/7] fix: currency_code & payement_account --- client/src/containers/Expenses/ExpenseForm.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/containers/Expenses/ExpenseForm.js b/client/src/containers/Expenses/ExpenseForm.js index 2abffd6bc..c86d8b26f 100644 --- a/client/src/containers/Expenses/ExpenseForm.js +++ b/client/src/containers/Expenses/ExpenseForm.js @@ -100,8 +100,6 @@ function ExpenseForm({ ...(expense ? { ...pick(expense, Object.keys(defaultInitialValues)), - currency_code: baseCurrency, - payment_account_id: defaultTo(preferredPaymentAccount, ''), categories: [ ...expense.categories.map((category) => ({ ...pick(category, Object.keys(defaultCategory)), @@ -114,6 +112,8 @@ function ExpenseForm({ } : { ...defaultInitialValues, + currency_code: baseCurrency, + payment_account_id: defaultTo(preferredPaymentAccount, ''), categories: orderingLinesIndexes(defaultInitialValues.categories), }), }), From f72f1a75e3856287c159d85720318ae92a70698a Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Tue, 1 Dec 2020 18:01:56 +0200 Subject: [PATCH 4/7] fix: reference_no in Expense. --- client/src/containers/Expenses/ExpenseForm.schema.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/containers/Expenses/ExpenseForm.schema.js b/client/src/containers/Expenses/ExpenseForm.schema.js index 8a5a6fd74..adb5ee608 100644 --- a/client/src/containers/Expenses/ExpenseForm.schema.js +++ b/client/src/containers/Expenses/ExpenseForm.schema.js @@ -11,7 +11,7 @@ const Schema = Yup.object().shape({ payment_date: Yup.date() .required() .label(formatMessage({ id: 'payment_date_' })), - reference_no: Yup.string().min(1).max(DATATYPES_LENGTH.STRING), + reference_no: Yup.string().min(1).max(DATATYPES_LENGTH.STRING).nullable(), currency_code: Yup.string() .nullable() .max(3) From b159cd2409f0fa065014be53a7f89ed2ff137800 Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Tue, 1 Dec 2020 19:07:28 +0200 Subject: [PATCH 5/7] fix: active checkbox in manual journal. --- client/src/containers/Items/ItemForm.js | 2 +- client/src/containers/Items/ItemForm.schema.js | 1 + client/src/containers/Items/ItemFormFloatingActions.js | 7 +++---- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/src/containers/Items/ItemForm.js b/client/src/containers/Items/ItemForm.js index 167ec4f12..67ed8446c 100644 --- a/client/src/containers/Items/ItemForm.js +++ b/client/src/containers/Items/ItemForm.js @@ -30,7 +30,7 @@ import { } from './ItemForm.schema'; const defaultInitialValues = { - active: true, + active: 1, name: '', type: 'service', code: '', diff --git a/client/src/containers/Items/ItemForm.schema.js b/client/src/containers/Items/ItemForm.schema.js index 0046d403f..76c0d09ad 100644 --- a/client/src/containers/Items/ItemForm.schema.js +++ b/client/src/containers/Items/ItemForm.schema.js @@ -64,6 +64,7 @@ export const transformItemFormData = (item, defaultValue) => { ...item, sellable: !!defaultTo(item?.sellable, defaultValue.sellable), purchasable: !!defaultTo(item?.purchasable, defaultValue.purchasable), + active: !!defaultTo(item?.active, defaultValue.active), }; } diff --git a/client/src/containers/Items/ItemFormFloatingActions.js b/client/src/containers/Items/ItemFormFloatingActions.js index 3005133df..e6a60ad47 100644 --- a/client/src/containers/Items/ItemFormFloatingActions.js +++ b/client/src/containers/Items/ItemFormFloatingActions.js @@ -6,7 +6,6 @@ import classNames from 'classnames'; import { FastField } from 'formik'; import { CLASSES } from 'common/classes'; - /** * Item form floating actions. */ @@ -56,13 +55,13 @@ export default function ItemFormFloatingActions({ {/*----------- Active ----------*/} - {({ form, field, field: { value } }) => ( + {({ field }) => ( } - checked={value} - onChange={() => form.setFieldValue('active', !value)} + name={'active'} + {...field} /> )} From 88b360b2acdc5fe585434f09ed819f90141ce828 Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Tue, 1 Dec 2020 20:30:51 +0200 Subject: [PATCH 6/7] fix: currency_code in Expense. --- client/src/containers/Expenses/ExpenseDataTable.js | 4 ++-- client/src/containers/Expenses/ExpenseFormHeader.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/containers/Expenses/ExpenseDataTable.js b/client/src/containers/Expenses/ExpenseDataTable.js index a8eea0755..347704cef 100644 --- a/client/src/containers/Expenses/ExpenseDataTable.js +++ b/client/src/containers/Expenses/ExpenseDataTable.js @@ -187,7 +187,7 @@ function ExpensesDataTable({ { id: 'total_amount', Header: formatMessage({ id: 'full_amount' }), - accessor: (r) => , + accessor: (r) => , className: 'total_amount', width: 150, }, @@ -209,7 +209,7 @@ function ExpensesDataTable({ id: 'publish', Header: formatMessage({ id: 'publish' }), accessor: (r) => { - return !!r.is_published ? ( + return r.is_published ? ( diff --git a/client/src/containers/Expenses/ExpenseFormHeader.js b/client/src/containers/Expenses/ExpenseFormHeader.js index 1e9122607..5ce47164a 100644 --- a/client/src/containers/Expenses/ExpenseFormHeader.js +++ b/client/src/containers/Expenses/ExpenseFormHeader.js @@ -23,7 +23,7 @@ export default function ExpenseFormHeader() {
); From 9c1edace50d274d12f3711f719d50590a800504d Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Tue, 1 Dec 2020 20:32:37 +0200 Subject: [PATCH 7/7] fix: newline & clear all line in ExpenseFormEntries. --- .../Accounting/MakeJournalEntriesForm.js | 2 +- .../Expenses/ExpenseFormEntriesField.js | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/client/src/containers/Accounting/MakeJournalEntriesForm.js b/client/src/containers/Accounting/MakeJournalEntriesForm.js index 6a255b78c..bcbfa7354 100644 --- a/client/src/containers/Accounting/MakeJournalEntriesForm.js +++ b/client/src/containers/Accounting/MakeJournalEntriesForm.js @@ -225,7 +225,7 @@ function MakeJournalEntriesForm({ }, [setSubmitPayload], ); - console.log(submitPayload, 'RR'); + return (
@@ -12,10 +14,19 @@ export default function ExpenseFormEntriesField({ entries={value} error={error} onChange={(entries) => { - form.setFieldValue('categories', entries) + form.setFieldValue('categories', entries); + }} + onClickAddNewRow={() => { + form.setFieldValue('categories', [...value, defaultRow]); + }} + onClickClearAllLines={() => { + form.setFieldValue( + 'categories', + orderingLinesIndexes([...repeatValue(defaultRow, linesNumber)]) + ); }} /> )} - ) -} \ No newline at end of file + ); +}