mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-21 23:30:32 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -1,41 +1,46 @@
|
|||||||
import React, { useCallback, useState, useEffect, useMemo } from 'react';
|
import React, { useCallback, useState, useEffect, useMemo } from 'react';
|
||||||
import { FormattedMessage as T } from 'react-intl';
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
import { ListSelect } from 'components';
|
import { MenuItem, Button } from '@blueprintjs/core';
|
||||||
import { MenuItem } from '@blueprintjs/core';
|
import { Select } from '@blueprintjs/select';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { CLASSES } from 'common/classes';
|
import { CLASSES } from 'common/classes';
|
||||||
|
|
||||||
export default function ContactSelecetList({
|
export default function ContactSelecetList({
|
||||||
contactsList,
|
contactsList,
|
||||||
|
initialContactId,
|
||||||
selectedContactId,
|
selectedContactId,
|
||||||
|
selectedContactType,
|
||||||
defaultSelectText = <T id={'select_contact'} />,
|
defaultSelectText = <T id={'select_contact'} />,
|
||||||
onContactSelected,
|
onContactSelected,
|
||||||
popoverFill = false,
|
popoverFill = false,
|
||||||
...restProps
|
disabled = false,
|
||||||
}) {
|
}) {
|
||||||
const [selecetedContact, setSelectedContact] = useState(null);
|
const contacts = useMemo(
|
||||||
|
() =>
|
||||||
// Filter Contact List
|
contactsList.map((contact) => ({
|
||||||
const FilterContacts = (query, contact, index, exactMatch) => {
|
...contact,
|
||||||
const normalizedTitle = contact.display_name.toLowerCase();
|
_id: `${contact.id}_${contact.contact_type}`,
|
||||||
const normalizedQuery = query.toLowerCase();
|
})),
|
||||||
if (exactMatch) {
|
[contactsList],
|
||||||
return normalizedTitle === normalizedQuery;
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
`${contact.display_name} ${normalizedTitle}`.indexOf(normalizedQuery) >=
|
|
||||||
0
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const initialContact = useMemo(
|
||||||
|
() => contacts.find((a) => a.id === initialContactId),
|
||||||
|
[initialContactId, contacts],
|
||||||
|
);
|
||||||
|
|
||||||
|
const [selecetedContact, setSelectedContact] = useState(
|
||||||
|
initialContact || null,
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof selectedContactId !== 'undefined') {
|
||||||
|
const account = selectedContactId
|
||||||
|
? contacts.find((a) => a.id === selectedContactId)
|
||||||
|
: null;
|
||||||
|
setSelectedContact(account);
|
||||||
}
|
}
|
||||||
};
|
}, [selectedContactId, contacts, setSelectedContact]);
|
||||||
|
|
||||||
const onContactSelect = useCallback(
|
|
||||||
(contact) => {
|
|
||||||
setSelectedContact({ ...contact });
|
|
||||||
onContactSelected && onContactSelected(contact);
|
|
||||||
},
|
|
||||||
[setSelectedContact, onContactSelected],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleContactRenderer = useCallback(
|
const handleContactRenderer = useCallback(
|
||||||
(contact, { handleClick }) => (
|
(contact, { handleClick }) => (
|
||||||
@@ -48,21 +53,48 @@ export default function ContactSelecetList({
|
|||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const onContactSelect = useCallback(
|
||||||
|
(contact) => {
|
||||||
|
setSelectedContact({ ...contact });
|
||||||
|
onContactSelected && onContactSelected(contact);
|
||||||
|
},
|
||||||
|
[setSelectedContact, onContactSelected],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Filter Contact List
|
||||||
|
const filterContacts = (query, contact, index, exactMatch) => {
|
||||||
|
const normalizedTitle = contact.display_name.toLowerCase();
|
||||||
|
const normalizedQuery = query.toLowerCase();
|
||||||
|
if (exactMatch) {
|
||||||
|
return normalizedTitle === normalizedQuery;
|
||||||
|
} else {
|
||||||
return (
|
return (
|
||||||
<ListSelect
|
`${contact.display_name} ${normalizedTitle}`.indexOf(normalizedQuery) >=
|
||||||
items={contactsList}
|
0
|
||||||
selectedItemProp={'id'}
|
);
|
||||||
selectedItem={selectedContactId}
|
}
|
||||||
labelProp={'display_name'}
|
};
|
||||||
defaultText={defaultSelectText}
|
|
||||||
onItemSelect={onContactSelect}
|
return (
|
||||||
itemPredicate={FilterContacts}
|
<Select
|
||||||
|
items={contacts}
|
||||||
|
noResults={<MenuItem disabled={true} text="No results." />}
|
||||||
itemRenderer={handleContactRenderer}
|
itemRenderer={handleContactRenderer}
|
||||||
|
itemPredicate={filterContacts}
|
||||||
|
filterable={true}
|
||||||
|
disabled={disabled}
|
||||||
|
onItemSelect={onContactSelect}
|
||||||
popoverProps={{ minimal: true, usePortal: !popoverFill }}
|
popoverProps={{ minimal: true, usePortal: !popoverFill }}
|
||||||
className={classNames(CLASSES.FORM_GROUP_LIST_SELECT, {
|
className={classNames(CLASSES.FORM_GROUP_LIST_SELECT, {
|
||||||
[CLASSES.SELECT_LIST_FILL_POPOVER]: popoverFill,
|
[CLASSES.SELECT_LIST_FILL_POPOVER]: popoverFill,
|
||||||
})}
|
})}
|
||||||
{...restProps}
|
>
|
||||||
|
<Button
|
||||||
|
disabled={disabled}
|
||||||
|
text={
|
||||||
|
selecetedContact ? selecetedContact.display_name : defaultSelectText
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
</Select>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
import React, { useCallback, useMemo } from 'react';
|
|
||||||
import { MenuItem } from '@blueprintjs/core';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { CLASSES } from 'common/classes';
|
|
||||||
import ListSelect from 'components/ListSelect';
|
|
||||||
import { FormattedMessage as T } from 'react-intl';
|
|
||||||
|
|
||||||
export default function ContactsListField({
|
|
||||||
contacts,
|
|
||||||
onContactSelected,
|
|
||||||
selectedContactId,
|
|
||||||
selectedContactType,
|
|
||||||
defautlSelectText = <T id={'select_contact'} />,
|
|
||||||
popoverFill = false,
|
|
||||||
}) {
|
|
||||||
// Contact item of select accounts field.
|
|
||||||
const contactRenderer = useCallback(
|
|
||||||
(item, { handleClick, modifiers, query }) => (
|
|
||||||
<MenuItem text={item.display_name} key={item.id} onClick={handleClick} />
|
|
||||||
),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const onContactSelect = useCallback(
|
|
||||||
(contact) => {
|
|
||||||
onContactSelected && onContactSelected(contact);
|
|
||||||
},
|
|
||||||
[onContactSelected],
|
|
||||||
);
|
|
||||||
|
|
||||||
const items = useMemo(
|
|
||||||
() =>
|
|
||||||
contacts.map((contact) => ({
|
|
||||||
...contact,
|
|
||||||
_id: `${contact.id}_${contact.contact_type}`,
|
|
||||||
})),
|
|
||||||
[contacts],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ListSelect
|
|
||||||
items={items}
|
|
||||||
noResults={<MenuItem disabled={true} text="No results." />}
|
|
||||||
itemRenderer={contactRenderer}
|
|
||||||
filterable={true}
|
|
||||||
onItemSelect={onContactSelect}
|
|
||||||
labelProp={'display_name'}
|
|
||||||
selectedItem={`${selectedContactId}_${selectedContactType}`}
|
|
||||||
selectedItemProp={'_id'}
|
|
||||||
defaultText={defautlSelectText}
|
|
||||||
popoverProps={{ minimal: true, usePortal: !popoverFill }}
|
|
||||||
className={classNames(CLASSES.FORM_GROUP_LIST_SELECT, {
|
|
||||||
[CLASSES.SELECT_LIST_FILL_POPOVER]: popoverFill,
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,17 @@
|
|||||||
import React, { useCallback, useState } from 'react';
|
import React, { useCallback, useState } from 'react';
|
||||||
import { FormattedMessage as T } from 'react-intl';
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
|
import { CLASSES } from 'common/classes';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { ListSelect } from 'components';
|
import { MenuItem, Button } from '@blueprintjs/core';
|
||||||
import { MenuItem } from '@blueprintjs/core';
|
import { Select } from '@blueprintjs/select';
|
||||||
|
|
||||||
export default function CurrencySelectList({
|
export default function CurrencySelectList({
|
||||||
currenciesList,
|
currenciesList,
|
||||||
selectedCurrencyCode,
|
selectedCurrencyCode,
|
||||||
defaultSelectText = <T id={'select_currency_code'} />,
|
defaultSelectText = <T id={'select_currency_code'} />,
|
||||||
onCurrencySelected,
|
onCurrencySelected,
|
||||||
className,
|
popoverFill = false,
|
||||||
...restProps
|
disabled = false,
|
||||||
}) {
|
}) {
|
||||||
const [selectedCurrency, setSelectedCurrency] = useState(null);
|
const [selectedCurrency, setSelectedCurrency] = useState(null);
|
||||||
|
|
||||||
@@ -45,19 +46,37 @@ export default function CurrencySelectList({
|
|||||||
);
|
);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof selectedCurrencyCode !== 'undefined') {
|
||||||
|
const currency = selectedCurrencyCode
|
||||||
|
? currenciesList.find((a) => a.currency_code === selectedCurrencyCode)
|
||||||
|
: null;
|
||||||
|
setSelectedCurrency(currency);
|
||||||
|
}
|
||||||
|
}, [selectedCurrencyCode, currenciesList, setSelectedCurrency]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ListSelect
|
<Select
|
||||||
items={currenciesList}
|
items={currenciesList}
|
||||||
selectedItemProp={'currency_code'}
|
|
||||||
selectedItem={selectedCurrencyCode}
|
|
||||||
labelProp={'currency_code'}
|
|
||||||
defaultText={defaultSelectText}
|
|
||||||
onItemSelect={onCurrencySelect}
|
|
||||||
itemPredicate={filterCurrencies}
|
|
||||||
itemRenderer={currencyCodeRenderer}
|
itemRenderer={currencyCodeRenderer}
|
||||||
popoverProps={{ minimal: true }}
|
itemPredicate={filterCurrencies}
|
||||||
className={classNames('form-group--select-list', className)}
|
onItemSelect={onCurrencySelect}
|
||||||
{...restProps}
|
filterable={true}
|
||||||
|
popoverProps={{
|
||||||
|
minimal: true,
|
||||||
|
usePortal: !popoverFill,
|
||||||
|
inline: popoverFill,
|
||||||
|
}}
|
||||||
|
className={classNames('form-group--select-list', {
|
||||||
|
[CLASSES.SELECT_LIST_FILL_POPOVER]: popoverFill,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
disabled={disabled}
|
||||||
|
text={
|
||||||
|
selectedCurrency ? selectedCurrency.currency_code : defaultSelectText
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
</Select>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,23 @@
|
|||||||
import React, { useState, useCallback, useMemo } from 'react';
|
import React, { useState, useCallback, useMemo } from 'react';
|
||||||
import { FormGroup, Intent, Classes } from "@blueprintjs/core";
|
import { FormGroup, Intent, Classes } from '@blueprintjs/core';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import ContactsListField from 'components/ContactsListField';
|
import { ContactSelecetList } from 'components';
|
||||||
|
|
||||||
export default function ContactsListCellRenderer({
|
export default function ContactsListCellRenderer({
|
||||||
column: { id },
|
column: { id },
|
||||||
row: { index, original },
|
row: { index, original },
|
||||||
cell: { value },
|
cell: { value },
|
||||||
payload: { contacts, updateData, errors }
|
payload: { contacts, updateData, errors },
|
||||||
}) {
|
}) {
|
||||||
const handleContactSelected = useCallback((contact) => {
|
const handleContactSelected = useCallback(
|
||||||
|
(contact) => {
|
||||||
updateData(index, {
|
updateData(index, {
|
||||||
contact_id: contact.id,
|
contact_id: contact.id,
|
||||||
contact_type: contact.contact_type,
|
contact_type: contact.contact_type,
|
||||||
});
|
});
|
||||||
}, [updateData, index, id]);
|
},
|
||||||
|
[updateData, index, id],
|
||||||
|
);
|
||||||
|
|
||||||
const error = errors?.[index]?.[id];
|
const error = errors?.[index]?.[id];
|
||||||
|
|
||||||
@@ -27,8 +30,8 @@ export default function ContactsListCellRenderer({
|
|||||||
Classes.FILL,
|
Classes.FILL,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<ContactsListField
|
<ContactSelecetList
|
||||||
contacts={contacts}
|
contactsList={contacts}
|
||||||
onContactSelected={handleContactSelected}
|
onContactSelected={handleContactSelected}
|
||||||
selectedContactId={original?.contact_id}
|
selectedContactId={original?.contact_id}
|
||||||
selectedContactType={original?.contact_type}
|
selectedContactType={original?.contact_type}
|
||||||
|
|||||||
199
client/src/containers/Accounting/MakeJournalEntriesFooter.js
Normal file
199
client/src/containers/Accounting/MakeJournalEntriesFooter.js
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
Intent,
|
||||||
|
Button,
|
||||||
|
ButtonGroup,
|
||||||
|
Popover,
|
||||||
|
PopoverInteractionKind,
|
||||||
|
Position,
|
||||||
|
Menu,
|
||||||
|
MenuItem,
|
||||||
|
} from '@blueprintjs/core';
|
||||||
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
|
import { CLASSES } from 'common/classes';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { saveInvoke } from 'utils';
|
||||||
|
import { If, Icon } from 'components';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make Journal floating actions bar.
|
||||||
|
*/
|
||||||
|
export default function MakeJournalEntriesFooter({
|
||||||
|
isSubmitting,
|
||||||
|
onSubmitClick,
|
||||||
|
onCancelClick,
|
||||||
|
manualJournalId,
|
||||||
|
onSubmitForm,
|
||||||
|
onResetForm,
|
||||||
|
manualJournalPublished,
|
||||||
|
}) {
|
||||||
|
const handleSubmitPublishBtnClick = (event) => {
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: true,
|
||||||
|
publish: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitPublishAndNewBtnClick = (event) => {
|
||||||
|
onSubmitForm();
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: false,
|
||||||
|
publish: true,
|
||||||
|
resetForm: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitPublishContinueEditingBtnClick = (event) => {
|
||||||
|
onSubmitForm();
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: false,
|
||||||
|
publish: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitDraftBtnClick = (event) => {
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: true,
|
||||||
|
publish: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitDraftAndNewBtnClick = (event) => {
|
||||||
|
onSubmitForm();
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: false,
|
||||||
|
publish: false,
|
||||||
|
resetForm: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitDraftContinueEditingBtnClick = (event) => {
|
||||||
|
onSubmitForm();
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: false,
|
||||||
|
publish: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancelBtnClick = (event) => {
|
||||||
|
saveInvoke(onCancelClick, event);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClearBtnClick = (event) => {
|
||||||
|
// saveInvoke(onClearClick, event);
|
||||||
|
onResetForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
||||||
|
{/* ----------- Save And Publish ----------- */}
|
||||||
|
<If condition={!manualJournalId || !manualJournalPublished}>
|
||||||
|
<ButtonGroup>
|
||||||
|
<Button
|
||||||
|
disabled={isSubmitting}
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
type="submit"
|
||||||
|
onClick={handleSubmitPublishBtnClick}
|
||||||
|
text={<T id={'save_publish'} />}
|
||||||
|
/>
|
||||||
|
<Popover
|
||||||
|
content={
|
||||||
|
<Menu>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'publish_and_new'} />}
|
||||||
|
onClick={handleSubmitPublishAndNewBtnClick}
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'publish_continue_editing'} />}
|
||||||
|
onClick={handleSubmitPublishContinueEditingBtnClick}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
}
|
||||||
|
minimal={true}
|
||||||
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
|
position={Position.BOTTOM_LEFT}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
|
{/* ----------- Save As Draft ----------- */}
|
||||||
|
<ButtonGroup>
|
||||||
|
<Button
|
||||||
|
disabled={isSubmitting}
|
||||||
|
className={'ml1'}
|
||||||
|
type="submit"
|
||||||
|
onClick={handleSubmitDraftBtnClick}
|
||||||
|
text={<T id={'save_as_draft'} />}
|
||||||
|
/>
|
||||||
|
<Popover
|
||||||
|
content={
|
||||||
|
<Menu>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'save_and_new'} />}
|
||||||
|
onClick={handleSubmitDraftAndNewBtnClick}
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'save_continue_editing'} />}
|
||||||
|
onClick={handleSubmitDraftContinueEditingBtnClick}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
}
|
||||||
|
minimal={true}
|
||||||
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
|
position={Position.BOTTOM_LEFT}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
|
</If>
|
||||||
|
{/* ----------- Save and New ----------- */}
|
||||||
|
<If condition={manualJournalId && manualJournalPublished}>
|
||||||
|
<ButtonGroup>
|
||||||
|
<Button
|
||||||
|
disabled={isSubmitting}
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
type="submit"
|
||||||
|
onClick={handleSubmitPublishBtnClick}
|
||||||
|
text={<T id={'save'} />}
|
||||||
|
/>
|
||||||
|
<Popover
|
||||||
|
content={
|
||||||
|
<Menu>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'save_and_new'} />}
|
||||||
|
onClick={handleSubmitPublishAndNewBtnClick}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
}
|
||||||
|
minimal={true}
|
||||||
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
|
position={Position.BOTTOM_LEFT}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
|
</If>
|
||||||
|
{/* ----------- Clear & Reset----------- */}
|
||||||
|
<Button
|
||||||
|
className={'ml1'}
|
||||||
|
disabled={isSubmitting}
|
||||||
|
onClick={handleClearBtnClick}
|
||||||
|
text={manualJournalId ? <T id={'reset'} /> : <T id={'clear'} />}
|
||||||
|
/>
|
||||||
|
{/* ----------- Cancel ----------- */}
|
||||||
|
<Button
|
||||||
|
className={'ml1'}
|
||||||
|
onClick={handleCancelBtnClick}
|
||||||
|
text={<T id={'cancel'} />}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -17,6 +17,11 @@ import MakeJournalEntriesField from './MakeJournalEntriesField';
|
|||||||
import MakeJournalNumberWatcher from './MakeJournalNumberWatcher';
|
import MakeJournalNumberWatcher from './MakeJournalNumberWatcher';
|
||||||
import MakeJournalFormFooter from './MakeJournalFormFooter';
|
import MakeJournalFormFooter from './MakeJournalFormFooter';
|
||||||
|
|
||||||
|
import {
|
||||||
|
CreateMakeJournalFormSchema,
|
||||||
|
EditMakeJournalFormSchema,
|
||||||
|
} from './MakeJournalEntriesForm.schema';
|
||||||
|
|
||||||
import withJournalsActions from 'containers/Accounting/withJournalsActions';
|
import withJournalsActions from 'containers/Accounting/withJournalsActions';
|
||||||
import withManualJournalDetail from 'containers/Accounting/withManualJournalDetail';
|
import withManualJournalDetail from 'containers/Accounting/withManualJournalDetail';
|
||||||
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
||||||
@@ -83,8 +88,8 @@ function MakeJournalEntriesForm({
|
|||||||
onFormSubmit,
|
onFormSubmit,
|
||||||
onCancelForm,
|
onCancelForm,
|
||||||
}) {
|
}) {
|
||||||
|
const isNewMode = !manualJournalId;
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const isNewMode = manualJournalId;
|
|
||||||
|
|
||||||
const journalNumber = isNewMode
|
const journalNumber = isNewMode
|
||||||
? `${journalNumberPrefix}-${journalNextNumber}`
|
? `${journalNumberPrefix}-${journalNextNumber}`
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { DATATYPES_LENGTH } from 'common/dataTypes';
|
|||||||
|
|
||||||
const Schema = Yup.object().shape({
|
const Schema = Yup.object().shape({
|
||||||
journal_number: Yup.string()
|
journal_number: Yup.string()
|
||||||
.required()
|
// .required()
|
||||||
.min(1)
|
.min(1)
|
||||||
.max(DATATYPES_LENGTH.STRING)
|
.max(DATATYPES_LENGTH.STRING)
|
||||||
.label(formatMessage({ id: 'journal_number_' })),
|
.label(formatMessage({ id: 'journal_number_' })),
|
||||||
@@ -17,8 +17,9 @@ const Schema = Yup.object().shape({
|
|||||||
.required()
|
.required()
|
||||||
.label(formatMessage({ id: 'date' })),
|
.label(formatMessage({ id: 'date' })),
|
||||||
currency_code: Yup.string().max(3),
|
currency_code: Yup.string().max(3),
|
||||||
reference: Yup.string().min(1).max(DATATYPES_LENGTH.STRING),
|
reference: Yup.string().nullable().min(1).max(DATATYPES_LENGTH.STRING),
|
||||||
description: Yup.string().min(1).max(DATATYPES_LENGTH.STRING),
|
description: Yup.string().min(1).max(DATATYPES_LENGTH.STRING),
|
||||||
|
status: Yup.boolean(),
|
||||||
entries: Yup.array().of(
|
entries: Yup.array().of(
|
||||||
Yup.object().shape({
|
Yup.object().shape({
|
||||||
credit: Yup.number().decimalScale(13).nullable(),
|
credit: Yup.number().decimalScale(13).nullable(),
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default function ManualJournalsEmptyStatus() {
|
|||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
large={true}
|
large={true}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
history.push('/invoices/new');
|
history.push('/make-journal-entry');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Make journal
|
Make journal
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import classNames from 'classnames';
|
|||||||
import { FormGroup, Position, Classes, ControlGroup } from '@blueprintjs/core';
|
import { FormGroup, Position, Classes, ControlGroup } from '@blueprintjs/core';
|
||||||
import { DateInput } from '@blueprintjs/datetime';
|
import { DateInput } from '@blueprintjs/datetime';
|
||||||
import { FastField, ErrorMessage } from 'formik';
|
import { FastField, ErrorMessage } from 'formik';
|
||||||
|
import moment from 'moment';
|
||||||
import {
|
import {
|
||||||
MoneyInputGroup,
|
MoneyInputGroup,
|
||||||
InputPrependText,
|
InputPrependText,
|
||||||
@@ -27,7 +28,6 @@ function CustomerFinancialPanel({
|
|||||||
|
|
||||||
customerId,
|
customerId,
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'tab-panel--financial'}>
|
<div className={'tab-panel--financial'}>
|
||||||
<Row>
|
<Row>
|
||||||
@@ -44,6 +44,12 @@ function CustomerFinancialPanel({
|
|||||||
>
|
>
|
||||||
<DateInput
|
<DateInput
|
||||||
{...momentFormatter('YYYY/MM/DD')}
|
{...momentFormatter('YYYY/MM/DD')}
|
||||||
|
onChange={(date) => {
|
||||||
|
form.setFieldValue(
|
||||||
|
'opening_balance_at',
|
||||||
|
moment(date).format('YYYY-MM-DD'),
|
||||||
|
);
|
||||||
|
}}
|
||||||
value={tansformDateValue(value)}
|
value={tansformDateValue(value)}
|
||||||
popoverProps={{ position: Position.BOTTOM, minimal: true }}
|
popoverProps={{ position: Position.BOTTOM, minimal: true }}
|
||||||
disabled={customerId}
|
disabled={customerId}
|
||||||
@@ -55,7 +61,7 @@ function CustomerFinancialPanel({
|
|||||||
{/*------------ Opening balance -----------*/}
|
{/*------------ Opening balance -----------*/}
|
||||||
<FastField name={'opening_balance'}>
|
<FastField name={'opening_balance'}>
|
||||||
{({
|
{({
|
||||||
form: { values },
|
form,
|
||||||
field,
|
field,
|
||||||
field: { value },
|
field: { value },
|
||||||
meta: { error, touched },
|
meta: { error, touched },
|
||||||
@@ -70,12 +76,14 @@ function CustomerFinancialPanel({
|
|||||||
inline={true}
|
inline={true}
|
||||||
>
|
>
|
||||||
<ControlGroup>
|
<ControlGroup>
|
||||||
<InputPrependText text={values.currency_code} />
|
<InputPrependText text={form.values.currency_code} />
|
||||||
<MoneyInputGroup
|
<MoneyInputGroup
|
||||||
value={value}
|
value={value}
|
||||||
inputGroupProps={{ fill: true }}
|
inputGroupProps={{ fill: true }}
|
||||||
disabled={customerId}
|
disabled={customerId}
|
||||||
{...field}
|
onChange={(balance) => {
|
||||||
|
form.setFieldValue('opening_balance', balance);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</ControlGroup>
|
</ControlGroup>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ export default function CustomerFloatingActions({
|
|||||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
/>
|
/>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
{/* ----------- Clear & Reset----------- */}
|
{/* ----------- Clear & Reset----------- */}
|
||||||
<Button
|
<Button
|
||||||
className={'ml1'}
|
className={'ml1'}
|
||||||
@@ -91,7 +92,6 @@ export default function CustomerFloatingActions({
|
|||||||
onClick={handleCancelBtnClick}
|
onClick={handleCancelBtnClick}
|
||||||
text={<T id={'cancel'} />}
|
text={<T id={'cancel'} />}
|
||||||
/>
|
/>
|
||||||
</ButtonGroup>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export default function CustomerFormAfterPrimarySection({}) {
|
|||||||
label={<T id={'website'} />}
|
label={<T id={'website'} />}
|
||||||
inline={true}
|
inline={true}
|
||||||
>
|
>
|
||||||
<InputGroup {...field} />
|
<InputGroup placeholder={'http://'} {...field} />
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
)}
|
)}
|
||||||
</FastField>
|
</FastField>
|
||||||
|
|||||||
@@ -137,7 +137,9 @@ const CustomerTable = ({
|
|||||||
{
|
{
|
||||||
id: 'receivable_balance',
|
id: 'receivable_balance',
|
||||||
Header: formatMessage({ id: 'receivable_balance' }),
|
Header: formatMessage({ id: 'receivable_balance' }),
|
||||||
accessor: (r) => <Money amount={r.closing_balance} currency={'USD'} />,
|
accessor: (r) => (
|
||||||
|
<Money amount={r.closing_balance} currency={r.currency_code} />
|
||||||
|
),
|
||||||
className: 'receivable_balance',
|
className: 'receivable_balance',
|
||||||
width: 100,
|
width: 100,
|
||||||
},
|
},
|
||||||
@@ -189,7 +191,6 @@ const CustomerTable = ({
|
|||||||
customersCurrentViewId === -1,
|
customersCurrentViewId === -1,
|
||||||
customers.length === 0,
|
customers.length === 0,
|
||||||
].every((condition) => condition === true);
|
].every((condition) => condition === true);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(CLASSES.DASHBOARD_DATATABLE)}>
|
<div className={classNames(CLASSES.DASHBOARD_DATATABLE)}>
|
||||||
<LoadingIndicator loading={customersLoading && !isLoadedBefore}>
|
<LoadingIndicator loading={customersLoading && !isLoadedBefore}>
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export default function ItemCategoryForm({
|
|||||||
{({ field, field: { value }, meta: { error, touched } }) => (
|
{({ field, field: { value }, meta: { error, touched } }) => (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'category_name'} />}
|
label={<T id={'category_name'} />}
|
||||||
labelInfo={FieldRequiredHint}
|
labelInfo={<FieldRequiredHint />}
|
||||||
className={'form-group--category-name'}
|
className={'form-group--category-name'}
|
||||||
intent={inputIntent({ error, touched })}
|
intent={inputIntent({ error, touched })}
|
||||||
helperText={<ErrorMessage name="name" />}
|
helperText={<ErrorMessage name="name" />}
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ function ExpensesDataTable({
|
|||||||
text={formatMessage({ id: 'view_details' })}
|
text={formatMessage({ id: 'view_details' })}
|
||||||
/>
|
/>
|
||||||
<MenuDivider />
|
<MenuDivider />
|
||||||
<If condition={!expense.published}>
|
<If condition={!expense.is_published}>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon={<Icon icon={'arrow-to-top'} size={16} />}
|
icon={<Icon icon={'arrow-to-top'} size={16} />}
|
||||||
text={formatMessage({ id: 'publish_expense' })}
|
text={formatMessage({ id: 'publish_expense' })}
|
||||||
@@ -209,7 +209,7 @@ function ExpensesDataTable({
|
|||||||
id: 'publish',
|
id: 'publish',
|
||||||
Header: formatMessage({ id: 'publish' }),
|
Header: formatMessage({ id: 'publish' }),
|
||||||
accessor: (r) => {
|
accessor: (r) => {
|
||||||
return r.published ? (
|
return !!r.is_published ? (
|
||||||
<Tag minimal={true}>
|
<Tag minimal={true}>
|
||||||
<T id={'published'} />
|
<T id={'published'} />
|
||||||
</Tag>
|
</Tag>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { FormattedMessage as T } from 'react-intl';
|
|||||||
import { CLASSES } from 'common/classes';
|
import { CLASSES } from 'common/classes';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { saveInvoke } from 'utils';
|
import { saveInvoke } from 'utils';
|
||||||
import { Icon } from 'components';
|
import { Icon, If } from 'components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expense form floating actions.
|
* Expense form floating actions.
|
||||||
@@ -25,11 +25,18 @@ export default function ExpenseFloatingFooter({
|
|||||||
onCancelClick,
|
onCancelClick,
|
||||||
onDraftClick,
|
onDraftClick,
|
||||||
onClearClick,
|
onClearClick,
|
||||||
onSubmitAndNewClick,
|
|
||||||
onSubmitForm,
|
onSubmitForm,
|
||||||
onResetForm,
|
onResetForm,
|
||||||
expense,
|
expense,
|
||||||
|
expensePublished,
|
||||||
}) {
|
}) {
|
||||||
|
const handleSubmitPublishBtnClick = (event) => {
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: true,
|
||||||
|
publish: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleSubmitPublishAndNewBtnClick = (event) => {
|
const handleSubmitPublishAndNewBtnClick = (event) => {
|
||||||
onSubmitForm();
|
onSubmitForm();
|
||||||
saveInvoke(onSubmitClick, event, {
|
saveInvoke(onSubmitClick, event, {
|
||||||
@@ -47,6 +54,13 @@ export default function ExpenseFloatingFooter({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSubmitDraftBtnClick = (event) => {
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: true,
|
||||||
|
publish: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleSubmitDraftAndNewBtnClick = (event) => {
|
const handleSubmitDraftAndNewBtnClick = (event) => {
|
||||||
onSubmitForm();
|
onSubmitForm();
|
||||||
saveInvoke(onSubmitClick, event, {
|
saveInvoke(onSubmitClick, event, {
|
||||||
@@ -60,31 +74,30 @@ export default function ExpenseFloatingFooter({
|
|||||||
onSubmitForm();
|
onSubmitForm();
|
||||||
saveInvoke(onSubmitClick, event, {
|
saveInvoke(onSubmitClick, event, {
|
||||||
redirect: false,
|
redirect: false,
|
||||||
publish: true,
|
publish: false,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleCancelBtnClick = (event) => {
|
||||||
|
saveInvoke(onCancelClick, event);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClearBtnClick = (event) => {
|
||||||
|
// saveInvoke(onClearClick, event);
|
||||||
|
onResetForm();
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
||||||
<ButtonGroup>
|
|
||||||
{/* ----------- Save And Publish ----------- */}
|
{/* ----------- Save And Publish ----------- */}
|
||||||
|
<If condition={!expense || !expensePublished}>
|
||||||
|
<ButtonGroup>
|
||||||
<Button
|
<Button
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
type="submit"
|
type="submit"
|
||||||
onClick={(event) => {
|
onClick={handleSubmitPublishBtnClick}
|
||||||
saveInvoke(onSubmitClick, event, {
|
text={<T id={'save_publish'} />}
|
||||||
redirect: true,
|
|
||||||
publish: true,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
text={
|
|
||||||
expense && expense.id ? (
|
|
||||||
<T id={'edit'} />
|
|
||||||
) : (
|
|
||||||
<T id={'save_publish'} />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<Popover
|
<Popover
|
||||||
content={
|
content={
|
||||||
@@ -108,18 +121,14 @@ export default function ExpenseFloatingFooter({
|
|||||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
/>
|
/>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
{/* ----------- Save As Draft ----------- */}
|
{/* ----------- Save As Draft ----------- */}
|
||||||
|
<ButtonGroup>
|
||||||
<Button
|
<Button
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
className={'ml1'}
|
className={'ml1'}
|
||||||
type="submit"
|
type="submit"
|
||||||
onClick={(event) => {
|
onClick={handleSubmitDraftBtnClick}
|
||||||
saveInvoke(onSubmitClick, event, {
|
|
||||||
redirect: true,
|
|
||||||
publish: false,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
text={<T id={'save_as_draft'} />}
|
text={<T id={'save_as_draft'} />}
|
||||||
/>
|
/>
|
||||||
<Popover
|
<Popover
|
||||||
@@ -139,28 +148,55 @@ export default function ExpenseFloatingFooter({
|
|||||||
interactionKind={PopoverInteractionKind.CLICK}
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
position={Position.BOTTOM_LEFT}
|
position={Position.BOTTOM_LEFT}
|
||||||
>
|
>
|
||||||
<Button rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />} />
|
<Button
|
||||||
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
|
/>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
{/* ----------- Clear ----------- */}
|
</If>
|
||||||
|
{/* ----------- Save and New ----------- */}
|
||||||
|
<If condition={expense && expensePublished}>
|
||||||
|
<ButtonGroup>
|
||||||
|
<Button
|
||||||
|
disabled={isSubmitting}
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
type="submit"
|
||||||
|
onClick={handleSubmitPublishBtnClick}
|
||||||
|
text={<T id={'save'} />}
|
||||||
|
/>
|
||||||
|
<Popover
|
||||||
|
content={
|
||||||
|
<Menu>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'save_and_new'} />}
|
||||||
|
onClick={handleSubmitPublishAndNewBtnClick}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
}
|
||||||
|
minimal={true}
|
||||||
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
|
position={Position.BOTTOM_LEFT}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
|
</If>
|
||||||
|
{/* ----------- Clear & Reset----------- */}
|
||||||
<Button
|
<Button
|
||||||
className={'ml1'}
|
className={'ml1'}
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
onClick={(event) => {
|
onClick={handleClearBtnClick}
|
||||||
onResetForm();
|
text={expense ? <T id={'reset'} /> : <T id={'clear'} />}
|
||||||
saveInvoke(onClearClick, event);
|
|
||||||
}}
|
|
||||||
text={expense && expense.id ? <T id={'reset'} /> : <T id={'clear'} />}
|
|
||||||
/>
|
/>
|
||||||
{/* ----------- Cancel ----------- */}
|
{/* ----------- Cancel ----------- */}
|
||||||
<Button
|
<Button
|
||||||
className={'ml1'}
|
className={'ml1'}
|
||||||
onClick={(event) => {
|
onClick={handleCancelBtnClick}
|
||||||
saveInvoke(onCancelClick, event);
|
|
||||||
}}
|
|
||||||
text={<T id={'cancel'} />}
|
text={<T id={'cancel'} />}
|
||||||
/>
|
/>
|
||||||
</ButtonGroup>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const Schema = Yup.object().shape({
|
|||||||
.max(DATATYPES_LENGTH.TEXT)
|
.max(DATATYPES_LENGTH.TEXT)
|
||||||
.nullable()
|
.nullable()
|
||||||
.label(formatMessage({ id: 'description' })),
|
.label(formatMessage({ id: 'description' })),
|
||||||
publish: Yup.boolean().label(formatMessage({ id: 'publish' })),
|
is_published: Yup.boolean(),
|
||||||
categories: Yup.array().of(
|
categories: Yup.array().of(
|
||||||
Yup.object().shape({
|
Yup.object().shape({
|
||||||
index: Yup.number().min(1).max(DATATYPES_LENGTH.INT_10).nullable(),
|
index: Yup.number().min(1).max(DATATYPES_LENGTH.INT_10).nullable(),
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ const Schema = Yup.object().shape({
|
|||||||
.max(DATATYPES_LENGTH.STRING)
|
.max(DATATYPES_LENGTH.STRING)
|
||||||
.label(formatMessage({ id: 'item_type_' })),
|
.label(formatMessage({ id: 'item_type_' })),
|
||||||
code: Yup.string().trim().min(0).max(DATATYPES_LENGTH.STRING),
|
code: Yup.string().trim().min(0).max(DATATYPES_LENGTH.STRING),
|
||||||
cost_price: Yup.number().when(['purchasable'], {
|
cost_price: Yup.number().min(0).when(['purchasable'], {
|
||||||
is: true,
|
is: true,
|
||||||
then: Yup.number()
|
then: Yup.number()
|
||||||
.required()
|
.required()
|
||||||
.label(formatMessage({ id: 'cost_price_' })),
|
.label(formatMessage({ id: 'cost_price_' })),
|
||||||
otherwise: Yup.number().nullable(true),
|
otherwise: Yup.number().nullable(true),
|
||||||
}),
|
}),
|
||||||
sell_price: Yup.number().when(['sellable'], {
|
sell_price: Yup.number().min(0).when(['sellable'], {
|
||||||
is: true,
|
is: true,
|
||||||
then: Yup.number()
|
then: Yup.number()
|
||||||
.required()
|
.required()
|
||||||
|
|||||||
@@ -1,62 +1,201 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Intent, Button } from '@blueprintjs/core';
|
import {
|
||||||
|
Intent,
|
||||||
|
Button,
|
||||||
|
ButtonGroup,
|
||||||
|
Popover,
|
||||||
|
PopoverInteractionKind,
|
||||||
|
Position,
|
||||||
|
Menu,
|
||||||
|
MenuItem,
|
||||||
|
} from '@blueprintjs/core';
|
||||||
import { FormattedMessage as T } from 'react-intl';
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
|
import { CLASSES } from 'common/classes';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { useFormikContext } from 'formik';
|
||||||
import { saveInvoke } from 'utils';
|
import { saveInvoke } from 'utils';
|
||||||
|
import { If, Icon } from 'components';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bill floating actions bar.
|
||||||
|
*/
|
||||||
export default function BillFloatingActions({
|
export default function BillFloatingActions({
|
||||||
isSubmitting,
|
isSubmitting,
|
||||||
onSubmitClick,
|
onSubmitClick,
|
||||||
onSubmitAndNewClick,
|
|
||||||
onCancelClick,
|
onCancelClick,
|
||||||
onClearClick,
|
onClearClick,
|
||||||
billId,
|
billId,
|
||||||
|
billPublished,
|
||||||
}) {
|
}) {
|
||||||
return (
|
const { resetForm, submitForm } = useFormikContext();
|
||||||
<div className={'form__floating-footer'}>
|
const handleSubmitPublishBtnClick = (event) => {
|
||||||
<Button
|
saveInvoke(onSubmitClick, event, {
|
||||||
disabled={isSubmitting}
|
redirect: true,
|
||||||
loading={isSubmitting}
|
publish: true,
|
||||||
intent={Intent.PRIMARY}
|
});
|
||||||
type="submit"
|
};
|
||||||
onClick={(event) => {
|
|
||||||
saveInvoke(onSubmitClick, event);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{billId ? <T id={'edit'} /> : <T id={'save'} />}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
const handleSubmitPublishAndNewBtnClick = (event) => {
|
||||||
disabled={isSubmitting}
|
submitForm();
|
||||||
loading={isSubmitting}
|
saveInvoke(onSubmitClick, event, {
|
||||||
intent={Intent.PRIMARY}
|
redirect: false,
|
||||||
className={'ml1'}
|
publish: true,
|
||||||
type="submit"
|
resetForm: true,
|
||||||
onClick={(event) => {
|
});
|
||||||
saveInvoke(onSubmitAndNewClick, event);
|
};
|
||||||
}}
|
|
||||||
>
|
|
||||||
<T id={'save_new'} />
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
const handleSubmitPublishContinueEditingBtnClick = (event) => {
|
||||||
className={'ml1'}
|
submitForm();
|
||||||
disabled={isSubmitting}
|
saveInvoke(onSubmitClick, event, {
|
||||||
onClick={(event) => {
|
redirect: false,
|
||||||
saveInvoke(onClearClick, event);
|
publish: true,
|
||||||
}}
|
});
|
||||||
>
|
};
|
||||||
<T id={'clear'} />
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
const handleSubmitDraftBtnClick = (event) => {
|
||||||
className={'ml1'}
|
saveInvoke(onSubmitClick, event, {
|
||||||
type="submit"
|
redirect: true,
|
||||||
onClick={(event) => {
|
publish: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitDraftAndNewBtnClick = (event) => {
|
||||||
|
submitForm();
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: false,
|
||||||
|
publish: false,
|
||||||
|
resetForm: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitDraftContinueEditingBtnClick = (event) => {
|
||||||
|
submitForm();
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: false,
|
||||||
|
publish: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancelBtnClick = (event) => {
|
||||||
saveInvoke(onCancelClick, event);
|
saveInvoke(onCancelClick, event);
|
||||||
}}
|
};
|
||||||
|
|
||||||
|
const handleClearBtnClick = (event) => {
|
||||||
|
// saveInvoke(onClearClick, event);
|
||||||
|
resetForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
||||||
|
{/* ----------- Save And Publish ----------- */}
|
||||||
|
<If condition={!billId || !billPublished}>
|
||||||
|
<ButtonGroup>
|
||||||
|
<Button
|
||||||
|
disabled={isSubmitting}
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
type="submit"
|
||||||
|
onClick={handleSubmitPublishBtnClick}
|
||||||
|
text={<T id={'save_publish'} />}
|
||||||
|
/>
|
||||||
|
<Popover
|
||||||
|
content={
|
||||||
|
<Menu>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'publish_and_new'} />}
|
||||||
|
onClick={handleSubmitPublishAndNewBtnClick}
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'publish_continue_editing'} />}
|
||||||
|
onClick={handleSubmitPublishContinueEditingBtnClick}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
}
|
||||||
|
minimal={true}
|
||||||
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
|
position={Position.BOTTOM_LEFT}
|
||||||
>
|
>
|
||||||
<T id={'close'} />
|
<Button
|
||||||
</Button>
|
intent={Intent.PRIMARY}
|
||||||
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
|
{/* ----------- Save As Draft ----------- */}
|
||||||
|
<ButtonGroup>
|
||||||
|
<Button
|
||||||
|
disabled={isSubmitting}
|
||||||
|
className={'ml1'}
|
||||||
|
type="submit"
|
||||||
|
onClick={handleSubmitDraftBtnClick}
|
||||||
|
text={<T id={'save_as_draft'} />}
|
||||||
|
/>
|
||||||
|
<Popover
|
||||||
|
content={
|
||||||
|
<Menu>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'save_and_new'} />}
|
||||||
|
onClick={handleSubmitDraftAndNewBtnClick}
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'save_continue_editing'} />}
|
||||||
|
onClick={handleSubmitDraftContinueEditingBtnClick}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
}
|
||||||
|
minimal={true}
|
||||||
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
|
position={Position.BOTTOM_LEFT}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
|
</If>
|
||||||
|
{/* ----------- Save and New ----------- */}
|
||||||
|
<If condition={billId && billPublished}>
|
||||||
|
<ButtonGroup>
|
||||||
|
<Button
|
||||||
|
disabled={isSubmitting}
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
type="submit"
|
||||||
|
onClick={handleSubmitPublishBtnClick}
|
||||||
|
text={<T id={'save'} />}
|
||||||
|
/>
|
||||||
|
<Popover
|
||||||
|
content={
|
||||||
|
<Menu>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'save_and_new'} />}
|
||||||
|
onClick={handleSubmitPublishAndNewBtnClick}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
}
|
||||||
|
minimal={true}
|
||||||
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
|
position={Position.BOTTOM_LEFT}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
|
</If>
|
||||||
|
|
||||||
|
{/* ----------- Clear & Reset----------- */}
|
||||||
|
<Button
|
||||||
|
className={'ml1'}
|
||||||
|
disabled={isSubmitting}
|
||||||
|
onClick={handleClearBtnClick}
|
||||||
|
text={billId ? <T id={'reset'} /> : <T id={'clear'} />}
|
||||||
|
/>
|
||||||
|
{/* ----------- Cancel ----------- */}
|
||||||
|
<Button
|
||||||
|
className={'ml1'}
|
||||||
|
onClick={handleCancelBtnClick}
|
||||||
|
text={<T id={'cancel'} />}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ const defaultInitialValues = {
|
|||||||
entries: [...repeatValue(defaultBill, MIN_LINES_NUMBER)],
|
entries: [...repeatValue(defaultBill, MIN_LINES_NUMBER)],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bill form.
|
||||||
|
*/
|
||||||
function BillForm({
|
function BillForm({
|
||||||
//#WithMedia
|
//#WithMedia
|
||||||
requestSubmitMedia,
|
requestSubmitMedia,
|
||||||
@@ -75,12 +78,12 @@ function BillForm({
|
|||||||
const isNewMode = !billId;
|
const isNewMode = !billId;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (bill && bill.id) {
|
if (!isNewMode) {
|
||||||
changePageTitle(formatMessage({ id: 'edit_bill' }));
|
changePageTitle(formatMessage({ id: 'edit_bill' }));
|
||||||
} else {
|
} else {
|
||||||
changePageTitle(formatMessage({ id: 'new_bill' }));
|
changePageTitle(formatMessage({ id: 'new_bill' }));
|
||||||
}
|
}
|
||||||
}, [changePageTitle, bill, formatMessage]);
|
}, [changePageTitle, isNewMode, formatMessage]);
|
||||||
|
|
||||||
// Initial values in create and edit mode.
|
// Initial values in create and edit mode.
|
||||||
const initialValues = useMemo(
|
const initialValues = useMemo(
|
||||||
@@ -146,8 +149,8 @@ function BillForm({
|
|||||||
message: formatMessage(
|
message: formatMessage(
|
||||||
{
|
{
|
||||||
id: isNewMode
|
id: isNewMode
|
||||||
? 'the_bill_has_been_successfully_created'
|
? 'the_bill_has_been_successfully_created' :
|
||||||
: 'the_bill_has_been_successfully_edited',
|
'the_bill_has_been_successfully_edited',
|
||||||
},
|
},
|
||||||
{ number: values.bill_number },
|
{ number: values.bill_number },
|
||||||
),
|
),
|
||||||
@@ -155,11 +158,13 @@ function BillForm({
|
|||||||
});
|
});
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
|
|
||||||
resetForm();
|
|
||||||
changePageSubtitle('');
|
changePageSubtitle('');
|
||||||
|
|
||||||
if (submitPayload.redirect) {
|
if (submitPayload.redirect) {
|
||||||
history.go('/bills');
|
history.push('/bills');
|
||||||
|
}
|
||||||
|
if (submitPayload.resetForm) {
|
||||||
|
resetForm();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Handle the request error.
|
// Handle the request error.
|
||||||
@@ -167,7 +172,7 @@ function BillForm({
|
|||||||
handleErrors(errors, { setErrors });
|
handleErrors(errors, { setErrors });
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
};
|
};
|
||||||
if (isNewMode) {
|
if (bill && bill.id) {
|
||||||
requestEditBill(bill.id, form).then(onSuccess).catch(onError);
|
requestEditBill(bill.id, form).then(onSuccess).catch(onError);
|
||||||
} else {
|
} else {
|
||||||
requestSubmitBill(form).then(onSuccess).catch(onError);
|
requestSubmitBill(form).then(onSuccess).catch(onError);
|
||||||
@@ -190,9 +195,12 @@ function BillForm({
|
|||||||
[changePageSubtitle],
|
[changePageSubtitle],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSubmitClick = useCallback(() => {
|
const handleSubmitClick = useCallback(
|
||||||
setSubmitPayload({ redirect: true });
|
(event, payload) => {
|
||||||
}, [setSubmitPayload]);
|
setSubmitPayload({ ...payload });
|
||||||
|
},
|
||||||
|
[setSubmitPayload],
|
||||||
|
);
|
||||||
|
|
||||||
const handleCancelClick = useCallback(() => {
|
const handleCancelClick = useCallback(() => {
|
||||||
history.goBack();
|
history.goBack();
|
||||||
@@ -209,7 +217,7 @@ function BillForm({
|
|||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
onSubmit={handleFormSubmit}
|
onSubmit={handleFormSubmit}
|
||||||
>
|
>
|
||||||
{({ isSubmitting, values }) => (
|
{({ isSubmitting }) => (
|
||||||
<Form>
|
<Form>
|
||||||
<BillFormHeader onBillNumberChanged={handleBillNumberChanged} />
|
<BillFormHeader onBillNumberChanged={handleBillNumberChanged} />
|
||||||
<BillFormBody defaultBill={defaultBill} />
|
<BillFormBody defaultBill={defaultBill} />
|
||||||
@@ -220,8 +228,9 @@ function BillForm({
|
|||||||
<BillFloatingActions
|
<BillFloatingActions
|
||||||
isSubmitting={isSubmitting}
|
isSubmitting={isSubmitting}
|
||||||
billId={billId}
|
billId={billId}
|
||||||
|
billPublished={true}
|
||||||
onSubmitClick={handleSubmitClick}
|
onSubmitClick={handleSubmitClick}
|
||||||
onCancelForm={handleCancelClick}
|
onCancelClick={handleCancelClick}
|
||||||
/>
|
/>
|
||||||
</Form>
|
</Form>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Intent, Button } from '@blueprintjs/core';
|
import {
|
||||||
|
Intent,
|
||||||
|
Button,
|
||||||
|
ButtonGroup,
|
||||||
|
Popover,
|
||||||
|
PopoverInteractionKind,
|
||||||
|
Position,
|
||||||
|
Menu,
|
||||||
|
MenuItem,
|
||||||
|
} from '@blueprintjs/core';
|
||||||
import { FormattedMessage as T } from 'react-intl';
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import { CLASSES } from 'common/classes';
|
import { CLASSES } from 'common/classes';
|
||||||
|
import { saveInvoke } from 'utils';
|
||||||
|
import { Icon } from 'components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Payment made floating actions bar.
|
* Payment made floating actions bar.
|
||||||
@@ -13,56 +23,85 @@ export default function PaymentMadeFloatingActions({
|
|||||||
onSubmitClick,
|
onSubmitClick,
|
||||||
onCancelClick,
|
onCancelClick,
|
||||||
onClearBtnClick,
|
onClearBtnClick,
|
||||||
|
onSubmitForm,
|
||||||
|
paymentMadeId,
|
||||||
}) {
|
}) {
|
||||||
|
const handleSubmitBtnClick = (event) => {
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleClearBtnClick = (event) => {
|
const handleClearBtnClick = (event) => {
|
||||||
onClearBtnClick && onClearBtnClick(event);
|
onClearBtnClick && onClearBtnClick(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmitClick = (event) => {
|
const handleCancelBtnClick = (event) => {
|
||||||
onSubmitClick && onSubmitClick(event, { redirect: true });
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCancelClick = (event) => {
|
|
||||||
onCancelClick && onCancelClick(event);
|
onCancelClick && onCancelClick(event);
|
||||||
|
saveInvoke(onCancelClick, event);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSubmitAndNewClick = (event) => {
|
||||||
|
onSubmitForm();
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitContinueEditingBtnClick = (event) => {
|
||||||
|
onSubmitForm();
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: false,
|
||||||
|
publish: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
||||||
|
{/* ----------- Save and New ----------- */}
|
||||||
|
<ButtonGroup>
|
||||||
<Button
|
<Button
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
type="submit"
|
type="submit"
|
||||||
onClick={handleSubmitClick}
|
onClick={handleSubmitBtnClick}
|
||||||
|
text={paymentMadeId ? <T id={'edit'} /> : <T id={'save'} />}
|
||||||
|
/>
|
||||||
|
<Popover
|
||||||
|
content={
|
||||||
|
<Menu>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'save_and_new'} />}
|
||||||
|
onClick={handleSubmitAndNewClick}
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'save_continue_editing'} />}
|
||||||
|
onClick={handleSubmitContinueEditingBtnClick}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
}
|
||||||
|
minimal={true}
|
||||||
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
|
position={Position.BOTTOM_LEFT}
|
||||||
>
|
>
|
||||||
<T id={'save_send'} />
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
disabled={isSubmitting}
|
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
className={'ml1'}
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
name={'save'}
|
/>
|
||||||
type="submit"
|
</Popover>
|
||||||
onClick={handleSubmitClick}
|
</ButtonGroup>
|
||||||
>
|
{/* ----------- Clear & Reset----------- */}
|
||||||
<T id={'save'} />
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
className={'ml1'}
|
className={'ml1'}
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
onClick={handleClearBtnClick}
|
onClick={handleClearBtnClick}
|
||||||
>
|
text={paymentMadeId ? <T id={'reset'} /> : <T id={'clear'} />}
|
||||||
<T id={'clear'} />
|
/>
|
||||||
</Button>
|
{/* ----------- Cancel ----------- */}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
className={'ml1'}
|
className={'ml1'}
|
||||||
type="submit"
|
onClick={handleCancelBtnClick}
|
||||||
onClick={handleCancelClick}
|
text={<T id={'cancel'} />}
|
||||||
>
|
/>
|
||||||
<T id={'close'} />
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ function PaymentMadeForm({
|
|||||||
const [clearLinesAlert, setClearLinesAlert] = useState(false);
|
const [clearLinesAlert, setClearLinesAlert] = useState(false);
|
||||||
const [clearFormAlert, setClearFormAlert] = useState(false);
|
const [clearFormAlert, setClearFormAlert] = useState(false);
|
||||||
const [fullAmount, setFullAmount] = useState(null);
|
const [fullAmount, setFullAmount] = useState(null);
|
||||||
|
const [submitPayload, setSubmitPayload] = useState({});
|
||||||
|
|
||||||
const [localPaymentEntries, setLocalPaymentEntries] = useState(
|
const [localPaymentEntries, setLocalPaymentEntries] = useState(
|
||||||
paymentMadeEntries,
|
paymentMadeEntries,
|
||||||
@@ -155,8 +156,13 @@ function PaymentMadeForm({
|
|||||||
intent: Intent.SUCCESS,
|
intent: Intent.SUCCESS,
|
||||||
});
|
});
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
resetForm();
|
// resetForm();
|
||||||
changePageSubtitle('');
|
changePageSubtitle('');
|
||||||
|
|
||||||
|
if (submitPayload.redirect) {
|
||||||
|
history.push('/payment-mades');
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onError = (errors) => {
|
const onError = (errors) => {
|
||||||
@@ -187,6 +193,7 @@ function PaymentMadeForm({
|
|||||||
values,
|
values,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
isSubmitting,
|
isSubmitting,
|
||||||
|
submitForm,
|
||||||
} = useFormik({
|
} = useFormik({
|
||||||
validationSchema,
|
validationSchema,
|
||||||
initialValues,
|
initialValues,
|
||||||
@@ -300,6 +307,14 @@ function PaymentMadeForm({
|
|||||||
[values.entries],
|
[values.entries],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleSubmitClick = useCallback(
|
||||||
|
(event, payload) => {
|
||||||
|
setSubmitPayload({ ...payload });
|
||||||
|
},
|
||||||
|
[setSubmitPayload],
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
@@ -379,8 +394,11 @@ function PaymentMadeForm({
|
|||||||
|
|
||||||
<PaymentMadeFloatingActions
|
<PaymentMadeFloatingActions
|
||||||
isSubmitting={isSubmitting}
|
isSubmitting={isSubmitting}
|
||||||
|
paymentMadeId={paymentMadeId}
|
||||||
|
onSubmitClick={handleSubmitClick}
|
||||||
onCancelClick={handleCancelClick}
|
onCancelClick={handleCancelClick}
|
||||||
onClearBtnClick={handleClearBtnClick}
|
onClearBtnClick={handleClearBtnClick}
|
||||||
|
onSubmitForm={submitForm}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* <Dragzone
|
{/* <Dragzone
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ function PaymentMadeList({
|
|||||||
}, [deletePaymentMade, requestDeletePaymentMade, formatMessage]);
|
}, [deletePaymentMade, requestDeletePaymentMade, formatMessage]);
|
||||||
|
|
||||||
const handleEditPaymentMade = useCallback((payment) => {
|
const handleEditPaymentMade = useCallback((payment) => {
|
||||||
history.push(`/payment-made/${payment.id}/edit`);
|
history.push(`/payment-mades/${payment.id}/edit`);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Calculates the selected rows count.
|
// Calculates the selected rows count.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default function PaymentMadesEmptyStatus() {
|
|||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
large={true}
|
large={true}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
history.push('/payment-made/new');
|
history.push('/payment-mades/new');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
New bill payment
|
New bill payment
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { CLASSES } from 'common/classes';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useFormikContext } from 'formik';
|
import { useFormikContext } from 'formik';
|
||||||
import { saveInvoke } from 'utils';
|
import { saveInvoke } from 'utils';
|
||||||
import { Icon } from 'components';
|
import { If, Icon } from 'components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Estimate floating actions bar.
|
* Estimate floating actions bar.
|
||||||
@@ -25,12 +25,55 @@ export default function EstimateFloatingActions({
|
|||||||
onCancelClick,
|
onCancelClick,
|
||||||
onClearClick,
|
onClearClick,
|
||||||
estimateId,
|
estimateId,
|
||||||
|
estimatePublished,
|
||||||
}) {
|
}) {
|
||||||
const { resetForm, submitForm } = useFormikContext();
|
const { resetForm, submitForm } = useFormikContext();
|
||||||
|
|
||||||
const handleSubmitBtnClick = (event) => {
|
const handleSubmitPublishBtnClick = (event) => {
|
||||||
saveInvoke(onSubmitClick, event, {
|
saveInvoke(onSubmitClick, event, {
|
||||||
redirect: true,
|
redirect: true,
|
||||||
|
publish: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitPublishAndNewBtnClick = (event) => {
|
||||||
|
submitForm();
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: false,
|
||||||
|
publish: true,
|
||||||
|
resetForm: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitPublishContinueEditingBtnClick = (event) => {
|
||||||
|
submitForm();
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: false,
|
||||||
|
publish: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitDraftBtnClick = (event) => {
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: true,
|
||||||
|
publish: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitDraftAndNewBtnClick = (event) => {
|
||||||
|
submitForm();
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: false,
|
||||||
|
publish: false,
|
||||||
|
resetForm: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitDraftContinueEditingBtnClick = (event) => {
|
||||||
|
submitForm();
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: false,
|
||||||
|
publish: false,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -43,30 +86,28 @@ export default function EstimateFloatingActions({
|
|||||||
resetForm();
|
resetForm();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmitAndNewClick = (event) => {
|
|
||||||
submitForm();
|
|
||||||
saveInvoke(onSubmitClick, event, {
|
|
||||||
redirect: false,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
||||||
|
{/* ----------- Save And Publish ----------- */}
|
||||||
|
<If condition={!estimateId || !estimatePublished}>
|
||||||
<ButtonGroup>
|
<ButtonGroup>
|
||||||
{/* ----------- Save and New ----------- */}
|
|
||||||
<Button
|
<Button
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
type="submit"
|
type="submit"
|
||||||
onClick={handleSubmitBtnClick}
|
onClick={handleSubmitPublishBtnClick}
|
||||||
text={estimateId ? <T id={'edit'} /> : <T id={'save'} />}
|
text={<T id={'save_publish'} />}
|
||||||
/>
|
/>
|
||||||
<Popover
|
<Popover
|
||||||
content={
|
content={
|
||||||
<Menu>
|
<Menu>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
text={<T id={'save_and_new'} />}
|
text={<T id={'publish_and_new'} />}
|
||||||
onClick={handleSubmitAndNewClick}
|
onClick={handleSubmitPublishAndNewBtnClick}
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'publish_continue_editing'} />}
|
||||||
|
onClick={handleSubmitPublishContinueEditingBtnClick}
|
||||||
/>
|
/>
|
||||||
</Menu>
|
</Menu>
|
||||||
}
|
}
|
||||||
@@ -79,6 +120,70 @@ export default function EstimateFloatingActions({
|
|||||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
/>
|
/>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
|
{/* ----------- Save As Draft ----------- */}
|
||||||
|
<ButtonGroup>
|
||||||
|
<Button
|
||||||
|
disabled={isSubmitting}
|
||||||
|
className={'ml1'}
|
||||||
|
type="submit"
|
||||||
|
onClick={handleSubmitDraftBtnClick}
|
||||||
|
text={<T id={'save_as_draft'} />}
|
||||||
|
/>
|
||||||
|
<Popover
|
||||||
|
content={
|
||||||
|
<Menu>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'save_and_new'} />}
|
||||||
|
onClick={handleSubmitDraftAndNewBtnClick}
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'save_continue_editing'} />}
|
||||||
|
onClick={handleSubmitDraftContinueEditingBtnClick}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
}
|
||||||
|
minimal={true}
|
||||||
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
|
position={Position.BOTTOM_LEFT}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
|
</If>
|
||||||
|
{/* ----------- Save and New ----------- */}
|
||||||
|
<If condition={estimateId && estimatePublished}>
|
||||||
|
<ButtonGroup>
|
||||||
|
<Button
|
||||||
|
disabled={isSubmitting}
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
type="submit"
|
||||||
|
onClick={handleSubmitPublishBtnClick}
|
||||||
|
text={<T id={'save'} />}
|
||||||
|
/>
|
||||||
|
<Popover
|
||||||
|
content={
|
||||||
|
<Menu>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'save_and_new'} />}
|
||||||
|
onClick={handleSubmitPublishAndNewBtnClick}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
}
|
||||||
|
minimal={true}
|
||||||
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
|
position={Position.BOTTOM_LEFT}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
|
</If>
|
||||||
|
|
||||||
{/* ----------- Clear & Reset----------- */}
|
{/* ----------- Clear & Reset----------- */}
|
||||||
<Button
|
<Button
|
||||||
className={'ml1'}
|
className={'ml1'}
|
||||||
@@ -92,7 +197,6 @@ export default function EstimateFloatingActions({
|
|||||||
onClick={handleCancelBtnClick}
|
onClick={handleCancelBtnClick}
|
||||||
text={<T id={'cancel'} />}
|
text={<T id={'cancel'} />}
|
||||||
/>
|
/>
|
||||||
</ButtonGroup>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ const EstimateForm = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const transNumber = !isNewMode ? estimate.estimate_number : estimateNumber;
|
const transNumber = !isNewMode ? estimate.estimate_number : estimateNumber;
|
||||||
|
|
||||||
if (isNewMode) {
|
if (!isNewMode) {
|
||||||
changePageTitle(formatMessage({ id: 'edit_estimate' }));
|
changePageTitle(formatMessage({ id: 'edit_estimate' }));
|
||||||
} else {
|
} else {
|
||||||
changePageTitle(formatMessage({ id: 'new_estimate' }));
|
changePageTitle(formatMessage({ id: 'new_estimate' }));
|
||||||
@@ -199,11 +199,13 @@ const EstimateForm = ({
|
|||||||
intent: Intent.SUCCESS,
|
intent: Intent.SUCCESS,
|
||||||
});
|
});
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
resetForm();
|
|
||||||
|
|
||||||
if (submitPayload.redirect) {
|
if (submitPayload.redirect) {
|
||||||
history.push('/estimates');
|
history.push('/estimates');
|
||||||
}
|
}
|
||||||
|
if (submitPayload.resetForm) {
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onError = (errors) => {
|
const onError = (errors) => {
|
||||||
@@ -267,8 +269,8 @@ const EstimateForm = ({
|
|||||||
estimateId={estimateId}
|
estimateId={estimateId}
|
||||||
onSubmitClick={handleSubmitClick}
|
onSubmitClick={handleSubmitClick}
|
||||||
onCancelClick={handleCancelClick}
|
onCancelClick={handleCancelClick}
|
||||||
|
estimatePublished={true}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</Form>
|
</Form>
|
||||||
)}
|
)}
|
||||||
</Formik>
|
</Formik>
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ const Schema = Yup.object().shape({
|
|||||||
.required()
|
.required()
|
||||||
.label(formatMessage({ id: 'expiration_date_' })),
|
.label(formatMessage({ id: 'expiration_date_' })),
|
||||||
estimate_number: Yup.string()
|
estimate_number: Yup.string()
|
||||||
.nullable()
|
|
||||||
.max(DATATYPES_LENGTH.STRING)
|
.max(DATATYPES_LENGTH.STRING)
|
||||||
.label(formatMessage({ id: 'estimate_number_' })),
|
.label(formatMessage({ id: 'estimate_number_' })),
|
||||||
reference: Yup.string().min(1).max(DATATYPES_LENGTH.STRING).nullable(),
|
reference: Yup.string().min(1).max(DATATYPES_LENGTH.STRING).nullable(),
|
||||||
|
|||||||
@@ -14,8 +14,7 @@ import { FormattedMessage as T } from 'react-intl';
|
|||||||
import { CLASSES } from 'common/classes';
|
import { CLASSES } from 'common/classes';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { saveInvoke } from 'utils';
|
import { saveInvoke } from 'utils';
|
||||||
import { Icon } from 'components';
|
import { If, Icon } from 'components';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoice floating actions bar.
|
* Invoice floating actions bar.
|
||||||
@@ -26,76 +25,78 @@ export default function InvoiceFloatingActions({
|
|||||||
onCancelClick,
|
onCancelClick,
|
||||||
onClearClick,
|
onClearClick,
|
||||||
invoice,
|
invoice,
|
||||||
|
invoicePublished,
|
||||||
}) {
|
}) {
|
||||||
const { resetForm, submitForm } = useFormikContext();
|
const { resetForm, submitForm } = useFormikContext();
|
||||||
|
|
||||||
const handleSubmitPublishAndNewBtnClick = useCallback(
|
const handleSubmitPublishBtnClick = (event) => {
|
||||||
(event) => {
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: true,
|
||||||
|
publish: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitPublishAndNewBtnClick = (event) => {
|
||||||
submitForm();
|
submitForm();
|
||||||
saveInvoke(onSubmitClick, event, {
|
saveInvoke(onSubmitClick, event, {
|
||||||
redirect: false,
|
redirect: false,
|
||||||
publish: true,
|
publish: true,
|
||||||
resetForm: true,
|
resetForm: true,
|
||||||
});
|
});
|
||||||
},
|
};
|
||||||
[submitForm],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleSubmitPublishContinueEditingBtnClick = useCallback(
|
const handleSubmitPublishContinueEditingBtnClick = (event) => {
|
||||||
(event) => {
|
|
||||||
submitForm();
|
submitForm();
|
||||||
saveInvoke(onSubmitClick, event, {
|
saveInvoke(onSubmitClick, event, {
|
||||||
redirect: false,
|
redirect: false,
|
||||||
publish: true,
|
publish: true,
|
||||||
});
|
});
|
||||||
},
|
};
|
||||||
[submitForm],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleSubmitDraftAndNewBtnClick = useCallback(
|
const handleSubmitDraftBtnClick = (event) => {
|
||||||
(event) => {
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: true,
|
||||||
|
publish: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitDraftAndNewBtnClick = (event) => {
|
||||||
submitForm();
|
submitForm();
|
||||||
saveInvoke(onSubmitClick, event, {
|
saveInvoke(onSubmitClick, event, {
|
||||||
redirect: false,
|
redirect: false,
|
||||||
publish: false,
|
publish: false,
|
||||||
resetForm: true,
|
resetForm: true,
|
||||||
});
|
});
|
||||||
},
|
};
|
||||||
[submitForm],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleSubmitDraftContinueEditingBtnClick = useCallback(
|
const handleSubmitDraftContinueEditingBtnClick = (event) => {
|
||||||
(event) => {
|
|
||||||
submitForm();
|
submitForm();
|
||||||
saveInvoke(onSubmitClick, event, {
|
saveInvoke(onSubmitClick, event, {
|
||||||
redirect: false,
|
redirect: false,
|
||||||
publish: true,
|
publish: false,
|
||||||
});
|
});
|
||||||
},
|
};
|
||||||
[submitForm],
|
|
||||||
);
|
const handleCancelBtnClick = (event) => {
|
||||||
|
saveInvoke(onCancelClick, event);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClearBtnClick = (event) => {
|
||||||
|
// saveInvoke(onClearClick, event);
|
||||||
|
resetForm();
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
||||||
<ButtonGroup>
|
|
||||||
{/* ----------- Save And Publish ----------- */}
|
{/* ----------- Save And Publish ----------- */}
|
||||||
|
<If condition={!invoice || !invoicePublished}>
|
||||||
|
<ButtonGroup>
|
||||||
<Button
|
<Button
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
type="submit"
|
type="submit"
|
||||||
onClick={(event) => {
|
onClick={handleSubmitPublishBtnClick}
|
||||||
saveInvoke(onSubmitClick, event, {
|
text={<T id={'save_publish'} />}
|
||||||
redirect: true,
|
|
||||||
publish: true,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
text={
|
|
||||||
invoice && invoice.id ? (
|
|
||||||
<T id={'edit'} />
|
|
||||||
) : (
|
|
||||||
<T id={'save_publish'} />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<Popover
|
<Popover
|
||||||
content={
|
content={
|
||||||
@@ -119,18 +120,14 @@ export default function InvoiceFloatingActions({
|
|||||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
/>
|
/>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
{/* ----------- Save As Draft ----------- */}
|
{/* ----------- Save As Draft ----------- */}
|
||||||
|
<ButtonGroup>
|
||||||
<Button
|
<Button
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
className={'ml1'}
|
className={'ml1'}
|
||||||
type="submit"
|
type="submit"
|
||||||
onClick={(event) => {
|
onClick={handleSubmitDraftBtnClick}
|
||||||
saveInvoke(onSubmitClick, event, {
|
|
||||||
redirect: true,
|
|
||||||
publish: false,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
text={<T id={'save_as_draft'} />}
|
text={<T id={'save_as_draft'} />}
|
||||||
/>
|
/>
|
||||||
<Popover
|
<Popover
|
||||||
@@ -150,27 +147,56 @@ export default function InvoiceFloatingActions({
|
|||||||
interactionKind={PopoverInteractionKind.CLICK}
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
position={Position.BOTTOM_LEFT}
|
position={Position.BOTTOM_LEFT}
|
||||||
>
|
>
|
||||||
<Button rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />} />
|
<Button
|
||||||
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
|
/>
|
||||||
</Popover>
|
</Popover>
|
||||||
{/* ----------- Clear ----------- */}
|
</ButtonGroup>
|
||||||
|
</If>
|
||||||
|
{/* ----------- Save and New ----------- */}
|
||||||
|
<If condition={invoice && invoicePublished}>
|
||||||
|
<ButtonGroup>
|
||||||
|
<Button
|
||||||
|
disabled={isSubmitting}
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
type="submit"
|
||||||
|
onClick={handleSubmitPublishBtnClick}
|
||||||
|
text={<T id={'save'} />}
|
||||||
|
/>
|
||||||
|
<Popover
|
||||||
|
content={
|
||||||
|
<Menu>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'save_and_new'} />}
|
||||||
|
onClick={handleSubmitPublishAndNewBtnClick}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
}
|
||||||
|
minimal={true}
|
||||||
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
|
position={Position.BOTTOM_LEFT}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
|
</If>
|
||||||
|
|
||||||
|
{/* ----------- Clear & Reset----------- */}
|
||||||
<Button
|
<Button
|
||||||
className={'ml1'}
|
className={'ml1'}
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
onClick={(event) => {
|
onClick={handleClearBtnClick}
|
||||||
resetForm();
|
text={invoice ? <T id={'reset'} /> : <T id={'clear'} />}
|
||||||
saveInvoke(onClearClick, event);
|
|
||||||
}}
|
|
||||||
text={invoice && invoice.id ? <T id={'reset'} /> : <T id={'clear'} />}
|
|
||||||
/>
|
/>
|
||||||
{/* ----------- Cancel ----------- */}
|
{/* ----------- Cancel ----------- */}
|
||||||
<Button
|
<Button
|
||||||
className={'ml1'}
|
className={'ml1'}
|
||||||
onClick={(event) => {
|
onClick={handleCancelBtnClick}
|
||||||
saveInvoke(onCancelClick, event);
|
|
||||||
}}
|
|
||||||
text={<T id={'cancel'} />}
|
text={<T id={'cancel'} />}
|
||||||
/>
|
/>
|
||||||
</ButtonGroup>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,7 +186,6 @@ function InvoiceForm({
|
|||||||
intent: Intent.SUCCESS,
|
intent: Intent.SUCCESS,
|
||||||
});
|
});
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
resetForm();
|
|
||||||
|
|
||||||
if (submitPayload.redirect) {
|
if (submitPayload.redirect) {
|
||||||
history.push('/invoices');
|
history.push('/invoices');
|
||||||
@@ -260,9 +259,10 @@ function InvoiceForm({
|
|||||||
<InvoiceFormFooter />
|
<InvoiceFormFooter />
|
||||||
<InvoiceFloatingActions
|
<InvoiceFloatingActions
|
||||||
isSubmitting={isSubmitting}
|
isSubmitting={isSubmitting}
|
||||||
invoice={invoice}
|
invoice={invoiceId}
|
||||||
onCancelClick={handleCancelClick}
|
onCancelClick={handleCancelClick}
|
||||||
onSubmitClick={handleSubmitClick}
|
onSubmitClick={handleSubmitClick}
|
||||||
|
invoicePublished={true}
|
||||||
/>
|
/>
|
||||||
</Form>
|
</Form>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -46,19 +46,28 @@ export default function PaymentReceiveFormFloatingActions({
|
|||||||
onSubmitForm();
|
onSubmitForm();
|
||||||
saveInvoke(onSubmitClick, event, {
|
saveInvoke(onSubmitClick, event, {
|
||||||
redirect: false,
|
redirect: false,
|
||||||
|
resetForm: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitContinueEditingBtnClick = (event) => {
|
||||||
|
onSubmitForm();
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: false,
|
||||||
|
publish: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
||||||
<ButtonGroup>
|
|
||||||
{/* ----------- Save and New ----------- */}
|
{/* ----------- Save and New ----------- */}
|
||||||
|
<ButtonGroup>
|
||||||
<Button
|
<Button
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
type="submit"
|
type="submit"
|
||||||
onClick={handleSubmitBtnClick}
|
onClick={handleSubmitBtnClick}
|
||||||
text={paymentReceiveId ? <T id={'edit'} /> : <T id={'save_and_send'} />}
|
text={paymentReceiveId ? <T id={'edit'} /> : <T id={'save'} />}
|
||||||
/>
|
/>
|
||||||
<Popover
|
<Popover
|
||||||
content={
|
content={
|
||||||
@@ -67,6 +76,10 @@ export default function PaymentReceiveFormFloatingActions({
|
|||||||
text={<T id={'save_and_new'} />}
|
text={<T id={'save_and_new'} />}
|
||||||
onClick={handleSubmitAndNewClick}
|
onClick={handleSubmitAndNewClick}
|
||||||
/>
|
/>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'save_continue_editing'} />}
|
||||||
|
onClick={handleSubmitContinueEditingBtnClick}
|
||||||
|
/>
|
||||||
</Menu>
|
</Menu>
|
||||||
}
|
}
|
||||||
minimal={true}
|
minimal={true}
|
||||||
@@ -78,6 +91,7 @@ export default function PaymentReceiveFormFloatingActions({
|
|||||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
/>
|
/>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
{/* ----------- Clear & Reset----------- */}
|
{/* ----------- Clear & Reset----------- */}
|
||||||
<Button
|
<Button
|
||||||
className={'ml1'}
|
className={'ml1'}
|
||||||
@@ -91,7 +105,6 @@ export default function PaymentReceiveFormFloatingActions({
|
|||||||
onClick={handleCancelBtnClick}
|
onClick={handleCancelBtnClick}
|
||||||
text={<T id={'cancel'} />}
|
text={<T id={'cancel'} />}
|
||||||
/>
|
/>
|
||||||
</ButtonGroup>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,11 +190,13 @@ function PaymentReceiveForm({
|
|||||||
intent: Intent.SUCCESS,
|
intent: Intent.SUCCESS,
|
||||||
});
|
});
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
resetForm();
|
|
||||||
|
|
||||||
if (submitPayload.redirect) {
|
if (submitPayload.redirect) {
|
||||||
history.push('/payment-receives');
|
history.push('/payment-receives');
|
||||||
}
|
}
|
||||||
|
if (submitPayload.resetForm) {
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
// Handle request response errors.
|
// Handle request response errors.
|
||||||
const onError = (errors) => {
|
const onError = (errors) => {
|
||||||
|
|||||||
@@ -201,11 +201,13 @@ function ReceiptForm({
|
|||||||
intent: Intent.SUCCESS,
|
intent: Intent.SUCCESS,
|
||||||
});
|
});
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
resetForm();
|
|
||||||
|
|
||||||
if (submitPayload.redirect) {
|
if (submitPayload.redirect) {
|
||||||
history.push('/receipts');
|
history.push('/receipts');
|
||||||
}
|
}
|
||||||
|
if (submitPayload.resetForm) {
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle the request error.
|
// Handle the request error.
|
||||||
@@ -268,6 +270,7 @@ function ReceiptForm({
|
|||||||
<ReceiptFormFloatingActions
|
<ReceiptFormFloatingActions
|
||||||
isSubmitting={isSubmitting}
|
isSubmitting={isSubmitting}
|
||||||
receiptId={receiptId}
|
receiptId={receiptId}
|
||||||
|
receiptPublished={true}
|
||||||
onSubmitClick={handleSubmitClick}
|
onSubmitClick={handleSubmitClick}
|
||||||
onCancelClick={handleCancelClick}
|
onCancelClick={handleCancelClick}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { useFormikContext } from 'formik';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { CLASSES } from 'common/classes';
|
import { CLASSES } from 'common/classes';
|
||||||
import { saveInvoke } from 'utils';
|
import { saveInvoke } from 'utils';
|
||||||
import { Icon } from 'components';
|
import { If, Icon } from 'components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receipt floating actions bar.
|
* Receipt floating actions bar.
|
||||||
@@ -22,21 +22,60 @@ import { Icon } from 'components';
|
|||||||
export default function ReceiptFormFloatingActions({
|
export default function ReceiptFormFloatingActions({
|
||||||
isSubmitting,
|
isSubmitting,
|
||||||
receiptId,
|
receiptId,
|
||||||
|
receiptPublished,
|
||||||
onSubmitClick,
|
onSubmitClick,
|
||||||
onCancelClick,
|
onCancelClick,
|
||||||
onClearClick,
|
onClearClick,
|
||||||
}) {
|
}) {
|
||||||
const { resetForm, submitForm } = useFormikContext();
|
const { resetForm, submitForm } = useFormikContext();
|
||||||
|
|
||||||
const handleSubmitAndNewClick = useCallback(
|
const handleSubmitPublishBtnClick = (event) => {
|
||||||
(event) => {
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: true,
|
||||||
|
publish: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitPublishAndNewBtnClick = (event) => {
|
||||||
submitForm();
|
submitForm();
|
||||||
saveInvoke(onSubmitClick, event, {
|
saveInvoke(onSubmitClick, event, {
|
||||||
redirect: false,
|
redirect: false,
|
||||||
|
publish: true,
|
||||||
|
resetForm: true,
|
||||||
});
|
});
|
||||||
},
|
};
|
||||||
[submitForm],
|
|
||||||
);
|
const handleSubmitPublishContinueEditingBtnClick = (event) => {
|
||||||
|
submitForm();
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: false,
|
||||||
|
publish: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitDraftBtnClick = (event) => {
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: true,
|
||||||
|
publish: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitDraftAndNewBtnClick = (event) => {
|
||||||
|
submitForm();
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: false,
|
||||||
|
publish: false,
|
||||||
|
resetForm: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmitDraftContinueEditingBtnClick = (event) => {
|
||||||
|
submitForm();
|
||||||
|
saveInvoke(onSubmitClick, event, {
|
||||||
|
redirect: false,
|
||||||
|
publish: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleCancelBtnClick = (event) => {
|
const handleCancelBtnClick = (event) => {
|
||||||
saveInvoke(onCancelClick, event);
|
saveInvoke(onCancelClick, event);
|
||||||
@@ -49,25 +88,26 @@ export default function ReceiptFormFloatingActions({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
||||||
|
{/* ----------- Save And Publish ----------- */}
|
||||||
|
<If condition={!receiptId || !receiptPublished}>
|
||||||
<ButtonGroup>
|
<ButtonGroup>
|
||||||
{/* ----------- Save and New ----------- */}
|
|
||||||
<Button
|
<Button
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
type="submit"
|
type="submit"
|
||||||
onClick={(event) => {
|
onClick={handleSubmitPublishBtnClick}
|
||||||
saveInvoke(onSubmitClick, event, {
|
text={<T id={'save_publish'} />}
|
||||||
redirect: true,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
text={receiptId ? <T id={'edit'} /> : <T id={'save'} />}
|
|
||||||
/>
|
/>
|
||||||
<Popover
|
<Popover
|
||||||
content={
|
content={
|
||||||
<Menu>
|
<Menu>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
text={<T id={'save_and_new'} />}
|
text={<T id={'publish_and_new'} />}
|
||||||
onClick={handleSubmitAndNewClick}
|
onClick={handleSubmitPublishAndNewBtnClick}
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'publish_continue_editing'} />}
|
||||||
|
onClick={handleSubmitPublishContinueEditingBtnClick}
|
||||||
/>
|
/>
|
||||||
</Menu>
|
</Menu>
|
||||||
}
|
}
|
||||||
@@ -80,6 +120,69 @@ export default function ReceiptFormFloatingActions({
|
|||||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
/>
|
/>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
|
{/* ----------- Save As Draft ----------- */}
|
||||||
|
<ButtonGroup>
|
||||||
|
<Button
|
||||||
|
disabled={isSubmitting}
|
||||||
|
className={'ml1'}
|
||||||
|
type="submit"
|
||||||
|
onClick={handleSubmitDraftBtnClick}
|
||||||
|
text={<T id={'save_as_draft'} />}
|
||||||
|
/>
|
||||||
|
<Popover
|
||||||
|
content={
|
||||||
|
<Menu>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'save_and_new'} />}
|
||||||
|
onClick={handleSubmitDraftAndNewBtnClick}
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'save_continue_editing'} />}
|
||||||
|
onClick={handleSubmitDraftContinueEditingBtnClick}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
}
|
||||||
|
minimal={true}
|
||||||
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
|
position={Position.BOTTOM_LEFT}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
|
</If>
|
||||||
|
{/* ----------- Save and New ----------- */}
|
||||||
|
<If condition={receiptId && receiptPublished}>
|
||||||
|
<ButtonGroup>
|
||||||
|
<Button
|
||||||
|
disabled={isSubmitting}
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
type="submit"
|
||||||
|
onClick={handleSubmitPublishBtnClick}
|
||||||
|
text={<T id={'save'} />}
|
||||||
|
/>
|
||||||
|
<Popover
|
||||||
|
content={
|
||||||
|
<Menu>
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'save_and_new'} />}
|
||||||
|
onClick={handleSubmitPublishAndNewBtnClick}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
}
|
||||||
|
minimal={true}
|
||||||
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
|
position={Position.BOTTOM_LEFT}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
intent={Intent.PRIMARY}
|
||||||
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
|
</If>
|
||||||
{/* ----------- Clear & Reset----------- */}
|
{/* ----------- Clear & Reset----------- */}
|
||||||
<Button
|
<Button
|
||||||
className={'ml1'}
|
className={'ml1'}
|
||||||
@@ -93,7 +196,6 @@ export default function ReceiptFormFloatingActions({
|
|||||||
onClick={handleCancelBtnClick}
|
onClick={handleCancelBtnClick}
|
||||||
text={<T id={'cancel'} />}
|
text={<T id={'cancel'} />}
|
||||||
/>
|
/>
|
||||||
</ButtonGroup>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import classNames from 'classnames';
|
|||||||
import { FormGroup, ControlGroup, Position, Classes } from '@blueprintjs/core';
|
import { FormGroup, ControlGroup, Position, Classes } from '@blueprintjs/core';
|
||||||
import { DateInput } from '@blueprintjs/datetime';
|
import { DateInput } from '@blueprintjs/datetime';
|
||||||
import { FastField, ErrorMessage } from 'formik';
|
import { FastField, ErrorMessage } from 'formik';
|
||||||
|
import moment from 'moment';
|
||||||
import {
|
import {
|
||||||
MoneyInputGroup,
|
MoneyInputGroup,
|
||||||
InputPrependText,
|
InputPrependText,
|
||||||
@@ -47,6 +48,12 @@ function VendorFinanicalPanelTab({
|
|||||||
>
|
>
|
||||||
<DateInput
|
<DateInput
|
||||||
{...momentFormatter('YYYY/MM/DD')}
|
{...momentFormatter('YYYY/MM/DD')}
|
||||||
|
onChange={(date) => {
|
||||||
|
form.setFieldValue(
|
||||||
|
'opening_balance_at',
|
||||||
|
moment(date).format('YYYY-MM-DD'),
|
||||||
|
);
|
||||||
|
}}
|
||||||
value={tansformDateValue(value)}
|
value={tansformDateValue(value)}
|
||||||
popoverProps={{ position: Position.BOTTOM, minimal: true }}
|
popoverProps={{ position: Position.BOTTOM, minimal: true }}
|
||||||
disabled={vendorId}
|
disabled={vendorId}
|
||||||
@@ -56,12 +63,7 @@ function VendorFinanicalPanelTab({
|
|||||||
</FastField>
|
</FastField>
|
||||||
{/*------------ Opening balance -----------*/}
|
{/*------------ Opening balance -----------*/}
|
||||||
<FastField name={'opening_balance'}>
|
<FastField name={'opening_balance'}>
|
||||||
{({
|
{({ form, field, field: { value }, meta: { error, touched } }) => (
|
||||||
form: { values },
|
|
||||||
field,
|
|
||||||
field: { value },
|
|
||||||
meta: { error, touched },
|
|
||||||
}) => (
|
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'opening_balance'} />}
|
label={<T id={'opening_balance'} />}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
@@ -72,14 +74,15 @@ function VendorFinanicalPanelTab({
|
|||||||
inline={true}
|
inline={true}
|
||||||
>
|
>
|
||||||
<ControlGroup>
|
<ControlGroup>
|
||||||
<InputPrependText text={values.currency_code } />
|
<InputPrependText text={form.values.currency_code} />
|
||||||
<MoneyInputGroup
|
<MoneyInputGroup
|
||||||
value={value}
|
value={value}
|
||||||
onChange={field.onChange}
|
|
||||||
prefix={'$'}
|
|
||||||
inputGroupProps={{
|
inputGroupProps={{
|
||||||
fill: true,
|
fill: true,
|
||||||
...field,
|
// ...field,
|
||||||
|
}}
|
||||||
|
onChange={(balance) => {
|
||||||
|
form.setFieldValue('opening_balance', balance);
|
||||||
}}
|
}}
|
||||||
disabled={vendorId}
|
disabled={vendorId}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ export default function VendorFloatingActions({
|
|||||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||||
/>
|
/>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
</ButtonGroup>
|
||||||
{/* ----------- Clear & Reset----------- */}
|
{/* ----------- Clear & Reset----------- */}
|
||||||
<Button
|
<Button
|
||||||
className={'ml1'}
|
className={'ml1'}
|
||||||
@@ -92,7 +93,6 @@ export default function VendorFloatingActions({
|
|||||||
onClick={handleCancelBtnClick}
|
onClick={handleCancelBtnClick}
|
||||||
text={<T id={'cancel'} />}
|
text={<T id={'cancel'} />}
|
||||||
/>
|
/>
|
||||||
</ButtonGroup>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import classNames from 'classnames';
|
|||||||
import { CLASSES } from 'common/classes';
|
import { CLASSES } from 'common/classes';
|
||||||
import { inputIntent } from 'utils';
|
import { inputIntent } from 'utils';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vendor form after primary section.
|
* Vendor form after primary section.
|
||||||
*/
|
*/
|
||||||
@@ -66,7 +65,7 @@ function VendorFormAfterPrimarySection() {
|
|||||||
label={<T id={'website'} />}
|
label={<T id={'website'} />}
|
||||||
inline={true}
|
inline={true}
|
||||||
>
|
>
|
||||||
<InputGroup {...field} />
|
<InputGroup placeholder={'http://'} {...field} />
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
)}
|
)}
|
||||||
</FastField>
|
</FastField>
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ function VendorsTable({
|
|||||||
vendorsPageination,
|
vendorsPageination,
|
||||||
vendorTableQuery,
|
vendorTableQuery,
|
||||||
vendorItems,
|
vendorItems,
|
||||||
|
vendorsCurrentViewId,
|
||||||
|
|
||||||
// #withVendorsActions
|
// #withVendorsActions
|
||||||
addVendorsTableQueries,
|
addVendorsTableQueries,
|
||||||
@@ -135,7 +136,9 @@ function VendorsTable({
|
|||||||
{
|
{
|
||||||
id: 'receivable_balance',
|
id: 'receivable_balance',
|
||||||
Header: formatMessage({ id: 'receivable_balance' }),
|
Header: formatMessage({ id: 'receivable_balance' }),
|
||||||
accessor: (r) => <Money amount={r.closing_balance} currency={'USD'} />,
|
accessor: (r) => (
|
||||||
|
<Money amount={r.closing_balance} currency={r.currency_code} />
|
||||||
|
),
|
||||||
className: 'receivable_balance',
|
className: 'receivable_balance',
|
||||||
width: 100,
|
width: 100,
|
||||||
},
|
},
|
||||||
@@ -182,6 +185,10 @@ function VendorsTable({
|
|||||||
onEditVendor,
|
onEditVendor,
|
||||||
onDeleteVendor,
|
onDeleteVendor,
|
||||||
});
|
});
|
||||||
|
const showEmptyStatus = [
|
||||||
|
vendorsCurrentViewId === -1,
|
||||||
|
vendorItems.length === 0,
|
||||||
|
].every((condition) => condition === true);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(CLASSES.DASHBOARD_DATATABLE)}>
|
<div className={classNames(CLASSES.DASHBOARD_DATATABLE)}>
|
||||||
@@ -190,7 +197,7 @@ function VendorsTable({
|
|||||||
mount={false}
|
mount={false}
|
||||||
>
|
>
|
||||||
<Choose>
|
<Choose>
|
||||||
<Choose.When condition={true}>
|
<Choose.When condition={showEmptyStatus}>
|
||||||
<VendorsEmptyStatus />
|
<VendorsEmptyStatus />
|
||||||
</Choose.When>
|
</Choose.When>
|
||||||
|
|
||||||
@@ -228,11 +235,13 @@ export default compose(
|
|||||||
vendorsLoading,
|
vendorsLoading,
|
||||||
vendorTableQuery,
|
vendorTableQuery,
|
||||||
vendorsPageination,
|
vendorsPageination,
|
||||||
|
vendorsCurrentViewId,
|
||||||
}) => ({
|
}) => ({
|
||||||
vendorItems,
|
vendorItems,
|
||||||
vendorsLoading,
|
vendorsLoading,
|
||||||
vendorsPageination,
|
vendorsPageination,
|
||||||
vendorTableQuery,
|
vendorTableQuery,
|
||||||
|
vendorsCurrentViewId,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
withVendorsActions,
|
withVendorsActions,
|
||||||
|
|||||||
@@ -5,11 +5,13 @@ import {
|
|||||||
getVendorCurrentPageFactory,
|
getVendorCurrentPageFactory,
|
||||||
getVendorsTableQuery,
|
getVendorsTableQuery,
|
||||||
getVendorsPaginationMetaFactory,
|
getVendorsPaginationMetaFactory,
|
||||||
|
getVendorsCurrentViewIdFactory,
|
||||||
} from 'store/vendors/vendors.selectors';
|
} from 'store/vendors/vendors.selectors';
|
||||||
|
|
||||||
export default (mapState) => {
|
export default (mapState) => {
|
||||||
const getVendorsItems = getVendorCurrentPageFactory();
|
const getVendorsItems = getVendorCurrentPageFactory();
|
||||||
const getVendorsPaginationMeta = getVendorsPaginationMetaFactory();
|
const getVendorsPaginationMeta = getVendorsPaginationMetaFactory();
|
||||||
|
const getVendorsCurrentViewId = getVendorsCurrentViewIdFactory();
|
||||||
const mapStateToProps = (state, props) => {
|
const mapStateToProps = (state, props) => {
|
||||||
const query = getVendorsTableQuery(state, props);
|
const query = getVendorsTableQuery(state, props);
|
||||||
|
|
||||||
@@ -20,6 +22,7 @@ export default (mapState) => {
|
|||||||
vendorTableQuery: query,
|
vendorTableQuery: query,
|
||||||
vendorsPageination: getVendorsPaginationMeta(state, props, query),
|
vendorsPageination: getVendorsPaginationMeta(state, props, query),
|
||||||
vendorsLoading: state.vendors.loading,
|
vendorsLoading: state.vendors.loading,
|
||||||
|
vendorsCurrentViewId: getVendorsCurrentViewId(state, props),
|
||||||
};
|
};
|
||||||
return mapState ? mapState(mapped, state, props) : mapped;
|
return mapState ? mapState(mapped, state, props) : mapped;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ const vendorByIdSelector = (state, props) =>
|
|||||||
state.vendors.items[props.vendorId];
|
state.vendors.items[props.vendorId];
|
||||||
const vendorsItemsSelector = (state) => state.vendors.items;
|
const vendorsItemsSelector = (state) => state.vendors.items;
|
||||||
|
|
||||||
|
const vendorsCurrentViewIdSelector = (state) => state.vendors.currentViewId;
|
||||||
|
|
||||||
const vendorsPaginationSelector = (state, props) => {
|
const vendorsPaginationSelector = (state, props) => {
|
||||||
const viewId = state.vendors.currentViewId;
|
const viewId = state.vendors.currentViewId;
|
||||||
return state.vendors.views?.[viewId];
|
return state.vendors.views?.[viewId];
|
||||||
@@ -57,3 +59,8 @@ export const getVendorByIdFactory = () =>
|
|||||||
createSelector(vendorByIdSelector, (vendor) => {
|
createSelector(vendorByIdSelector, (vendor) => {
|
||||||
return vendor;
|
return vendor;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const getVendorsCurrentViewIdFactory = () =>
|
||||||
|
createSelector(vendorsCurrentViewIdSelector, (currentViewId) => {
|
||||||
|
return currentViewId;
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
import { Model } from 'objection';
|
import { Model } from "objection";
|
||||||
import TenantModel from 'models/TenantModel';
|
import TenantModel from "models/TenantModel";
|
||||||
import { viewRolesBuilder } from 'lib/ViewRolesBuilder';
|
import { viewRolesBuilder } from "lib/ViewRolesBuilder";
|
||||||
import Media from './Media';
|
import Media from "./Media";
|
||||||
|
|
||||||
export default class Expense extends TenantModel {
|
export default class Expense extends TenantModel {
|
||||||
/**
|
/**
|
||||||
* Table name
|
* Table name
|
||||||
*/
|
*/
|
||||||
static get tableName() {
|
static get tableName() {
|
||||||
return 'expenses_transactions';
|
return "expenses_transactions";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Account transaction reference type.
|
* Account transaction reference type.
|
||||||
*/
|
*/
|
||||||
static get referenceType() {
|
static get referenceType() {
|
||||||
return 'Expense';
|
return "Expense";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model timestamps.
|
* Model timestamps.
|
||||||
*/
|
*/
|
||||||
get timestamps() {
|
get timestamps() {
|
||||||
return ['createdAt', 'updatedAt'];
|
return ["createdAt", "updatedAt"];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,10 +35,17 @@ export default class Expense extends TenantModel {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static get media () {
|
static get media() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get virtualAttributes() {
|
||||||
|
return ["isPublished"];
|
||||||
|
}
|
||||||
|
isPublished() {
|
||||||
|
return Boolean(this.publishedAt);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model modifiers.
|
* Model modifiers.
|
||||||
*/
|
*/
|
||||||
@@ -46,28 +53,28 @@ export default class Expense extends TenantModel {
|
|||||||
return {
|
return {
|
||||||
filterByDateRange(query, startDate, endDate) {
|
filterByDateRange(query, startDate, endDate) {
|
||||||
if (startDate) {
|
if (startDate) {
|
||||||
query.where('date', '>=', startDate);
|
query.where("date", ">=", startDate);
|
||||||
}
|
}
|
||||||
if (endDate) {
|
if (endDate) {
|
||||||
query.where('date', '<=', endDate);
|
query.where("date", "<=", endDate);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
filterByAmountRange(query, from, to) {
|
filterByAmountRange(query, from, to) {
|
||||||
if (from) {
|
if (from) {
|
||||||
query.where('amount', '>=', from);
|
query.where("amount", ">=", from);
|
||||||
}
|
}
|
||||||
if (to) {
|
if (to) {
|
||||||
query.where('amount', '<=', to);
|
query.where("amount", "<=", to);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
filterByExpenseAccount(query, accountId) {
|
filterByExpenseAccount(query, accountId) {
|
||||||
if (accountId) {
|
if (accountId) {
|
||||||
query.where('expense_account_id', accountId);
|
query.where("expense_account_id", accountId);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
filterByPaymentAccount(query, accountId) {
|
filterByPaymentAccount(query, accountId) {
|
||||||
if (accountId) {
|
if (accountId) {
|
||||||
query.where('payment_account_id', accountId);
|
query.where("payment_account_id", accountId);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
viewRolesBuilder(query, conditionals, expression) {
|
viewRolesBuilder(query, conditionals, expression) {
|
||||||
@@ -80,41 +87,41 @@ export default class Expense extends TenantModel {
|
|||||||
* Relationship mapping.
|
* Relationship mapping.
|
||||||
*/
|
*/
|
||||||
static get relationMappings() {
|
static get relationMappings() {
|
||||||
const Account = require('models/Account');
|
const Account = require("models/Account");
|
||||||
const ExpenseCategory = require('models/ExpenseCategory');
|
const ExpenseCategory = require("models/ExpenseCategory");
|
||||||
const Media = require('models/Media');
|
const Media = require("models/Media");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
paymentAccount: {
|
paymentAccount: {
|
||||||
relation: Model.BelongsToOneRelation,
|
relation: Model.BelongsToOneRelation,
|
||||||
modelClass: Account.default,
|
modelClass: Account.default,
|
||||||
join: {
|
join: {
|
||||||
from: 'expenses_transactions.paymentAccountId',
|
from: "expenses_transactions.paymentAccountId",
|
||||||
to: 'accounts.id',
|
to: "accounts.id",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
categories: {
|
categories: {
|
||||||
relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
modelClass: ExpenseCategory.default,
|
modelClass: ExpenseCategory.default,
|
||||||
join: {
|
join: {
|
||||||
from: 'expenses_transactions.id',
|
from: "expenses_transactions.id",
|
||||||
to: 'expense_transaction_categories.expenseId',
|
to: "expense_transaction_categories.expenseId",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
media: {
|
media: {
|
||||||
relation: Model.ManyToManyRelation,
|
relation: Model.ManyToManyRelation,
|
||||||
modelClass: Media.default,
|
modelClass: Media.default,
|
||||||
join: {
|
join: {
|
||||||
from: 'expenses_transactions.id',
|
from: "expenses_transactions.id",
|
||||||
through: {
|
through: {
|
||||||
from: 'media_links.model_id',
|
from: "media_links.model_id",
|
||||||
to: 'media_links.media_id',
|
to: "media_links.media_id",
|
||||||
},
|
},
|
||||||
to: 'media.id',
|
to: "media.id",
|
||||||
},
|
},
|
||||||
filter(query) {
|
filter(query) {
|
||||||
query.where('model_name', 'Expense');
|
query.where("model_name", "Expense");
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -125,51 +132,50 @@ export default class Expense extends TenantModel {
|
|||||||
static get fields() {
|
static get fields() {
|
||||||
return {
|
return {
|
||||||
payment_date: {
|
payment_date: {
|
||||||
label: 'Payment date',
|
label: "Payment date",
|
||||||
column: 'payment_date',
|
column: "payment_date",
|
||||||
columnType: 'date',
|
columnType: "date",
|
||||||
},
|
},
|
||||||
payment_account: {
|
payment_account: {
|
||||||
label: 'Payment account',
|
label: "Payment account",
|
||||||
column: 'payment_account_id',
|
column: "payment_account_id",
|
||||||
relation: 'accounts.id',
|
relation: "accounts.id",
|
||||||
optionsResource: 'account',
|
optionsResource: "account",
|
||||||
},
|
},
|
||||||
amount: {
|
amount: {
|
||||||
label: 'Amount',
|
label: "Amount",
|
||||||
column: 'total_amount',
|
column: "total_amount",
|
||||||
columnType: 'number'
|
columnType: "number",
|
||||||
},
|
},
|
||||||
currency_code: {
|
currency_code: {
|
||||||
label: 'Currency',
|
label: "Currency",
|
||||||
column: 'currency_code',
|
column: "currency_code",
|
||||||
optionsResource: 'currency',
|
optionsResource: "currency",
|
||||||
},
|
},
|
||||||
reference_no: {
|
reference_no: {
|
||||||
label: 'Reference No.',
|
label: "Reference No.",
|
||||||
column: 'reference_no',
|
column: "reference_no",
|
||||||
columnType: 'string',
|
columnType: "string",
|
||||||
},
|
},
|
||||||
description: {
|
description: {
|
||||||
label: 'Description',
|
label: "Description",
|
||||||
column: 'description',
|
column: "description",
|
||||||
columnType: 'string',
|
columnType: "string",
|
||||||
},
|
},
|
||||||
published: {
|
published: {
|
||||||
label: 'Published',
|
label: "Published",
|
||||||
column: 'published',
|
column: "published",
|
||||||
|
|
||||||
},
|
},
|
||||||
user: {
|
user: {
|
||||||
label: 'User',
|
label: "User",
|
||||||
column: 'user_id',
|
column: "user_id",
|
||||||
relation: 'users.id',
|
relation: "users.id",
|
||||||
relationColumn: 'users.id',
|
relationColumn: "users.id",
|
||||||
},
|
},
|
||||||
created_at: {
|
created_at: {
|
||||||
label: 'Created at',
|
label: "Created at",
|
||||||
column: 'created_at',
|
column: "created_at",
|
||||||
columnType: 'date',
|
columnType: "date",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user