Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ahmed Bouhuolia
2020-10-27 21:07:54 +02:00
20 changed files with 200 additions and 215 deletions

View File

@@ -1,15 +1,16 @@
import React, { useCallback, useMemo } from 'react';
import EstimateListField from 'components/EstimateListField';
import ItemListField from 'components/ItemListField';
import classNames from 'classnames';
import { FormGroup, Classes, Intent } from '@blueprintjs/core';
function EstimatesListFieldCell({
function ItemsListCell({
column: { id },
row: { index },
cell: { value: initialValue },
payload: { products, updateData, errors },
payload: { items, updateData, errors },
}) {
const handleProductSelected = useCallback(
const handleItemSelected = useCallback(
(item) => {
updateData(index, id, item.id);
},
@@ -21,18 +22,15 @@ function EstimatesListFieldCell({
return (
<FormGroup
intent={error ? Intent.DANGER : null}
className={classNames(
'form-group--select-list',
Classes.FILL,
)}
className={classNames('form-group--select-list', Classes.FILL)}
>
<EstimateListField
products={products}
onProductSelected={handleProductSelected}
selectedProductId={initialValue}
<ItemListField
items={items}
onItemSelected={handleItemSelected}
selectedItemId={initialValue}
/>
</FormGroup>
);
}
export default EstimatesListFieldCell;
export default ItemsListCell;

View File

@@ -2,15 +2,15 @@ import AccountsListFieldCell from './AccountsListFieldCell';
import MoneyFieldCell from './MoneyFieldCell';
import InputGroupCell from './InputGroupCell';
import ContactsListFieldCell from './ContactsListFieldCell';
import EstimatesListFieldCell from './EstimatesListFieldCell';
import ItemsListCell from './ItemsListCell';
import PercentFieldCell from './PercentFieldCell';
import { DivFieldCell,EmptyDiv } from './DivFieldCell';
import { DivFieldCell, EmptyDiv } from './DivFieldCell';
export {
AccountsListFieldCell,
MoneyFieldCell,
InputGroupCell,
ContactsListFieldCell,
EstimatesListFieldCell,
ItemsListCell,
PercentFieldCell,
DivFieldCell,
EmptyDiv,

View File

@@ -1,72 +0,0 @@
import React, { useCallback, useMemo, useEffect, useState } from 'react';
import { MenuItem } from '@blueprintjs/core';
import ListSelect from 'components/ListSelect';
function EstimateListField({
products,
initialProductId,
selectedProductId,
defautlSelectText = 'Click to select an item.',
onProductSelected,
}) {
const initialProduct = useMemo(
() => products.find((a) => a.id === initialProductId),
[initialProductId],
);
const [selectedProduct, setSelectedProduct] = useState(
initialProduct || null,
);
useEffect(() => {
if (typeof selectedProductId !== 'undefined') {
const product = selectedProductId
? products.find((a) => a.id === selectedProductId)
: null;
setSelectedProduct(product);
}
}, [selectedProductId, products, setSelectedProduct]);
const onProductSelect = useCallback(
(product) => {
setSelectedProduct({ ...product });
onProductSelected && onProductSelected(product);
},
[onProductSelected],
);
const productRenderer = useCallback(
(item, { handleClick }) => (
<MenuItem key={item.id} text={item.name} onClick={handleClick} />
),
[],
);
const filterProduct = useCallback((query, product, _index, exactMatch) => {
const normalizedTitle = product.name.toLowerCase();
const normalizedQuery = query.toLowerCase();
if (exactMatch) {
return normalizedTitle === normalizedQuery;
} else {
return normalizedTitle.indexOf(normalizedQuery) >= 0;
}
}, []);
return (
<ListSelect
items={products}
noResults={<MenuItem disabled={true} text="No results." />}
itemRenderer={productRenderer}
itemPredicate={filterProduct}
popoverProps={{ minimal: true }}
onItemSelect={onProductSelect}
selectedItem={`${selectedProductId}`}
selectedItemProp={'id'}
labelProp={'name'}
defaultText={selectedProduct ? selectedProduct.name : defautlSelectText}
/>
);
}
export default EstimateListField;

View File

@@ -0,0 +1,69 @@
import React, { useCallback, useMemo, useEffect, useState } from 'react';
import { MenuItem } from '@blueprintjs/core';
import ListSelect from 'components/ListSelect';
function ItemListField({
items,
initialItemId,
selectedItemId,
defautlSelectText = 'Click to select an item.',
onItemSelected,
}) {
const initialItem = useMemo(() => items.find((a) => a.id === initialItemId), [
initialItemId,
]);
const [selectedItem, setSelectedItem] = useState(initialItem || null);
useEffect(() => {
if (typeof selectedItemId !== 'undefined') {
const item = selectedItemId
? items.find((a) => a.id === selectedItemId)
: null;
setSelectedItem(item);
}
}, [selectedItemId, items, setSelectedItem]);
const onItemSelect = useCallback(
(item) => {
setSelectedItem({ ...item });
onItemSelected && onItemSelected(item);
},
[onItemSelected],
);
const itemRenderer = useCallback(
(item, { handleClick }) => (
<MenuItem key={item.id} text={item.name} onClick={handleClick} />
),
[],
);
const filterItem = useCallback((query, item, _index, exactMatch) => {
const normalizedTitle = item.name.toLowerCase();
const normalizedQuery = query.toLowerCase();
if (exactMatch) {
return normalizedTitle === normalizedQuery;
} else {
return normalizedTitle.indexOf(normalizedQuery) >= 0;
}
}, []);
return (
<ListSelect
items={items}
noResults={<MenuItem disabled={true} text="No results." />}
itemRenderer={itemRenderer}
itemPredicate={filterItem}
popoverProps={{ minimal: true }}
onItemSelect={onItemSelect}
selectedItem={`${selectedItemId}`}
selectedItemProp={'id'}
labelProp={'name'}
defaultText={selectedItem ? selectedItem.name : defautlSelectText}
/>
);
}
export default ItemListField;

View File

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

View File

@@ -8,24 +8,21 @@ import React, {
import * as Yup from 'yup';
import { useFormik } from 'formik';
import moment from 'moment';
import { Intent, FormGroup, TextArea } from '@blueprintjs/core';
import { Intent } from '@blueprintjs/core';
import classNames from 'classnames';
import { FormattedMessage as T, useIntl } from 'react-intl';
import { pick } from 'lodash';
import { CLASSES } from 'common/classes';
import BillFormHeader from './BillFormHeader';
import EstimatesItemsTable from 'containers/Sales/Estimate/EntriesItemsTable';
import BillFloatingActions from './BillFloatingActions';
import BillFormFooter from './BillFormFooter';
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
import withMediaActions from 'containers/Media/withMediaActions';
import withBills from './withBills';
import withBillActions from './withBillActions';
import withBillDetail from './withBillDetail';
import withSettings from 'containers/Settings/withSettings';
import { AppToaster, Row, Col } from 'components';
import Dragzone from 'components/Dragzone';
import { AppToaster } from 'components';
import useMedia from 'hooks/useMedia';
import { compose, repeatValue } from 'utils';
@@ -45,13 +42,6 @@ function BillForm({
//#withDashboard
changePageTitle,
// #withBills
nextBillNumberChanged,
// #withSettings
billNextNumber,
billNumberPrefix,
//#withBillDetail
bill,
@@ -147,14 +137,11 @@ function BillForm({
[],
);
const billNumber = billNumberPrefix
? `${billNumberPrefix}-${billNextNumber}`
: billNextNumber;
const defaultInitialValues = useMemo(
() => ({
vendor_id: '',
bill_number: billNumber,
bill_number: '',
bill_date: moment(new Date()).format('YYYY-MM-DD'),
due_date: moment(new Date()).format('YYYY-MM-DD'),
// status: 'Bill',
@@ -162,7 +149,7 @@ function BillForm({
note: '',
entries: [...repeatValue(defaultBill, MIN_LINES_NUMBER)],
}),
[defaultBill, billNumber],
[defaultBill],
);
const orderingIndex = (_bill) => {
@@ -259,11 +246,6 @@ function BillForm({
},
});
useEffect(() => {
formik.setFieldValue('bill_number', billNumber);
setBillNumberChanged(false);
}, [nextBillNumberChanged, billNumber]);
const handleSubmitClick = useCallback(
(payload) => {
setPayload(payload);
@@ -290,7 +272,7 @@ function BillForm({
},
[setDeletedFiles, deletedFiles],
);
const onClickCleanAllLines = () => {
formik.setFieldValue(
'entries',
@@ -305,10 +287,7 @@ function BillForm({
);
};
return (
<div className={classNames(
CLASSES.PAGE_FORM,
CLASSES.PAGE_FORM_BILL,
)}>
<div className={classNames(CLASSES.PAGE_FORM, CLASSES.PAGE_FORM_BILL)}>
<form onSubmit={formik.handleSubmit}>
<BillFormHeader formik={formik} />
@@ -318,33 +297,16 @@ function BillForm({
onClickAddNewRow={onClickAddNewRow}
onClickClearAllLines={onClickCleanAllLines}
/>
<div class="page-form__footer">
<Row>
<Col md={8}>
<FormGroup label={<T id={'note'} />} className={'form-group--note'}>
<TextArea
growVertically={true}
{...formik.getFieldProps('note')}
/>
</FormGroup>
</Col>
<Col md={4}>
<Dragzone
initialFiles={initialAttachmentFiles}
onDrop={handleDropFiles}
onDeleteFile={handleDeleteFile}
hint={'Attachments: Maxiumum size: 20MB'}
/>
</Col>
</Row>
</div>
<BillFormFooter
formik={formik}
oninitialFiles={initialAttachmentFiles}
onDropFiles={handleDeleteFile}
/>
</form>
<BillFormFooter
<BillFloatingActions
formik={formik}
onSubmitClick={handleSubmitClick}
bill={bill}
disabled={formik.isSubmitting}
onCancelClick={handleCancelClick}
/>
</div>
@@ -354,11 +316,6 @@ function BillForm({
export default compose(
withBillActions,
withBillDetail(),
withBills(({ nextBillNumberChanged }) => ({ nextBillNumberChanged })),
withDashboardActions,
withMediaActions,
withSettings(({ billsettings }) => ({
billNextNumber: billsettings?.next_number,
billNumberPrefix: billsettings?.number_prefix,
})),
)(BillForm);

View File

@@ -1,54 +1,32 @@
import React from 'react';
import { Intent, Button } from '@blueprintjs/core';
import { FormGroup, TextArea } from '@blueprintjs/core';
import { FormattedMessage as T } from 'react-intl';
import { Row, Col } from 'components';
import Dragzone from 'components/Dragzone';
export default function BillFormFooter({
formik: { isSubmitting },
onSubmitClick,
onCancelClick,
bill,
export default function BillFloatingActions({
formik: { getFieldProps },
oninitialFiles,
onDropFiles,
}) {
return (
<div className={'form__floating-footer'}>
<Button
disabled={isSubmitting}
loading={isSubmitting}
intent={Intent.PRIMARY}
type="submit"
onClick={() => {
onSubmitClick({ redirect: true });
}}
>
{bill && bill.id ? <T id={'edit'} /> : <T id={'save_send'} />}
</Button>
<div class="page-form__footer">
<Row>
<Col md={8}>
<FormGroup label={<T id={'note'} />} className={'form-group--note'}>
<TextArea growVertically={true} {...getFieldProps('note')} />
</FormGroup>
</Col>
<Button
disabled={isSubmitting}
loading={isSubmitting}
intent={Intent.PRIMARY}
className={'ml1'}
name={'save'}
type="submit"
onClick={() => {
onSubmitClick({ redirect: false });
}}
>
<T id={'save'} />
</Button>
<Button className={'ml1'} disabled={isSubmitting}>
<T id={'clear'} />
</Button>
<Button
className={'ml1'}
type="submit"
onClick={() => {
onCancelClick && onCancelClick();
}}
>
<T id={'close'} />
</Button>
<Col md={4}>
<Dragzone
initialFiles={oninitialFiles}
onDrop={onDropFiles}
onDeleteFile={onDropFiles}
hint={'Attachments: Maxiumum size: 20MB'}
/>
</Col>
</Row>
</div>
);
}

View File

@@ -16,7 +16,7 @@ import { pick, values } from 'lodash';
import PaymentMadeHeader from './PaymentMadeFormHeader';
import PaymentMadeItemsTable from './PaymentMadeItemsTable';
import PaymentMadeFooter from './PaymentMadeFormFooter';
import PaymentMadeFloatingActions from './PaymentMadeFloatingActions';
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
import withMediaActions from 'containers/Media/withMediaActions';
@@ -319,7 +319,7 @@ function PaymentMadeForm({
hint={'Attachments: Maxiumum size: 20MB'}
/> */}
</form>
<PaymentMadeFooter
<PaymentMadeFloatingActions
formik={formik}
onSubmitClick={handleSubmitClick}
onCancel={handleCancelClick}

View File

@@ -10,7 +10,7 @@ import DataTable from 'components/DataTable';
import {
InputGroupCell,
MoneyFieldCell,
EstimatesListFieldCell,
ItemsListCell,
PercentFieldCell,
DivFieldCell,
} from 'components/DataTableCells';
@@ -76,7 +76,7 @@ const ItemHeaderCell = () => {
);
};
function EstimateTable({
function EntriesItemsTable({
//#withitems
itemsCurrentPage,
@@ -109,7 +109,8 @@ function EstimateTable({
Header: ItemHeaderCell,
id: 'item_id',
accessor: 'item_id',
Cell: EstimatesListFieldCell,
Cell: ItemsListCell,
// ItemsListCell
disableSortBy: true,
width: 180,
},
@@ -239,7 +240,7 @@ function EstimateTable({
data={rows}
rowClassNames={rowClassNames}
payload={{
products: itemsCurrentPage,
items: itemsCurrentPage,
errors: errors.entries || [],
updateData: handleUpdateData,
removeRow: handleRemoveRow,
@@ -270,4 +271,4 @@ export default compose(
withItems(({ itemsCurrentPage }) => ({
itemsCurrentPage,
})),
)(EstimateTable);
)(EntriesItemsTable);

View File

@@ -3,7 +3,7 @@ import { Intent, Button } from '@blueprintjs/core';
import { FormattedMessage as T } from 'react-intl';
import { queryCache } from 'react-query';
export default function EstimateFormFooter({
export default function EstimateFloatingActions({
formik: { isSubmitting, resetForm },
onSubmitClick,
onCancelClick,

View File

@@ -15,8 +15,8 @@ import classNames from 'classnames';
import { CLASSES } from 'common/classes';
import EstimateFormHeader from './EstimateFormHeader';
import EstimatesItemsTable from './EntriesItemsTable';
import EstimateFormFooter from './EstimateFormFooter';
import EntriesItemsTable from './EntriesItemsTable';
import EstimateFloatingActions from './EstimateFloatingActions';
import withEstimateActions from './withEstimateActions';
import withEstimateDetail from './withEstimateDetail';
@@ -308,7 +308,7 @@ const EstimateForm = ({
)}>
<form onSubmit={formik.handleSubmit}>
<EstimateFormHeader formik={formik} />
<EstimatesItemsTable
<EntriesItemsTable
entries={formik.values.entries}
onClickAddNewRow={handleClickAddNewRow}
onClickClearAllLines={handleClearAllLines}
@@ -350,7 +350,7 @@ const EstimateForm = ({
</Row>
</div>
</form>
<EstimateFormFooter
<EstimateFloatingActions
formik={formik}
onSubmitClick={handleSubmitClick}
estimate={estimate}

View File

@@ -2,7 +2,7 @@ import React from 'react';
import { Intent, Button } from '@blueprintjs/core';
import { FormattedMessage as T } from 'react-intl';
export default function EstimateFormFooter({
export default function InvoiceFloatingActions({
formik: { isSubmitting },
onSubmitClick,
onCancelClick,

View File

@@ -15,8 +15,8 @@ import classNames from 'classnames';
import { CLASSES } from 'common/classes';
import InvoiceFormHeader from './InvoiceFormHeader';
import EstimatesItemsTable from 'containers/Sales/Estimate/EntriesItemsTable';
import InvoiceFormFooter from './InvoiceFormFooter';
import EntriesItemsTable from 'containers/Sales/Estimate/EntriesItemsTable';
import InvoiceFloatingActions from './InvoiceFloatingActions';
import withInvoiceActions from './withInvoiceActions';
import withInvoiceDetail from './withInvoiceDetail';
@@ -311,7 +311,7 @@ function InvoiceForm({
<div className={classNames(CLASSES.PAGE_FORM, CLASSES.PAGE_FORM_INVOICE)}>
<form onSubmit={formik.handleSubmit}>
<InvoiceFormHeader formik={formik} />
<EstimatesItemsTable
<EntriesItemsTable
entries={formik.values.entries}
onClickAddNewRow={handleClickAddNewRow}
onClickClearAllLines={handleClearAllLines}
@@ -356,7 +356,7 @@ function InvoiceForm({
</div>
</form>
<InvoiceFormFooter
<InvoiceFloatingActions
formik={formik}
onSubmitClick={handleSubmitClick}
invoice={invoice}

View File

@@ -16,7 +16,7 @@ import { pick, values } from 'lodash';
import PaymentReceiveHeader from './PaymentReceiveFormHeader';
import PaymentReceiveItemsTable from './PaymentReceiveItemsTable';
import PaymentReceiveFooter from './PaymentReceiveFormFooter';
import PaymentReceiveFloatingActions from './PaymentReceiveFloatingActions';
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
import withMediaActions from 'containers/Media/withMediaActions';
@@ -320,7 +320,7 @@ function PaymentReceiveForm({
/> */}
</form>
<PaymentReceiveFooter
<PaymentReceiveFloatingActions
formik={formik}
onSubmitClick={handleSubmitClick}
paymentReceive={paymentReceive}

View File

@@ -10,7 +10,7 @@ import { compose, formattedAmount, transformUpdatedRows } from 'utils';
import {
InputGroupCell,
MoneyFieldCell,
EstimatesListFieldCell,
ItemsListCell,
DivFieldCell,
EmptyDiv,
} from 'components/DataTableCells';

View File

@@ -17,8 +17,8 @@ import classNames from 'classnames';
import { CLASSES } from 'common/classes';
import ReceiptFromHeader from './ReceiptFormHeader';
import EstimatesItemsTable from 'containers/Sales/Estimate/EntriesItemsTable';
import ReceiptFormFooter from './ReceiptFormFooter';
import EntriesItemsTable from 'containers/Sales/Estimate/EntriesItemsTable';
import ReceiptReceiveFloatingActions from './ReceiptReceiveFloatingActions';
import withReceiptActions from './withReceiptActions';
import withReceiptDetail from './withReceiptDetail';
@@ -311,7 +311,7 @@ function ReceiptForm({
<form onSubmit={formik.handleSubmit}>
<ReceiptFromHeader formik={formik} />
<EstimatesItemsTable
<EntriesItemsTable
entries={formik.values.entries}
onClickAddNewRow={handleClickAddNewRow}
onClickClearAllLines={handleClearAllLines}
@@ -353,7 +353,7 @@ function ReceiptForm({
</Row>
</div>
</form>
<ReceiptFormFooter
<ReceiptReceiveFloatingActions
formik={formik}
onSubmitClick={handleSubmitClick}
receipt={receipt}

View File

@@ -2,7 +2,7 @@ import React from 'react';
import { Intent, Button } from '@blueprintjs/core';
import { FormattedMessage as T } from 'react-intl';
export default function ReceiptFormFooter({
export default function ReceiptReceiveFloatingActions({
formik: { isSubmitting },
onSubmitClick,
onCancelClick,

View File

@@ -668,7 +668,7 @@ export default {
the_bill_has_been_successfully_edited:
'The bill #{number} has been successfully edited.',
the_bill_has_been_successfully_created:
'The bill has been successfully created.',
'The bill #{number} has been successfully created.',
the_bill_has_been_successfully_deleted:
'The bill has been successfully deleted.',
once_delete_this_bill_you_will_able_to_restore_it: `Once you delete this bill, you won\'t be able to restore it later. Are you sure you want to delete this bill?`,