mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-23 00:00:31 +00:00
fix bugs.
This commit is contained in:
@@ -12,19 +12,24 @@ import Progress from 'components/NProgress/Progress';
|
|||||||
import messages from 'lang/en';
|
import messages from 'lang/en';
|
||||||
import 'style/App.scss';
|
import 'style/App.scss';
|
||||||
|
|
||||||
function App(props) {
|
function App({
|
||||||
|
isAuthorized,
|
||||||
|
locale,
|
||||||
|
}) {
|
||||||
const history = createBrowserHistory();
|
const history = createBrowserHistory();
|
||||||
|
|
||||||
|
history.listen((location, action) => {
|
||||||
|
console.log(`new location via ${action}`, location);
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IntlProvider locale={props.locale} messages={messages}>
|
<IntlProvider locale={locale} messages={messages}>
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<Authentication isAuthenticated={props.isAuthorized} />
|
<Authentication isAuthenticated={isAuthorized} />
|
||||||
<PrivateRoute isAuthenticated={props.isAuthorized} component={Dashboard} />
|
<PrivateRoute isAuthenticated={isAuthorized} component={Dashboard} />
|
||||||
</Router>
|
</Router>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Progress isAnimating={props.isLoading} />
|
|
||||||
</IntlProvider>
|
</IntlProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -33,13 +38,10 @@ App.defaultProps = {
|
|||||||
locale: 'en',
|
locale: 'en',
|
||||||
};
|
};
|
||||||
|
|
||||||
App.propTypes = {
|
const mapStateToProps = (state) => {
|
||||||
locale: PropTypes.string,
|
return {
|
||||||
isAuthorized: PropTypes.bool,
|
isAuthorized: isAuthenticated(state),
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = (state) => ({
|
|
||||||
isAuthorized: isAuthenticated(state),
|
|
||||||
isLoading: !!state.dashboard.requestsLoading,
|
|
||||||
});
|
|
||||||
export default connect(mapStateToProps)(App);
|
export default connect(mapStateToProps)(App);
|
||||||
@@ -9,7 +9,8 @@ export default function DashboardContentRoute() {
|
|||||||
<Switch>
|
<Switch>
|
||||||
{ routes.map((route, index) => (
|
{ routes.map((route, index) => (
|
||||||
<Route
|
<Route
|
||||||
key={index}
|
exact
|
||||||
|
// key={index}
|
||||||
path={`${route.path}`}
|
path={`${route.path}`}
|
||||||
component={route.component} />
|
component={route.component} />
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -15,11 +15,8 @@ function DashboardTopbarUser({ logout }) {
|
|||||||
|
|
||||||
const onClickLogout = useCallback(() => {
|
const onClickLogout = useCallback(() => {
|
||||||
logout();
|
logout();
|
||||||
|
history.go('/auth/login');
|
||||||
setTimeout(() => {
|
}, [logout, history]);
|
||||||
history.push('/auth/login');
|
|
||||||
}, 100);
|
|
||||||
}, [history, logout]);
|
|
||||||
|
|
||||||
const userAvatarDropMenu = useMemo(() => (
|
const userAvatarDropMenu = useMemo(() => (
|
||||||
<Menu>
|
<Menu>
|
||||||
|
|||||||
@@ -93,9 +93,9 @@ export default function DataTable({
|
|||||||
...(selectionColumn) ? [{
|
...(selectionColumn) ? [{
|
||||||
id: 'selection',
|
id: 'selection',
|
||||||
disableResizing: true,
|
disableResizing: true,
|
||||||
minWidth: 35,
|
minWidth: 42,
|
||||||
width: 35,
|
width: 42,
|
||||||
maxWidth: 35,
|
maxWidth: 42,
|
||||||
// The header can use the table's getToggleAllRowsSelectedProps method
|
// The header can use the table's getToggleAllRowsSelectedProps method
|
||||||
// to render a checkbox
|
// to render a checkbox
|
||||||
Header: ({ getToggleAllRowsSelectedProps }) => (
|
Header: ({ getToggleAllRowsSelectedProps }) => (
|
||||||
|
|||||||
@@ -22,15 +22,15 @@ import classNames from 'classnames';
|
|||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
import ItemCategoryConnect from 'connectors/ItemsCategory.connect';
|
import ItemCategoryConnect from 'connectors/ItemsCategory.connect';
|
||||||
import MoneyInputGroup from 'components/MoneyInputGroup';
|
import MoneyInputGroup from 'components/MoneyInputGroup';
|
||||||
|
import {useHistory} from 'react-router-dom';
|
||||||
|
|
||||||
const ItemForm = ({
|
const ItemForm = ({
|
||||||
requestSubmitItem,
|
requestSubmitItem,
|
||||||
accounts,
|
accounts,
|
||||||
categories,
|
categories,
|
||||||
categoriesList,
|
|
||||||
}) => {
|
}) => {
|
||||||
const [selectedAccounts, setSelectedAccounts] = useState({});
|
const [selectedAccounts, setSelectedAccounts] = useState({});
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
const ItemTypeDisplay = useMemo(() => ([
|
const ItemTypeDisplay = useMemo(() => ([
|
||||||
{ value: null, label: 'Select Item Type' },
|
{ value: null, label: 'Select Item Type' },
|
||||||
@@ -43,7 +43,7 @@ const ItemForm = ({
|
|||||||
active: Yup.boolean(),
|
active: Yup.boolean(),
|
||||||
name: Yup.string().required(),
|
name: Yup.string().required(),
|
||||||
type: Yup.string().trim().required(),
|
type: Yup.string().trim().required(),
|
||||||
sku: Yup.string().required(),
|
sku: Yup.string().trim(),
|
||||||
cost_price: Yup.number(),
|
cost_price: Yup.number(),
|
||||||
sell_price: Yup.number(),
|
sell_price: Yup.number(),
|
||||||
cost_account_id: Yup.number().required(),
|
cost_account_id: Yup.number().required(),
|
||||||
@@ -71,7 +71,14 @@ const ItemForm = ({
|
|||||||
note: '',
|
note: '',
|
||||||
}), []);
|
}), []);
|
||||||
|
|
||||||
const formik = useFormik({
|
const {
|
||||||
|
getFieldProps,
|
||||||
|
setFieldValue,
|
||||||
|
values,
|
||||||
|
touched,
|
||||||
|
errors,
|
||||||
|
handleSubmit,
|
||||||
|
} = useFormik({
|
||||||
enableReinitialize: true,
|
enableReinitialize: true,
|
||||||
validationSchema: validationSchema,
|
validationSchema: validationSchema,
|
||||||
initialValues: {
|
initialValues: {
|
||||||
@@ -83,13 +90,13 @@ const ItemForm = ({
|
|||||||
message: 'The_Items_has_been_Submit'
|
message: 'The_Items_has_been_Submit'
|
||||||
});
|
});
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
|
history.push('/dashboard/items');
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const {errors, values, touched} = useMemo(() => formik, [formik]);
|
|
||||||
|
|
||||||
const accountItem = useCallback((item, { handleClick }) => (
|
const accountItem = useCallback((item, { handleClick }) => (
|
||||||
<MenuItem key={item.id} text={item.name} label={item.code} onClick={handleClick} />
|
<MenuItem key={item.id} text={item.name} label={item.code} onClick={handleClick} />
|
||||||
@@ -112,9 +119,9 @@ const ItemForm = ({
|
|||||||
...selectedAccounts,
|
...selectedAccounts,
|
||||||
[filedName]: account
|
[filedName]: account
|
||||||
});
|
});
|
||||||
formik.setFieldValue(filedName, account.id);
|
setFieldValue(filedName, account.id);
|
||||||
};
|
};
|
||||||
}, [formik, selectedAccounts]);
|
}, [setFieldValue, selectedAccounts]);
|
||||||
|
|
||||||
const categoryItem = useCallback((item, { handleClick }) => (
|
const categoryItem = useCallback((item, { handleClick }) => (
|
||||||
<MenuItem text={item.name} onClick={handleClick} />
|
<MenuItem text={item.name} onClick={handleClick} />
|
||||||
@@ -129,12 +136,12 @@ const ItemForm = ({
|
|||||||
const infoIcon = useMemo(() => (<Icon icon="info-circle" iconSize={12} />), []);
|
const infoIcon = useMemo(() => (<Icon icon="info-circle" iconSize={12} />), []);
|
||||||
|
|
||||||
const handleMoneyInputChange = (fieldKey) => (e, value) => {
|
const handleMoneyInputChange = (fieldKey) => (e, value) => {
|
||||||
formik.setFieldValue(fieldKey, value);
|
setFieldValue(fieldKey, value);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class='item-form'>
|
<div class='item-form'>
|
||||||
<form onSubmit={formik.handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<div class="item-form__primary-section">
|
<div class="item-form__primary-section">
|
||||||
<FormGroup
|
<FormGroup
|
||||||
medium={true}
|
medium={true}
|
||||||
@@ -142,13 +149,13 @@ const ItemForm = ({
|
|||||||
labelInfo={requiredSpan}
|
labelInfo={requiredSpan}
|
||||||
className={'form-group--item-type'}
|
className={'form-group--item-type'}
|
||||||
intent={(errors.type && touched.type) && Intent.DANGER}
|
intent={(errors.type && touched.type) && Intent.DANGER}
|
||||||
helperText={<ErrorMessage {...formik} name="type" />}
|
helperText={<ErrorMessage {...{errors, touched}} name="type" />}
|
||||||
inline={true}
|
inline={true}
|
||||||
>
|
>
|
||||||
<HTMLSelect
|
<HTMLSelect
|
||||||
fill={true}
|
fill={true}
|
||||||
options={ItemTypeDisplay}
|
options={ItemTypeDisplay}
|
||||||
{...formik.getFieldProps('type')}
|
{...getFieldProps('type')}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
@@ -157,13 +164,13 @@ const ItemForm = ({
|
|||||||
labelInfo={requiredSpan}
|
labelInfo={requiredSpan}
|
||||||
className={'form-group--item-name'}
|
className={'form-group--item-name'}
|
||||||
intent={(errors.name && touched.name) && Intent.DANGER}
|
intent={(errors.name && touched.name) && Intent.DANGER}
|
||||||
helperText={<ErrorMessage {...formik} name="name" />}
|
helperText={<ErrorMessage {...{errors, touched}} name="name" />}
|
||||||
inline={true}
|
inline={true}
|
||||||
>
|
>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
medium={true}
|
medium={true}
|
||||||
intent={(errors.name && touched.name) && Intent.DANGER}
|
intent={(errors.name && touched.name) && Intent.DANGER}
|
||||||
{...formik.getFieldProps('name')}
|
{...getFieldProps('name')}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
@@ -172,13 +179,13 @@ const ItemForm = ({
|
|||||||
labelInfo={infoIcon}
|
labelInfo={infoIcon}
|
||||||
className={'form-group--item-sku'}
|
className={'form-group--item-sku'}
|
||||||
intent={(errors.sku && touched.sku) && Intent.DANGER}
|
intent={(errors.sku && touched.sku) && Intent.DANGER}
|
||||||
helperText={<ErrorMessage {...formik} name="sku" />}
|
helperText={<ErrorMessage {...{errors, touched}} name="sku" />}
|
||||||
inline={true}
|
inline={true}
|
||||||
>
|
>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
medium={true}
|
medium={true}
|
||||||
intent={(errors.sku && touched.sku) && Intent.DANGER}
|
intent={(errors.sku && touched.sku) && Intent.DANGER}
|
||||||
{...formik.getFieldProps('sku')}
|
{...getFieldProps('sku')}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
@@ -187,7 +194,7 @@ const ItemForm = ({
|
|||||||
labelInfo={infoIcon}
|
labelInfo={infoIcon}
|
||||||
inline={true}
|
inline={true}
|
||||||
intent={(errors.category_id && touched.category_id) && Intent.DANGER}
|
intent={(errors.category_id && touched.category_id) && Intent.DANGER}
|
||||||
helperText={<ErrorMessage {...formik} name="category" />}
|
helperText={<ErrorMessage {...{errors, touched}} name="category" />}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'form-group--select-list',
|
'form-group--select-list',
|
||||||
'form-group--category',
|
'form-group--category',
|
||||||
@@ -195,7 +202,7 @@ const ItemForm = ({
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
items={categoriesList}
|
items={categories}
|
||||||
itemRenderer={categoryItem}
|
itemRenderer={categoryItem}
|
||||||
itemPredicate={filterAccounts}
|
itemPredicate={filterAccounts}
|
||||||
popoverProps={{ minimal: true }}
|
popoverProps={{ minimal: true }}
|
||||||
@@ -218,7 +225,7 @@ const ItemForm = ({
|
|||||||
inline={true}
|
inline={true}
|
||||||
label={'Active'}
|
label={'Active'}
|
||||||
defaultChecked={values.active}
|
defaultChecked={values.active}
|
||||||
{...formik.getFieldProps('active')}
|
{...getFieldProps('active')}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</div>
|
</div>
|
||||||
@@ -231,7 +238,7 @@ const ItemForm = ({
|
|||||||
label={'Selling Price'}
|
label={'Selling Price'}
|
||||||
className={'form-group--item-selling-price'}
|
className={'form-group--item-selling-price'}
|
||||||
intent={(errors.selling_price && touched.selling_price) && Intent.DANGER}
|
intent={(errors.selling_price && touched.selling_price) && Intent.DANGER}
|
||||||
helperText={<ErrorMessage {...formik} name="selling_price" />}
|
helperText={<ErrorMessage {...{errors, touched}} name="selling_price" />}
|
||||||
inline={true}
|
inline={true}
|
||||||
>
|
>
|
||||||
<MoneyInputGroup
|
<MoneyInputGroup
|
||||||
@@ -249,7 +256,7 @@ const ItemForm = ({
|
|||||||
labelInfo={infoIcon}
|
labelInfo={infoIcon}
|
||||||
inline={true}
|
inline={true}
|
||||||
intent={(errors.sell_account_id && touched.sell_account_id) && Intent.DANGER}
|
intent={(errors.sell_account_id && touched.sell_account_id) && Intent.DANGER}
|
||||||
helperText={<ErrorMessage {...formik} name="sell_account_id" />}
|
helperText={<ErrorMessage {...{errors, touched}} name="sell_account_id" />}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'form-group--sell-account',
|
'form-group--sell-account',
|
||||||
'form-group--select-list',
|
'form-group--select-list',
|
||||||
@@ -280,7 +287,7 @@ const ItemForm = ({
|
|||||||
label={'Cost Price'}
|
label={'Cost Price'}
|
||||||
className={'form-group--item-cost-price'}
|
className={'form-group--item-cost-price'}
|
||||||
intent={(errors.cost_price && touched.cost_price) && Intent.DANGER}
|
intent={(errors.cost_price && touched.cost_price) && Intent.DANGER}
|
||||||
helperText={<ErrorMessage {...formik} name="cost_price" />}
|
helperText={<ErrorMessage {...{errors, touched}} name="cost_price" />}
|
||||||
inline={true}
|
inline={true}
|
||||||
>
|
>
|
||||||
<MoneyInputGroup
|
<MoneyInputGroup
|
||||||
@@ -298,7 +305,7 @@ const ItemForm = ({
|
|||||||
labelInfo={infoIcon}
|
labelInfo={infoIcon}
|
||||||
inline={true}
|
inline={true}
|
||||||
intent={(errors.cost_account_id && touched.cost_account_id) && Intent.DANGER}
|
intent={(errors.cost_account_id && touched.cost_account_id) && Intent.DANGER}
|
||||||
helperText={<ErrorMessage {...formik} name="cost_account_id" />}
|
helperText={<ErrorMessage {...{errors, touched}} name="cost_account_id" />}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'form-group--cost-account',
|
'form-group--cost-account',
|
||||||
'form-group--select-list',
|
'form-group--select-list',
|
||||||
@@ -331,7 +338,7 @@ const ItemForm = ({
|
|||||||
label={'Inventory Account'}
|
label={'Inventory Account'}
|
||||||
inline={true}
|
inline={true}
|
||||||
intent={(errors.inventory_account_id && touched.inventory_account_id) && Intent.DANGER}
|
intent={(errors.inventory_account_id && touched.inventory_account_id) && Intent.DANGER}
|
||||||
helperText={<ErrorMessage {...formik} name="inventory_account_id" />}
|
helperText={<ErrorMessage {...{errors, touched}} name="inventory_account_id" />}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'form-group--item-inventory_account',
|
'form-group--item-inventory_account',
|
||||||
'form-group--select-list',
|
'form-group--select-list',
|
||||||
@@ -361,8 +368,8 @@ const ItemForm = ({
|
|||||||
>
|
>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
medium={true}
|
medium={true}
|
||||||
intent={formik.errors.stock && Intent.DANGER}
|
intent={errors.stock && Intent.DANGER}
|
||||||
{...formik.getFieldProps('stock')}
|
{...getFieldProps('stock')}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useCallback, useState, useMemo } from 'react';
|
import React, { useCallback, useMemo } from 'react';
|
||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
import ItemsCategoryConnect from 'connectors/ItemsCategory.connect';
|
import ItemsCategoryConnect from 'connectors/ItemsCategory.connect';
|
||||||
import DialogConnect from 'connectors/Dialog.connector';
|
import DialogConnect from 'connectors/Dialog.connector';
|
||||||
@@ -11,8 +11,6 @@ import {
|
|||||||
Menu,
|
Menu,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
Position,
|
Position,
|
||||||
Classes,
|
|
||||||
Tooltip,
|
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
|
|
||||||
const ItemsCategoryList = ({
|
const ItemsCategoryList = ({
|
||||||
@@ -22,6 +20,7 @@ const ItemsCategoryList = ({
|
|||||||
onEditCategory,
|
onEditCategory,
|
||||||
openDialog,
|
openDialog,
|
||||||
count,
|
count,
|
||||||
|
onSelectedRowsChange,
|
||||||
}) => {
|
}) => {
|
||||||
const handelEditCategory = (category) => () => {
|
const handelEditCategory = (category) => () => {
|
||||||
openDialog('item-form', { action: 'edit', id: category.id });
|
openDialog('item-form', { action: 'edit', id: category.id });
|
||||||
@@ -42,51 +41,51 @@ const ItemsCategoryList = ({
|
|||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
|
|
||||||
const columns = useMemo(
|
const columns = useMemo(() => [
|
||||||
() => [
|
{
|
||||||
{
|
id: 'name',
|
||||||
id: 'name',
|
Header: 'Category Name',
|
||||||
Header: 'Category Name',
|
accessor: 'name',
|
||||||
accessor: 'name',
|
width: 150,
|
||||||
width: 150,
|
},
|
||||||
},
|
{
|
||||||
{
|
id: 'description',
|
||||||
id: 'description',
|
Header: 'Description',
|
||||||
Header: 'Description',
|
accessor: 'description',
|
||||||
accessor: 'description',
|
className: 'description',
|
||||||
className: 'description',
|
width: 150,
|
||||||
width: 150,
|
},
|
||||||
},
|
{
|
||||||
{
|
id: 'count',
|
||||||
id: 'count',
|
Header: 'Count',
|
||||||
Header: 'Count',
|
accessor: (r) => r.count || '',
|
||||||
accessor: () => <span>{count}</span>,
|
className: 'count',
|
||||||
className: 'count',
|
width: 50,
|
||||||
width: 50,
|
},
|
||||||
},
|
{
|
||||||
{
|
id: 'actions',
|
||||||
id: 'actions',
|
Header: '',
|
||||||
Header: '',
|
Cell: ({ cell }) => (
|
||||||
Cell: ({ cell }) => (
|
<Popover
|
||||||
<Popover
|
content={actionMenuList(cell.row.original)}
|
||||||
content={actionMenuList(cell.row.original)}
|
position={Position.RIGHT_BOTTOM}
|
||||||
position={Position.RIGHT_BOTTOM}
|
>
|
||||||
>
|
<Button icon={<Icon icon='ellipsis-h' />} />
|
||||||
<Button icon={<Icon icon='ellipsis-h' />} />
|
</Popover>
|
||||||
</Popover>
|
),
|
||||||
),
|
className: 'actions',
|
||||||
className: 'actions',
|
width: 50,
|
||||||
width: 50,
|
disableResizing: false
|
||||||
// canResize: false
|
},
|
||||||
},
|
], [actionMenuList]);
|
||||||
],
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handelFetchData = useCallback(() => {
|
const handelFetchData = useCallback(() => {
|
||||||
onFetchData && onFetchData();
|
onFetchData && onFetchData();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const handleSelectedRowsChange = useCallback((selectedRows) => {
|
||||||
|
onSelectedRowsChange && onSelectedRowsChange(selectedRows.map(s => s.original));
|
||||||
|
}, [onSelectedRowsChange]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LoadingIndicator spinnerSize={30}>
|
<LoadingIndicator spinnerSize={30}>
|
||||||
@@ -97,10 +96,13 @@ const ItemsCategoryList = ({
|
|||||||
manualSortBy={true}
|
manualSortBy={true}
|
||||||
selectionColumn={true}
|
selectionColumn={true}
|
||||||
expandable={true}
|
expandable={true}
|
||||||
treeGraph={true}
|
onSelectedRowsChange={handleSelectedRowsChange}
|
||||||
/>
|
/>
|
||||||
</LoadingIndicator>
|
</LoadingIndicator>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default compose(DialogConnect, ItemsCategoryConnect)(ItemsCategoryList);
|
export default compose(
|
||||||
|
DialogConnect,
|
||||||
|
ItemsCategoryConnect,
|
||||||
|
)(ItemsCategoryList);
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ function ManualJournalActionsBar({
|
|||||||
views,
|
views,
|
||||||
getResourceFields,
|
getResourceFields,
|
||||||
addManualJournalsTableQueries,
|
addManualJournalsTableQueries,
|
||||||
onFilterChanged
|
onFilterChanged,
|
||||||
|
selectedRows,
|
||||||
|
onBulkDelete
|
||||||
}) {
|
}) {
|
||||||
const { path } = useRouteMatch();
|
const { path } = useRouteMatch();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@@ -50,6 +52,13 @@ function ManualJournalActionsBar({
|
|||||||
onFilterChanged && onFilterChanged(filterConditions);
|
onFilterChanged && onFilterChanged(filterConditions);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
const hasSelectedRows = useMemo(() => selectedRows.length > 0, [selectedRows]);
|
||||||
|
|
||||||
|
// Handle delete button click.
|
||||||
|
const handleBulkDelete = useCallback(() => {
|
||||||
|
onBulkDelete && onBulkDelete(selectedRows.map(r => r.id));
|
||||||
|
}, [onBulkDelete, selectedRows]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
<NavbarGroup>
|
<NavbarGroup>
|
||||||
@@ -85,12 +94,13 @@ function ManualJournalActionsBar({
|
|||||||
/>
|
/>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|
||||||
{ (false) && (
|
{(hasSelectedRows) && (
|
||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
icon={<Icon icon='trash' iconSize={15} />}
|
icon={<Icon icon='trash' iconSize={15} />}
|
||||||
text='Delete'
|
text='Delete'
|
||||||
intent={Intent.DANGER}
|
intent={Intent.DANGER}
|
||||||
|
onClick={handleBulkDelete}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
MenuDivider,
|
MenuDivider,
|
||||||
Position,
|
Position,
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
import { useParams, useHistory } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
@@ -16,7 +16,7 @@ import ManualJournalsConnect from 'connectors/ManualJournals.connect';
|
|||||||
import DialogConnect from 'connectors/Dialog.connector';
|
import DialogConnect from 'connectors/Dialog.connector';
|
||||||
import DashboardConnect from 'connectors/Dashboard.connector';
|
import DashboardConnect from 'connectors/Dashboard.connector';
|
||||||
import ViewConnect from 'connectors/View.connector';
|
import ViewConnect from 'connectors/View.connector';
|
||||||
import LoadingIndicator from 'components/LoadingIndicator';
|
import { useUpdateEffect } from 'hooks';
|
||||||
import DataTable from 'components/DataTable';
|
import DataTable from 'components/DataTable';
|
||||||
import Money from 'components/Money';
|
import Money from 'components/Money';
|
||||||
|
|
||||||
@@ -31,8 +31,16 @@ function ManualJournalsDataTable({
|
|||||||
onEditJournal,
|
onEditJournal,
|
||||||
onDeleteJournal,
|
onDeleteJournal,
|
||||||
onPublishJournal,
|
onPublishJournal,
|
||||||
|
onSelectedRowsChange,
|
||||||
}) {
|
}) {
|
||||||
const { custom_view_id: customViewId } = useParams();
|
const { custom_view_id: customViewId } = useParams();
|
||||||
|
const [initialMount, setInitialMount] = useState(false);
|
||||||
|
|
||||||
|
useUpdateEffect(() => {
|
||||||
|
if (!manualJournalsLoading) {
|
||||||
|
setInitialMount(true);
|
||||||
|
}
|
||||||
|
}, [manualJournalsLoading, setInitialMount]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const viewMeta = getViewItem(customViewId);
|
const viewMeta = getViewItem(customViewId);
|
||||||
@@ -42,7 +50,25 @@ function ManualJournalsDataTable({
|
|||||||
setTopbarEditView(customViewId);
|
setTopbarEditView(customViewId);
|
||||||
}
|
}
|
||||||
changePageSubtitle(customViewId && viewMeta ? viewMeta.name : '');
|
changePageSubtitle(customViewId && viewMeta ? viewMeta.name : '');
|
||||||
}, [customViewId]);
|
}, [
|
||||||
|
customViewId,
|
||||||
|
changeCurrentView,
|
||||||
|
changePageSubtitle,
|
||||||
|
setTopbarEditView,
|
||||||
|
getViewItem,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const handlePublishJournal = useCallback((journal) => () => {
|
||||||
|
onPublishJournal && onPublishJournal(journal);
|
||||||
|
}, [onPublishJournal]);
|
||||||
|
|
||||||
|
const handleEditJournal = useCallback((journal) => () => {
|
||||||
|
onEditJournal && onEditJournal(journal);
|
||||||
|
}, [onEditJournal]);
|
||||||
|
|
||||||
|
const handleDeleteJournal = useCallback((journal) => () => {
|
||||||
|
onDeleteJournal && onDeleteJournal(journal);
|
||||||
|
}, [onDeleteJournal]);
|
||||||
|
|
||||||
const actionMenuList = (journal) => (
|
const actionMenuList = (journal) => (
|
||||||
<Menu>
|
<Menu>
|
||||||
@@ -51,21 +77,15 @@ function ManualJournalsDataTable({
|
|||||||
{!journal.status && (
|
{!journal.status && (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
text="Publish Journal"
|
text="Publish Journal"
|
||||||
onClick={() => {
|
onClick={handlePublishJournal(journal)} />
|
||||||
onPublishJournal && onPublishJournal(journal);
|
|
||||||
}} />
|
|
||||||
)}
|
)}
|
||||||
<MenuItem
|
<MenuItem
|
||||||
text='Edit Journal'
|
text='Edit Journal'
|
||||||
onClick={() => {
|
onClick={handleEditJournal(journal)} />
|
||||||
onEditJournal && onEditJournal(journal);
|
|
||||||
}} />
|
|
||||||
<MenuItem
|
<MenuItem
|
||||||
text='Delete Journal'
|
text='Delete Journal'
|
||||||
intent={Intent.DANGER}
|
intent={Intent.DANGER}
|
||||||
onClick={() => {
|
onClick={handleDeleteJournal(journal)} />
|
||||||
onDeleteJournal && onDeleteJournal(journal);
|
|
||||||
}} />
|
|
||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -143,26 +163,25 @@ function ManualJournalsDataTable({
|
|||||||
},
|
},
|
||||||
], []);
|
], []);
|
||||||
|
|
||||||
const handleDataTableFetchData = useCallback(() => {
|
const handleDataTableFetchData = useCallback((...args) => {
|
||||||
onFetchData && onFetchData();
|
onFetchData && onFetchData(...args);
|
||||||
}, [onFetchData]);
|
}, [onFetchData]);
|
||||||
|
|
||||||
const selectionColumn = useMemo(() => ({
|
const handleSelectedRowsChange = useCallback((selectedRows) => {
|
||||||
minWidth: 42,
|
onSelectedRowsChange && onSelectedRowsChange(selectedRows.map(s => s.original));
|
||||||
width: 42,
|
}, [onSelectedRowsChange]);
|
||||||
maxWidth: 42,
|
|
||||||
}), []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LoadingIndicator loading={manualJournalsLoading} spinnerSize={30}>
|
<DataTable
|
||||||
<DataTable
|
columns={columns}
|
||||||
columns={columns}
|
data={manualJournals}
|
||||||
data={manualJournals}
|
onFetchData={handleDataTableFetchData}
|
||||||
onFetchData={handleDataTableFetchData}
|
manualSortBy={true}
|
||||||
manualSortBy={true}
|
selectionColumn={true}
|
||||||
selectionColumn={selectionColumn}
|
noInitialFetch={true}
|
||||||
/>
|
loading={manualJournalsLoading && !initialMount}
|
||||||
</LoadingIndicator>
|
onSelectedRowsChange={handleSelectedRowsChange}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
18
client/src/components/NProgress/AppProgress.js
Normal file
18
client/src/components/NProgress/AppProgress.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import {connect} from 'react-redux';
|
||||||
|
import Progress from './Progress';
|
||||||
|
|
||||||
|
function AppProgress({
|
||||||
|
isAnimating,
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Progress isAnimating={isAnimating} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => ({
|
||||||
|
isAnimating: state.dashboard.requestsLoading > 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(mapStateToProps)(AppProgress);
|
||||||
@@ -21,8 +21,11 @@ export default function SidebarMenu() {
|
|||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
(item.divider) ?
|
(item.divider) ?
|
||||||
<MenuDivider title={item.title} /> :
|
<MenuDivider
|
||||||
|
key={index}
|
||||||
|
title={item.title} /> :
|
||||||
<MenuItem
|
<MenuItem
|
||||||
|
key={index}
|
||||||
active={isActive}
|
active={isActive}
|
||||||
icon={<Icon icon={item.icon} iconSize={item.iconSize} />}
|
icon={<Icon icon={item.icon} iconSize={item.iconSize} />}
|
||||||
text={item.text}
|
text={item.text}
|
||||||
|
|||||||
@@ -21,8 +21,10 @@ export const mapStateToProps = (state, props) => {
|
|||||||
return {
|
return {
|
||||||
views: getResourceViews(state, 'items'),
|
views: getResourceViews(state, 'items'),
|
||||||
currentPageItems: getCurrentPageResults(
|
currentPageItems: getCurrentPageResults(
|
||||||
state.items.items, viewPages, state.items.currentPage),
|
state.items.items,
|
||||||
|
viewPages,
|
||||||
|
state.items.currentPage,
|
||||||
|
),
|
||||||
bulkSelected: state.items.bulkActions,
|
bulkSelected: state.items.bulkActions,
|
||||||
itemsTableLoading: state.items.loading,
|
itemsTableLoading: state.items.loading,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,8 +12,7 @@ export const mapStateToProps = (state, props) => {
|
|||||||
const dialogPayload = getDialogPayload(state, 'item-form');
|
const dialogPayload = getDialogPayload(state, 'item-form');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
categories: state.itemCategories.categories,
|
categories: Object.values(state.itemCategories.categories),
|
||||||
count: 1,
|
|
||||||
name: 'item-form',
|
name: 'item-form',
|
||||||
payload: { action: 'new', id: null },
|
payload: { action: 'new', id: null },
|
||||||
editItemCategory:
|
editItemCategory:
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
deleteManualJournal,
|
deleteManualJournal,
|
||||||
fetchManualJournalsTable,
|
fetchManualJournalsTable,
|
||||||
publishManualJournal,
|
publishManualJournal,
|
||||||
|
deleteBulkManualJournals,
|
||||||
} from 'store/manualJournals/manualJournals.actions';
|
} from 'store/manualJournals/manualJournals.actions';
|
||||||
import { getResourceViews } from 'store/customViews/customViews.selectors';
|
import { getResourceViews } from 'store/customViews/customViews.selectors';
|
||||||
import t from 'store/types';
|
import t from 'store/types';
|
||||||
@@ -26,14 +27,14 @@ const mapActionsToProps = (dispatch) => ({
|
|||||||
}),
|
}),
|
||||||
addManualJournalsTableQueries: (queries) =>
|
addManualJournalsTableQueries: (queries) =>
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'MANUAL_JOURNALS_TABLE_QUERIES_ADD',
|
type: t.MANUAL_JOURNALS_TABLE_QUERIES_ADD,
|
||||||
queries,
|
queries,
|
||||||
}),
|
}),
|
||||||
fetchManualJournalsTable: (query = {}) =>
|
fetchManualJournalsTable: (query = {}) =>
|
||||||
dispatch(fetchManualJournalsTable({ query: { ...query } })),
|
dispatch(fetchManualJournalsTable({ query: { ...query } })),
|
||||||
|
|
||||||
requestPublishManualJournal: (id) =>
|
requestPublishManualJournal: (id) => dispatch(publishManualJournal({ id })),
|
||||||
dispatch(publishManualJournal({ id })),
|
requestDeleteBulkManualJournals: (ids) => dispatch(deleteBulkManualJournals({ ids })),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapActionsToProps);
|
export default connect(mapStateToProps, mapActionsToProps);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
FormGroup,
|
FormGroup,
|
||||||
} from "@blueprintjs/core";
|
} from "@blueprintjs/core";
|
||||||
import login from 'store/authentication/authentication.actions';
|
import login from 'store/authentication/authentication.actions';
|
||||||
import {hasErrorType, isAuthenticated} from 'store/authentication/authentication.reducer';
|
import {hasErrorType} from 'store/authentication/authentication.reducer';
|
||||||
import AuthenticationToaster from 'components/AppToaster';
|
import AuthenticationToaster from 'components/AppToaster';
|
||||||
import t from 'store/types';
|
import t from 'store/types';
|
||||||
|
|
||||||
@@ -21,9 +21,6 @@ const ERRORS_TYPES = {
|
|||||||
};
|
};
|
||||||
function Login({
|
function Login({
|
||||||
login,
|
login,
|
||||||
errors,
|
|
||||||
clearErrors,
|
|
||||||
hasError,
|
|
||||||
}) {
|
}) {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@@ -51,36 +48,29 @@ function Login({
|
|||||||
login({
|
login({
|
||||||
crediential: values.crediential,
|
crediential: values.crediential,
|
||||||
password: values.password,
|
password: values.password,
|
||||||
|
}).then(() => {
|
||||||
|
history.go('/dashboard/homepage');
|
||||||
|
}).catch((errors) => {
|
||||||
|
const toastBuilders = [];
|
||||||
|
if (errors.find((e) => e.type === ERRORS_TYPES.INVALID_DETAILS)) {
|
||||||
|
toastBuilders.push({
|
||||||
|
message: intl.formatMessage({ id: 'invalid_email_or_phone_numner' }),
|
||||||
|
intent: Intent.WARNING,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (errors.find((e) => e.type === ERRORS_TYPES.USER_INACTIVE)) {
|
||||||
|
toastBuilders.push({
|
||||||
|
message: intl.formatMessage({ id: 'the_user_has_been_suspended_from_admin' }),
|
||||||
|
intent: Intent.WARNING,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
toastBuilders.forEach(builder => {
|
||||||
|
AuthenticationToaster.show(builder);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const toastBuilders = [];
|
|
||||||
if (hasError(ERRORS_TYPES.INVALID_DETAILS)) {
|
|
||||||
toastBuilders.push({
|
|
||||||
message: intl.formatMessage({ id: 'invalid_email_or_phone_numner' }),
|
|
||||||
intent: Intent.WARNING,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (hasError(ERRORS_TYPES.USER_INACTIVE)) {
|
|
||||||
toastBuilders.push({
|
|
||||||
message: intl.formatMessage({ id: 'the_user_has_been_suspended_from_admin' }),
|
|
||||||
intent: Intent.WARNING,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
toastBuilders.forEach(builder => {
|
|
||||||
AuthenticationToaster.show(builder);
|
|
||||||
});
|
|
||||||
}, [hasError, intl]);
|
|
||||||
|
|
||||||
// Handle unmount component
|
|
||||||
useEffect(() => () => {
|
|
||||||
if (errors.length > 0) {
|
|
||||||
clearErrors();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="login-page">
|
<div className="login-page">
|
||||||
<form onSubmit={formik.handleSubmit}>
|
<form onSubmit={formik.handleSubmit}>
|
||||||
|
|||||||
@@ -12,17 +12,17 @@ import moment from 'moment';
|
|||||||
import {momentFormatter} from 'utils';
|
import {momentFormatter} from 'utils';
|
||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
import CurrenciesSelectList from 'components/CurrenciesSelectList';
|
import CurrenciesSelectList from 'components/CurrenciesSelectList';
|
||||||
|
import ErrorMessage from 'components/ErrorMessage';
|
||||||
|
|
||||||
export default function MakeJournalEntriesHeader({
|
export default function MakeJournalEntriesHeader({
|
||||||
formik
|
formik: { errors, touched, setFieldValue, getFieldProps }
|
||||||
}) {
|
}) {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const handleDateChange = useCallback((date) => {
|
const handleDateChange = useCallback((date) => {
|
||||||
const formatted = moment(date).format('YYYY-MM-DD');
|
const formatted = moment(date).format('YYYY-MM-DD');
|
||||||
formik.setFieldValue('date', formatted);
|
setFieldValue('date', formatted);
|
||||||
}, [formik]);
|
}, [setFieldValue]);
|
||||||
|
|
||||||
const infoIcon = useMemo(() =>
|
const infoIcon = useMemo(() =>
|
||||||
(<Icon icon="info-circle" iconSize={12} />), []);
|
(<Icon icon="info-circle" iconSize={12} />), []);
|
||||||
@@ -35,22 +35,22 @@ export default function MakeJournalEntriesHeader({
|
|||||||
label={'Journal number'}
|
label={'Journal number'}
|
||||||
labelInfo={infoIcon}
|
labelInfo={infoIcon}
|
||||||
className={'form-group--journal-number'}
|
className={'form-group--journal-number'}
|
||||||
intent={formik.errors.journal_number && Intent.DANGER}
|
intent={(errors.journal_number && touched.journal_number) && Intent.DANGER}
|
||||||
helperText={formik.errors.journal_number && formik.errors.journal_number}
|
helperText={<ErrorMessage name="journal_number" {...{errors, touched}} />}
|
||||||
fill={true}>
|
fill={true}>
|
||||||
|
|
||||||
<InputGroup
|
<InputGroup
|
||||||
intent={formik.errors.journal_number && Intent.DANGER}
|
intent={(errors.journal_number && touched.journal_number) && Intent.DANGER}
|
||||||
fill={true}
|
fill={true}
|
||||||
{...formik.getFieldProps('journal_number')} />
|
{...getFieldProps('journal_number')} />
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col sm={2}>
|
<Col sm={2}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={intl.formatMessage({'id': 'date'})}
|
label={intl.formatMessage({'id': 'date'})}
|
||||||
intent={formik.errors.date && Intent.DANGER}
|
intent={(errors.date && touched.date) && Intent.DANGER}
|
||||||
helperText={formik.errors.date && formik.errors.date}
|
helperText={<ErrorMessage name="date" {...{errors, touched}} />}
|
||||||
minimal={true}>
|
minimal={true}>
|
||||||
|
|
||||||
<DateInput
|
<DateInput
|
||||||
@@ -65,14 +65,14 @@ export default function MakeJournalEntriesHeader({
|
|||||||
<FormGroup
|
<FormGroup
|
||||||
label={intl.formatMessage({'id': 'description'})}
|
label={intl.formatMessage({'id': 'description'})}
|
||||||
className={'form-group--description'}
|
className={'form-group--description'}
|
||||||
intent={formik.errors.name && Intent.DANGER}
|
intent={(errors.name && touched.name) && Intent.DANGER}
|
||||||
helperText={formik.errors.name && formik.errors.label}
|
helperText={<ErrorMessage name="description" {...{errors, touched}} />}
|
||||||
fill={true}>
|
fill={true}>
|
||||||
|
|
||||||
<InputGroup
|
<InputGroup
|
||||||
intent={formik.errors.name && Intent.DANGER}
|
intent={(errors.name && touched.name) && Intent.DANGER}
|
||||||
fill={true}
|
fill={true}
|
||||||
{...formik.getFieldProps('description')} />
|
{...getFieldProps('description')} />
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
@@ -83,14 +83,14 @@ export default function MakeJournalEntriesHeader({
|
|||||||
label={'Reference'}
|
label={'Reference'}
|
||||||
labelInfo={infoIcon}
|
labelInfo={infoIcon}
|
||||||
className={'form-group--reference'}
|
className={'form-group--reference'}
|
||||||
intent={formik.errors.reference && Intent.DANGER}
|
intent={(errors.reference && touched.reference) && Intent.DANGER}
|
||||||
helperText={formik.errors.reference && formik.errors.reference}
|
helperText={<ErrorMessage name="reference" {...{errors, touched}} />}
|
||||||
fill={true}>
|
fill={true}>
|
||||||
|
|
||||||
<InputGroup
|
<InputGroup
|
||||||
intent={formik.errors.reference && Intent.DANGER}
|
intent={(errors.reference && touched.reference) && Intent.DANGER}
|
||||||
fill={true}
|
fill={true}
|
||||||
{...formik.getFieldProps('reference')} />
|
{...getFieldProps('reference')} />
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, {useMemo, useCallback} from 'react';
|
|||||||
import { useParams, useHistory } from 'react-router-dom';
|
import { useParams, useHistory } from 'react-router-dom';
|
||||||
import { useAsync } from 'react-use';
|
import { useAsync } from 'react-use';
|
||||||
import MakeJournalEntriesForm from './MakeJournalEntriesForm';
|
import MakeJournalEntriesForm from './MakeJournalEntriesForm';
|
||||||
import LoadingIndicator from 'components/LoadingIndicator';
|
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||||
import DashboardConnect from 'connectors/Dashboard.connector';
|
import DashboardConnect from 'connectors/Dashboard.connector';
|
||||||
import {compose} from 'utils';
|
import {compose} from 'utils';
|
||||||
import MakeJournalEntriesConnect from 'connectors/MakeJournalEntries.connect';
|
import MakeJournalEntriesConnect from 'connectors/MakeJournalEntries.connect';
|
||||||
@@ -36,12 +36,12 @@ function MakeJournalEntriesPage({
|
|||||||
}, [history]);
|
}, [history]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LoadingIndicator loading={fetchJournal.loading} mount={false}>
|
<DashboardInsider loading={fetchJournal.pending} name={'make-journal-page'}>
|
||||||
<MakeJournalEntriesForm
|
<MakeJournalEntriesForm
|
||||||
onFormSubmit={handleFormSubmit}
|
onFormSubmit={handleFormSubmit}
|
||||||
editJournal={editJournal}
|
editJournal={editJournal}
|
||||||
onCancelForm={handleCancel} />
|
onCancelForm={handleCancel} />
|
||||||
</LoadingIndicator>
|
</DashboardInsider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
|
|||||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||||
import ManualJournalsViewTabs from 'components/JournalEntry/ManualJournalsViewTabs';
|
import ManualJournalsViewTabs from 'components/JournalEntry/ManualJournalsViewTabs';
|
||||||
import ManualJournalsDataTable from 'components/JournalEntry/ManualJournalsDataTable';
|
import ManualJournalsDataTable from 'components/JournalEntry/ManualJournalsDataTable';
|
||||||
import DashboardActionsBar from 'components/JournalEntry/ManualJournalActionsBar';
|
import ManualJournalsActionsBar from 'components/JournalEntry/ManualJournalActionsBar';
|
||||||
import ManualJournalsConnect from 'connectors/ManualJournals.connect';
|
import ManualJournalsConnect from 'connectors/ManualJournals.connect';
|
||||||
import DashboardConnect from 'connectors/Dashboard.connector';
|
import DashboardConnect from 'connectors/Dashboard.connector';
|
||||||
import CustomViewConnect from 'connectors/CustomView.connector';
|
import CustomViewConnect from 'connectors/CustomView.connector';
|
||||||
@@ -16,13 +16,20 @@ import { compose } from 'utils';
|
|||||||
|
|
||||||
function ManualJournalsTable({
|
function ManualJournalsTable({
|
||||||
changePageTitle,
|
changePageTitle,
|
||||||
|
|
||||||
fetchResourceViews,
|
fetchResourceViews,
|
||||||
fetchManualJournalsTable,
|
fetchManualJournalsTable,
|
||||||
|
|
||||||
requestDeleteManualJournal,
|
requestDeleteManualJournal,
|
||||||
requestPublishManualJournal,
|
requestPublishManualJournal,
|
||||||
|
requestDeleteBulkManualJournals,
|
||||||
|
|
||||||
|
addManualJournalsTableQueries
|
||||||
}) {
|
}) {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const [deleteManualJournal, setDeleteManualJournal] = useState(false);
|
const [deleteManualJournal, setDeleteManualJournal] = useState(false);
|
||||||
|
const [selectedRows, setSelectedRows] = useState([]);
|
||||||
|
const [bulkDelete, setBulkDelete] = useState(false);
|
||||||
|
|
||||||
const fetchHook = useAsync(async () => {
|
const fetchHook = useAsync(async () => {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
@@ -32,16 +39,23 @@ function ManualJournalsTable({
|
|||||||
|
|
||||||
const fetchManualJournalsHook = useAsync(async () => {
|
const fetchManualJournalsHook = useAsync(async () => {
|
||||||
return fetchManualJournalsTable();
|
return fetchManualJournalsTable();
|
||||||
}, false);
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
changePageTitle('Manual Journals');
|
changePageTitle('Manual Journals');
|
||||||
}, []);
|
}, [changePageTitle]);
|
||||||
|
|
||||||
const handleCancelManualJournalDelete = () => {
|
// Handle delete manual journal click.
|
||||||
|
const handleDeleteJournal = useCallback((journal) => {
|
||||||
|
setDeleteManualJournal(journal);
|
||||||
|
}, [setDeleteManualJournal]);
|
||||||
|
|
||||||
|
// Handle cancel delete manual journal.
|
||||||
|
const handleCancelManualJournalDelete = useCallback(() => {
|
||||||
setDeleteManualJournal(false);
|
setDeleteManualJournal(false);
|
||||||
};
|
}, [setDeleteManualJournal]);
|
||||||
|
|
||||||
|
// Handle confirm delete manual journal.
|
||||||
const handleConfirmManualJournalDelete = useCallback(() => {
|
const handleConfirmManualJournalDelete = useCallback(() => {
|
||||||
requestDeleteManualJournal(deleteManualJournal.id).then(() => {
|
requestDeleteManualJournal(deleteManualJournal.id).then(() => {
|
||||||
setDeleteManualJournal(false);
|
setDeleteManualJournal(false);
|
||||||
@@ -49,25 +63,53 @@ function ManualJournalsTable({
|
|||||||
});
|
});
|
||||||
}, [deleteManualJournal, requestDeleteManualJournal]);
|
}, [deleteManualJournal, requestDeleteManualJournal]);
|
||||||
|
|
||||||
|
const handleBulkDelete = useCallback((accountsIds) => {
|
||||||
|
setBulkDelete(accountsIds);
|
||||||
|
}, [setBulkDelete]);
|
||||||
|
|
||||||
|
const handleConfirmBulkDelete = useCallback(() => {
|
||||||
|
requestDeleteBulkManualJournals(bulkDelete).then(() => {
|
||||||
|
setBulkDelete(false);
|
||||||
|
AppToaster.show({ message: 'the_accounts_have_been_deleted' });
|
||||||
|
}).catch((error) => {
|
||||||
|
setBulkDelete(false);
|
||||||
|
});
|
||||||
|
}, [
|
||||||
|
requestDeleteBulkManualJournals,
|
||||||
|
bulkDelete,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const handleCancelBulkDelete = useCallback(() => {
|
||||||
|
setBulkDelete(false);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleEditJournal = useCallback((journal) => {
|
const handleEditJournal = useCallback((journal) => {
|
||||||
history.push(`/dashboard/accounting/manual-journals/${journal.id}/edit`);
|
history.push(`/dashboard/accounting/manual-journals/${journal.id}/edit`);
|
||||||
}, [history]);
|
}, [history]);
|
||||||
|
|
||||||
const handleDeleteJournal = useCallback((journal) => {
|
// Handle filter change to re-fetch data-table.
|
||||||
setDeleteManualJournal(journal);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleFilterChanged = useCallback(() => {
|
const handleFilterChanged = useCallback(() => {
|
||||||
fetchManualJournalsHook.execute();
|
fetchManualJournalsHook.execute();
|
||||||
}, []);
|
}, [fetchManualJournalsHook]);
|
||||||
|
|
||||||
|
// Handle view change to re-fetch data table.
|
||||||
const handleViewChanged = useCallback(() => {
|
const handleViewChanged = useCallback(() => {
|
||||||
fetchManualJournalsHook.execute();
|
fetchManualJournalsHook.execute();
|
||||||
}, []);
|
}, [fetchManualJournalsHook]);
|
||||||
|
|
||||||
const handleFetchData = useCallback(() => {
|
// Handle fetch data of manual jouranls datatable.
|
||||||
|
const handleFetchData = useCallback(({ pageIndex, pageSize, sortBy }) => {
|
||||||
|
addManualJournalsTableQueries({
|
||||||
|
...(sortBy.length > 0) ? {
|
||||||
|
column_sort_by: sortBy[0].id,
|
||||||
|
sort_order: sortBy[0].desc ? 'desc' : 'asc',
|
||||||
|
} : {},
|
||||||
|
});
|
||||||
fetchManualJournalsHook.execute();
|
fetchManualJournalsHook.execute();
|
||||||
}, []);
|
}, [
|
||||||
|
fetchManualJournalsHook,
|
||||||
|
addManualJournalsTableQueries,
|
||||||
|
]);
|
||||||
|
|
||||||
const handlePublishJournal = useCallback((journal) => {
|
const handlePublishJournal = useCallback((journal) => {
|
||||||
requestPublishManualJournal(journal.id).then(() => {
|
requestPublishManualJournal(journal.id).then(() => {
|
||||||
@@ -75,9 +117,16 @@ function ManualJournalsTable({
|
|||||||
})
|
})
|
||||||
}, [requestPublishManualJournal]);
|
}, [requestPublishManualJournal]);
|
||||||
|
|
||||||
|
// Handle selected rows change.
|
||||||
|
const handleSelectedRowsChange = useCallback((accounts) => {
|
||||||
|
setSelectedRows(accounts);
|
||||||
|
}, [setSelectedRows]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardInsider loading={fetchHook.pending} name={'manual-journals'}>
|
<DashboardInsider loading={fetchHook.pending} name={'manual-journals'}>
|
||||||
<DashboardActionsBar
|
<ManualJournalsActionsBar
|
||||||
|
onBulkDelete={handleBulkDelete}
|
||||||
|
selectedRows={selectedRows}
|
||||||
onFilterChanged={handleFilterChanged} />
|
onFilterChanged={handleFilterChanged} />
|
||||||
|
|
||||||
<DashboardPageContent>
|
<DashboardPageContent>
|
||||||
@@ -97,7 +146,8 @@ function ManualJournalsTable({
|
|||||||
onDeleteJournal={handleDeleteJournal}
|
onDeleteJournal={handleDeleteJournal}
|
||||||
onFetchData={handleFetchData}
|
onFetchData={handleFetchData}
|
||||||
onEditJournal={handleEditJournal}
|
onEditJournal={handleEditJournal}
|
||||||
onPublishJournal={handlePublishJournal} />
|
onPublishJournal={handlePublishJournal}
|
||||||
|
onSelectedRowsChange={handleSelectedRowsChange} />
|
||||||
|
|
||||||
<Alert
|
<Alert
|
||||||
cancelButtonText='Cancel'
|
cancelButtonText='Cancel'
|
||||||
@@ -113,6 +163,21 @@ function ManualJournalsTable({
|
|||||||
able to restore it later, but it will become private to you.
|
able to restore it later, but it will become private to you.
|
||||||
</p>
|
</p>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
|
<Alert
|
||||||
|
cancelButtonText='Cancel'
|
||||||
|
confirmButtonText='Move to Trash'
|
||||||
|
icon='trash'
|
||||||
|
intent={Intent.DANGER}
|
||||||
|
isOpen={bulkDelete}
|
||||||
|
onCancel={handleCancelBulkDelete}
|
||||||
|
onConfirm={handleConfirmBulkDelete}
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
Are you sure you want to move <b>filename</b> to Trash? You will be
|
||||||
|
able to restore it later, but it will become private to you.
|
||||||
|
</p>
|
||||||
|
</Alert>
|
||||||
</DashboardPageContent>
|
</DashboardPageContent>
|
||||||
</DashboardInsider>
|
</DashboardInsider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -26,8 +26,6 @@ function AccountsChart({
|
|||||||
requestFetchAccountsTable,
|
requestFetchAccountsTable,
|
||||||
addAccountsTableQueries,
|
addAccountsTableQueries,
|
||||||
requestDeleteBulkAccounts,
|
requestDeleteBulkAccounts,
|
||||||
setDashboardRequestLoading,
|
|
||||||
setDashboardRequestCompleted,
|
|
||||||
}) {
|
}) {
|
||||||
const [deleteAccount, setDeleteAccount] = useState(false);
|
const [deleteAccount, setDeleteAccount] = useState(false);
|
||||||
const [inactiveAccount, setInactiveAccount] = useState(false);
|
const [inactiveAccount, setInactiveAccount] = useState(false);
|
||||||
@@ -36,23 +34,17 @@ function AccountsChart({
|
|||||||
|
|
||||||
// Fetch accounts resource views and fields.
|
// Fetch accounts resource views and fields.
|
||||||
const fetchHook = useAsync(async () => {
|
const fetchHook = useAsync(async () => {
|
||||||
setDashboardRequestLoading();
|
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
fetchResourceViews('accounts'),
|
fetchResourceViews('accounts'),
|
||||||
fetchResourceFields('accounts'),
|
fetchResourceFields('accounts'),
|
||||||
]);
|
]);
|
||||||
setDashboardRequestCompleted();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fetch accounts list according to the given custom view id.
|
// Fetch accounts list according to the given custom view id.
|
||||||
const fetchAccountsHook = useAsync(async () => {
|
const fetchAccountsHook = useAsync(async () => {
|
||||||
setDashboardRequestLoading();
|
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
requestFetchAccountsTable(),
|
requestFetchAccountsTable(),
|
||||||
]);
|
]);
|
||||||
setDashboardRequestCompleted();
|
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -102,7 +94,7 @@ function AccountsChart({
|
|||||||
requestFetchAccountsTable();
|
requestFetchAccountsTable();
|
||||||
AppToaster.show({ message: 'the_account_has_been_inactivated' });
|
AppToaster.show({ message: 'the_account_has_been_inactivated' });
|
||||||
});
|
});
|
||||||
}, [inactiveAccount]);
|
}, [inactiveAccount, requestFetchAccountsTable, requestInactiveAccount]);
|
||||||
|
|
||||||
|
|
||||||
const handleEditAccount = (account) => {
|
const handleEditAccount = (account) => {
|
||||||
|
|||||||
@@ -8,11 +8,7 @@ import {
|
|||||||
FormGroup,
|
FormGroup,
|
||||||
InputGroup,
|
InputGroup,
|
||||||
Intent,
|
Intent,
|
||||||
TextArea,
|
|
||||||
MenuItem,
|
|
||||||
Checkbox,
|
|
||||||
Classes,
|
Classes,
|
||||||
HTMLSelect,
|
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
import UserFormDialogConnect from 'connectors/UserFormDialog.connector';
|
import UserFormDialogConnect from 'connectors/UserFormDialog.connector';
|
||||||
import DialogReduxConnect from 'components/DialogReduxConnect';
|
import DialogReduxConnect from 'components/DialogReduxConnect';
|
||||||
@@ -22,7 +18,6 @@ import { objectKeysTransform } from 'utils';
|
|||||||
import { pick, snakeCase } from 'lodash';
|
import { pick, snakeCase } from 'lodash';
|
||||||
import ErrorMessage from 'components/ErrorMessage';
|
import ErrorMessage from 'components/ErrorMessage';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import Icon from 'components/Icon';
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
function UserFormDialog({
|
function UserFormDialog({
|
||||||
@@ -32,7 +27,6 @@ function UserFormDialog({
|
|||||||
name,
|
name,
|
||||||
payload,
|
payload,
|
||||||
isOpen,
|
isOpen,
|
||||||
userDetails,
|
|
||||||
closeDialog,
|
closeDialog,
|
||||||
}) {
|
}) {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
@@ -84,11 +78,6 @@ function UserFormDialog({
|
|||||||
});
|
});
|
||||||
const { values, errors, touched } = useMemo(() => formik, [formik]);
|
const { values, errors, touched } = useMemo(() => formik, [formik]);
|
||||||
|
|
||||||
const statusOptions = [
|
|
||||||
{ value: 1, label: 'Active' },
|
|
||||||
{ value: 2, label: 'Inactive' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const onDialogOpening = () => {
|
const onDialogOpening = () => {
|
||||||
fetchHook.execute();
|
fetchHook.execute();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,11 +15,12 @@ const ItemFormContainer = ({
|
|||||||
requestFetchItemCategories,
|
requestFetchItemCategories,
|
||||||
}) => {
|
}) => {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
id ?
|
id ?
|
||||||
changePageTitle('Edit Item Details') :
|
changePageTitle('Edit Item Details') :
|
||||||
changePageTitle('New Item');
|
changePageTitle('New Item');
|
||||||
}, []);
|
}, [id, changePageTitle]);
|
||||||
|
|
||||||
const fetchHook = useAsync(async () => {
|
const fetchHook = useAsync(async () => {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ const ItemsActionsBar = ({
|
|||||||
getResourceViews,
|
getResourceViews,
|
||||||
views,
|
views,
|
||||||
onFilterChanged,
|
onFilterChanged,
|
||||||
bulkSelected,
|
|
||||||
addItemsTableQueries,
|
addItemsTableQueries,
|
||||||
|
selectedRows = [],
|
||||||
}) => {
|
}) => {
|
||||||
const { path } = useRouteMatch();
|
const { path } = useRouteMatch();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@@ -43,6 +43,7 @@ const ItemsActionsBar = ({
|
|||||||
history.push('/dashboard/items/new');
|
history.push('/dashboard/items/new');
|
||||||
};
|
};
|
||||||
const itemsFields = getResourceFields('items');
|
const itemsFields = getResourceFields('items');
|
||||||
|
const hasSelectedRows = useMemo(() => selectedRows.length > 0, [selectedRows]);
|
||||||
|
|
||||||
const filterDropdown = FilterDropdown({
|
const filterDropdown = FilterDropdown({
|
||||||
fields: itemsFields,
|
fields: itemsFields,
|
||||||
@@ -55,11 +56,6 @@ const ItemsActionsBar = ({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const hasBulkActionsSelected = useMemo(
|
|
||||||
() => !!Object.keys(bulkSelected).length,
|
|
||||||
[bulkSelected]
|
|
||||||
);
|
|
||||||
|
|
||||||
const onClickNewCategory = useCallback(() => {
|
const onClickNewCategory = useCallback(() => {
|
||||||
openDialog('item-form', {});
|
openDialog('item-form', {});
|
||||||
}, [openDialog]);
|
}, [openDialog]);
|
||||||
@@ -108,7 +104,7 @@ const ItemsActionsBar = ({
|
|||||||
onClick={onClickNewCategory}
|
onClick={onClickNewCategory}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{hasBulkActionsSelected && (
|
{hasSelectedRows && (
|
||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
intent={Intent.DANGER}
|
intent={Intent.DANGER}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useCallback, useMemo } from 'react';
|
||||||
import {} from 'reselect';
|
|
||||||
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
import {
|
import {
|
||||||
NavbarGroup,
|
NavbarGroup,
|
||||||
@@ -20,21 +18,24 @@ import DialogConnect from 'connectors/Dialog.connector';
|
|||||||
import FilterDropdown from 'components/FilterDropdown';
|
import FilterDropdown from 'components/FilterDropdown';
|
||||||
import ResourceConnect from 'connectors/Resource.connector';
|
import ResourceConnect from 'connectors/Resource.connector';
|
||||||
|
|
||||||
|
|
||||||
const ItemsCategoryActionsBar = ({
|
const ItemsCategoryActionsBar = ({
|
||||||
openDialog,
|
openDialog,
|
||||||
onDeleteCategory,
|
onDeleteCategory,
|
||||||
onFilterChanged,
|
onFilterChanged,
|
||||||
getResourceFields,
|
getResourceFields,
|
||||||
|
selectedRows,
|
||||||
}) => {
|
}) => {
|
||||||
const onClickNewCategory = () => {
|
const onClickNewCategory = useCallback(() => {
|
||||||
openDialog('item-form', {});
|
openDialog('item-form', {});
|
||||||
};
|
}, [openDialog]);
|
||||||
|
|
||||||
const handleDeleteCategory = (category) => {
|
const handleDeleteCategory = useCallback((category) => {
|
||||||
onDeleteCategory(category);
|
onDeleteCategory(selectedRows);
|
||||||
};
|
}, [selectedRows, onDeleteCategory]);
|
||||||
|
|
||||||
const categoriesFields = getResourceFields('itemCategories');
|
const categoriesFields = getResourceFields('itemCategories');
|
||||||
|
const hasSelectedRows = useMemo(() => selectedRows.length > 0, [selectedRows]);
|
||||||
|
|
||||||
const filterDropdown = FilterDropdown({
|
const filterDropdown = FilterDropdown({
|
||||||
fields: categoriesFields,
|
fields: categoriesFields,
|
||||||
@@ -63,14 +64,15 @@ const ItemsCategoryActionsBar = ({
|
|||||||
/>
|
/>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|
||||||
<Button
|
{ hasSelectedRows && (
|
||||||
className={Classes.MINIMAL}
|
<Button
|
||||||
icon={<Icon icon='trash' iconSize={15} />}
|
className={Classes.MINIMAL}
|
||||||
text='Delete Category'
|
icon={<Icon icon='trash' iconSize={15} />}
|
||||||
intent={Intent.DANGER}
|
text='Delete'
|
||||||
onClick={handleDeleteCategory}
|
intent={Intent.DANGER}
|
||||||
/>
|
onClick={handleDeleteCategory}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
icon={<Icon icon='file-import' />}
|
icon={<Icon icon='file-import' />}
|
||||||
|
|||||||
@@ -20,25 +20,29 @@ const ItemCategoriesList = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const [deleteCategory, setDeleteCategory] = useState(false);
|
const [deleteCategory, setDeleteCategory] = useState(false);
|
||||||
|
const [selectedRows, setSelectedRows] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
id
|
id
|
||||||
? changePageTitle('Edit Item Details')
|
? changePageTitle('Edit Item Details')
|
||||||
: changePageTitle('Categories List');
|
: changePageTitle('Categories List');
|
||||||
}, []);
|
}, [id, changePageTitle]);
|
||||||
|
|
||||||
const fetchHook = useAsync(async () => {
|
const fetchHook = useAsync(async () => {
|
||||||
await Promise.all([requestFetchItemCategories()]);
|
await Promise.all([
|
||||||
|
requestFetchItemCategories(),
|
||||||
|
]);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
const handelDeleteCategory = category => {
|
const handelDeleteCategory = useCallback((category) => {
|
||||||
setDeleteCategory(category);
|
setDeleteCategory(category);
|
||||||
};
|
}, [setDeleteCategory]);
|
||||||
|
|
||||||
const handelEditCategory = category => {};
|
const handelEditCategory = category => {};
|
||||||
const handelCancelCategoryDelete = () => {
|
|
||||||
|
const handelCancelCategoryDelete = useCallback(() => {
|
||||||
setDeleteCategory(false);
|
setDeleteCategory(false);
|
||||||
};
|
}, [setDeleteCategory]);
|
||||||
|
|
||||||
const handelConfirmCategoryDelete = useCallback(() => {
|
const handelConfirmCategoryDelete = useCallback(() => {
|
||||||
requestDeleteItemCategory(deleteCategory.id).then(() => {
|
requestDeleteItemCategory(deleteCategory.id).then(() => {
|
||||||
@@ -47,23 +51,30 @@ const ItemCategoriesList = ({
|
|||||||
message: 'the_category_has_been_delete'
|
message: 'the_category_has_been_delete'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, [deleteCategory]);
|
}, [deleteCategory, requestDeleteItemCategory, setDeleteCategory]);
|
||||||
|
|
||||||
const handleFetchData = useCallback(() => {
|
const handleFetchData = useCallback(() => {
|
||||||
fetchHook.execute();
|
fetchHook.execute();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Handle selected rows change.
|
||||||
|
const handleSelectedRowsChange = useCallback((accounts) => {
|
||||||
|
setSelectedRows(accounts);
|
||||||
|
}, [setSelectedRows]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardInsider loading={fetchHook.pending}>
|
<DashboardInsider loading={fetchHook.pending}>
|
||||||
<ItemsCategoryActionsBar
|
<ItemsCategoryActionsBar
|
||||||
views={views}
|
views={views}
|
||||||
onDeleteCategory={handelDeleteCategory}
|
onDeleteCategory={handelDeleteCategory}
|
||||||
|
selectedRows={selectedRows}
|
||||||
/>
|
/>
|
||||||
<DashboardPageContent>
|
<DashboardPageContent>
|
||||||
<ItemsCategoryList
|
<ItemsCategoryList
|
||||||
onDeleteCategory={handelDeleteCategory}
|
onDeleteCategory={handelDeleteCategory}
|
||||||
onFetchData={handleFetchData}
|
onFetchData={handleFetchData}
|
||||||
onEditCategory={handelEditCategory}
|
onEditCategory={handelEditCategory}
|
||||||
categories
|
onSelectedRowsChange={handleSelectedRowsChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Alert
|
<Alert
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, {useEffect, useCallback, useMemo} from 'react';
|
import React, {useState, useEffect, useCallback, useMemo} from 'react';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Popover,
|
Popover,
|
||||||
@@ -7,7 +7,6 @@ import {
|
|||||||
MenuDivider,
|
MenuDivider,
|
||||||
Position,
|
Position,
|
||||||
} from '@blueprintjs/core'
|
} from '@blueprintjs/core'
|
||||||
import LoadingIndicator from 'components/LoadingIndicator';
|
|
||||||
import CustomViewConnect from 'connectors/View.connector';
|
import CustomViewConnect from 'connectors/View.connector';
|
||||||
import ItemsConnect from 'connectors/Items.connect';
|
import ItemsConnect from 'connectors/Items.connect';
|
||||||
import {compose} from 'utils';
|
import {compose} from 'utils';
|
||||||
@@ -22,7 +21,16 @@ const ItemsDataTable = ({
|
|||||||
onEditItem,
|
onEditItem,
|
||||||
onDeleteItem,
|
onDeleteItem,
|
||||||
onFetchData,
|
onFetchData,
|
||||||
|
onSelectedRowsChange,
|
||||||
}) => {
|
}) => {
|
||||||
|
const [initialMount, setInitialMount] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!itemsTableLoading) {
|
||||||
|
setInitialMount(true);
|
||||||
|
}
|
||||||
|
}, [itemsTableLoading, setInitialMount]);
|
||||||
|
|
||||||
const handleEditItem = (item) => () => { onEditItem(item); };
|
const handleEditItem = (item) => () => { onEditItem(item); };
|
||||||
const handleDeleteItem = (item) => () => { onDeleteItem(item); };
|
const handleDeleteItem = (item) => () => { onDeleteItem(item); };
|
||||||
|
|
||||||
@@ -75,7 +83,6 @@ const ItemsDataTable = ({
|
|||||||
// accessor: 'inventory_account.name',
|
// accessor: 'inventory_account.name',
|
||||||
// className: "inventory-account",
|
// className: "inventory-account",
|
||||||
// },
|
// },
|
||||||
|
|
||||||
{
|
{
|
||||||
id: 'actions',
|
id: 'actions',
|
||||||
Cell: ({ cell }) => (
|
Cell: ({ cell }) => (
|
||||||
@@ -98,16 +105,21 @@ const ItemsDataTable = ({
|
|||||||
|
|
||||||
const handleFetchData = useCallback((...args) => {
|
const handleFetchData = useCallback((...args) => {
|
||||||
onFetchData && onFetchData(...args)
|
onFetchData && onFetchData(...args)
|
||||||
}, [onFetchData])
|
}, [onFetchData]);
|
||||||
|
|
||||||
|
const handleSelectedRowsChange = useCallback((selectedRows) => {
|
||||||
|
onSelectedRowsChange && onSelectedRowsChange(selectedRows.map(s => s.original));
|
||||||
|
}, [onSelectedRowsChange]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LoadingIndicator loading={itemsTableLoading} spinnerSize={30}>
|
<DataTable
|
||||||
<DataTable
|
columns={columns}
|
||||||
columns={columns}
|
data={currentPageItems}
|
||||||
data={currentPageItems}
|
selectionColumn={selectionColumn}
|
||||||
selectionColumn={selectionColumn}
|
onFetchData={handleFetchData}
|
||||||
onFetchData={handleFetchData} />
|
loading={itemsTableLoading && !initialMount}
|
||||||
</LoadingIndicator>
|
noInitialFetch={true}
|
||||||
|
onSelectedRowsChange={handleSelectedRowsChange} />
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ function ItemsList({
|
|||||||
addItemsTableQueries,
|
addItemsTableQueries,
|
||||||
}) {
|
}) {
|
||||||
const [deleteItem, setDeleteItem] = useState(false);
|
const [deleteItem, setDeleteItem] = useState(false);
|
||||||
|
const [selectedRows, setSelectedRows] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
changePageTitle('Items List');
|
changePageTitle('Items List');
|
||||||
@@ -49,16 +50,19 @@ function ItemsList({
|
|||||||
])
|
])
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Handle click delete item.
|
||||||
const handleDeleteItem = useCallback((item) => {
|
const handleDeleteItem = useCallback((item) => {
|
||||||
setDeleteItem(item);
|
setDeleteItem(item);
|
||||||
}, [setDeleteItem]);
|
}, [setDeleteItem]);
|
||||||
|
|
||||||
const handleEditItem = () => {};
|
const handleEditItem = () => {};
|
||||||
|
|
||||||
|
// Handle cancel delete the item.
|
||||||
const handleCancelDeleteItem = useCallback(() => {
|
const handleCancelDeleteItem = useCallback(() => {
|
||||||
setDeleteItem(false);
|
setDeleteItem(false);
|
||||||
}, [setDeleteItem]);
|
}, [setDeleteItem]);
|
||||||
|
|
||||||
|
// handle confirm delete item.
|
||||||
const handleConfirmDeleteItem = useCallback(() => {
|
const handleConfirmDeleteItem = useCallback(() => {
|
||||||
requestDeleteItem(deleteItem.id).then(() => {
|
requestDeleteItem(deleteItem.id).then(() => {
|
||||||
AppToaster.show({ message: 'the_item_has_been_deleted' });
|
AppToaster.show({ message: 'the_item_has_been_deleted' });
|
||||||
@@ -69,25 +73,33 @@ function ItemsList({
|
|||||||
const handleFetchData = useCallback(({ pageIndex, pageSize, sortBy }) => {
|
const handleFetchData = useCallback(({ pageIndex, pageSize, sortBy }) => {
|
||||||
addItemsTableQueries({
|
addItemsTableQueries({
|
||||||
...(sortBy.length > 0) ? {
|
...(sortBy.length > 0) ? {
|
||||||
column_sort_by: sortBy[0].id,
|
column_sort_order: sortBy[0].id,
|
||||||
sort_by: sortBy[0].desc ? 'desc' : 'asc',
|
sort_order: sortBy[0].desc ? 'desc' : 'asc',
|
||||||
} : {},
|
} : {},
|
||||||
});
|
});
|
||||||
fetchItems.execute();
|
fetchItems.execute();
|
||||||
}, [fetchItems, addItemsTableQueries]);
|
}, [fetchItems, addItemsTableQueries]);
|
||||||
|
|
||||||
|
// Handle filter change to re-fetch the items.
|
||||||
const handleFilterChanged = useCallback(() => {
|
const handleFilterChanged = useCallback(() => {
|
||||||
fetchItems.execute();
|
fetchItems.execute();
|
||||||
}, [fetchItems]);
|
}, [fetchItems]);
|
||||||
|
|
||||||
|
// Handle custom view change to re-fetch the items.
|
||||||
const handleCustomViewChanged = useCallback(() => {
|
const handleCustomViewChanged = useCallback(() => {
|
||||||
fetchItems.execute();
|
fetchItems.execute();
|
||||||
}, [fetchItems]);
|
}, [fetchItems]);
|
||||||
|
|
||||||
|
// Handle selected rows change.
|
||||||
|
const handleSelectedRowsChange = useCallback((accounts) => {
|
||||||
|
setSelectedRows(accounts);
|
||||||
|
}, [setSelectedRows]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardInsider isLoading={fetchHook.pending} name={'items-list'}>
|
<DashboardInsider isLoading={fetchHook.pending} name={'items-list'}>
|
||||||
<ItemsActionsBar
|
<ItemsActionsBar
|
||||||
onFilterChanged={handleFilterChanged}
|
onFilterChanged={handleFilterChanged}
|
||||||
|
selectedRows={selectedRows}
|
||||||
views={views} />
|
views={views} />
|
||||||
|
|
||||||
<DashboardPageContent>
|
<DashboardPageContent>
|
||||||
@@ -98,12 +110,14 @@ function ItemsList({
|
|||||||
'/dashboard/items/:custom_view_id/custom_view',
|
'/dashboard/items/:custom_view_id/custom_view',
|
||||||
'/dashboard/items'
|
'/dashboard/items'
|
||||||
]}>
|
]}>
|
||||||
<ItemsViewsTabs onViewChanged={handleCustomViewChanged} />
|
<ItemsViewsTabs
|
||||||
|
onViewChanged={handleCustomViewChanged} />
|
||||||
|
|
||||||
<ItemsDataTable
|
<ItemsDataTable
|
||||||
onDeleteItem={handleDeleteItem}
|
onDeleteItem={handleDeleteItem}
|
||||||
onEditItem={handleEditItem}
|
onEditItem={handleEditItem}
|
||||||
onFetchData={handleFetchData} />
|
onFetchData={handleFetchData}
|
||||||
|
onSelectedRowsChange={handleSelectedRowsChange} />
|
||||||
|
|
||||||
<Alert
|
<Alert
|
||||||
cancelButtonText="Cancel"
|
cancelButtonText="Cancel"
|
||||||
|
|||||||
@@ -1,25 +1,24 @@
|
|||||||
import React from 'react';
|
import React, {useCallback} from 'react';
|
||||||
import {
|
import {
|
||||||
Tabs,
|
Tabs,
|
||||||
Tab,
|
Tab,
|
||||||
Button,
|
Button,
|
||||||
Intent,
|
Intent,
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
import { useHistory } from 'react-router-dom';
|
|
||||||
import PreferencesSubContent from 'components/Preferences/PreferencesSubContent';
|
import PreferencesSubContent from 'components/Preferences/PreferencesSubContent';
|
||||||
import connector from 'connectors/UsersPreferences.connector';
|
import connector from 'connectors/UsersPreferences.connector';
|
||||||
|
|
||||||
function UsersPreferences({
|
function UsersPreferences({
|
||||||
openDialog,
|
openDialog,
|
||||||
}) {
|
}) {
|
||||||
const history = useHistory();
|
|
||||||
const onChangeTabs = (currentTabId) => {
|
const onChangeTabs = (currentTabId) => {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onClickNewUser = () => {
|
const onClickNewUser = useCallback(() => {
|
||||||
openDialog('user-form');
|
openDialog('user-form');
|
||||||
};
|
}, [openDialog]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="preferences__inside-content preferences__inside-content--users-roles">
|
<div class="preferences__inside-content preferences__inside-content--users-roles">
|
||||||
<div class="preferences__tabs">
|
<div class="preferences__tabs">
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { BrowserRouter } from 'react-router-dom';
|
|||||||
import App from 'components/App';
|
import App from 'components/App';
|
||||||
import * as serviceWorker from 'serviceWorker';
|
import * as serviceWorker from 'serviceWorker';
|
||||||
import createStore from 'store/createStore';
|
import createStore from 'store/createStore';
|
||||||
|
import AppProgress from 'components/NProgress/AppProgress';
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<Provider store={createStore}>
|
<Provider store={createStore}>
|
||||||
@@ -15,6 +16,13 @@ ReactDOM.render(
|
|||||||
document.getElementById('root')
|
document.getElementById('root')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<Provider store={createStore}>
|
||||||
|
<AppProgress />
|
||||||
|
</Provider>,
|
||||||
|
document.getElementById('nprogress')
|
||||||
|
);
|
||||||
|
|
||||||
// If you want your app to work offline and load faster, you can change
|
// If you want your app to work offline and load faster, you can change
|
||||||
// unregister() to register() below. Note this comes with some pitfalls.
|
// unregister() to register() below. Note this comes with some pitfalls.
|
||||||
// Learn more about service workers: https://bit.ly/CRA-PWA
|
// Learn more about service workers: https://bit.ly/CRA-PWA
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export default [
|
|||||||
path: `${BASE_URL}/register`,
|
path: `${BASE_URL}/register`,
|
||||||
name: 'auth.register',
|
name: 'auth.register',
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () => import('containers/Authentication/Register'),
|
loader: () => import('containers/Authentication/Register'),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,17 +6,14 @@ export default [
|
|||||||
// Homepage
|
// Homepage
|
||||||
{
|
{
|
||||||
path: `${BASE_URL}/homepage`,
|
path: `${BASE_URL}/homepage`,
|
||||||
name: 'dashboard.homepage',
|
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () => import('containers/Dashboard/Homepage')
|
loader: () => import('containers/Dashboard/Homepage')
|
||||||
}),
|
}),
|
||||||
exact: true
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Accounts.
|
// Accounts.
|
||||||
{
|
{
|
||||||
path: `${BASE_URL}/accounts`,
|
path: `${BASE_URL}/accounts`,
|
||||||
name: 'dashboard.accounts',
|
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () => import('containers/Dashboard/Accounts/AccountsChart')
|
loader: () => import('containers/Dashboard/Accounts/AccountsChart')
|
||||||
})
|
})
|
||||||
@@ -25,14 +22,12 @@ export default [
|
|||||||
// Custom views.
|
// Custom views.
|
||||||
{
|
{
|
||||||
path: `${BASE_URL}/custom_views/:resource_slug/new`,
|
path: `${BASE_URL}/custom_views/:resource_slug/new`,
|
||||||
name: 'dashboard.custom_view.new',
|
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () => import('containers/Dashboard/Views/ViewFormPage')
|
loader: () => import('containers/Dashboard/Views/ViewFormPage')
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `${BASE_URL}/custom_views/:view_id/edit`,
|
path: `${BASE_URL}/custom_views/:view_id/edit`,
|
||||||
name: 'dashboard.custom_view.edit',
|
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () => import('containers/Dashboard/Views/ViewFormPage')
|
loader: () => import('containers/Dashboard/Views/ViewFormPage')
|
||||||
})
|
})
|
||||||
@@ -41,15 +36,12 @@ export default [
|
|||||||
// Expenses.
|
// Expenses.
|
||||||
{
|
{
|
||||||
path: `${BASE_URL}/expenses/new`,
|
path: `${BASE_URL}/expenses/new`,
|
||||||
name: 'dashboard.expense.new',
|
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () => import('containers/Dashboard/Expenses/ExpenseForm')
|
loader: () => import('containers/Dashboard/Expenses/ExpenseForm')
|
||||||
}),
|
}),
|
||||||
text: 'New Expense'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `${BASE_URL}/expenses`,
|
path: `${BASE_URL}/expenses`,
|
||||||
name: 'dashboard.expeneses.list',
|
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () => import('containers/Dashboard/Expenses/ExpensesList')
|
loader: () => import('containers/Dashboard/Expenses/ExpensesList')
|
||||||
})
|
})
|
||||||
@@ -58,30 +50,24 @@ export default [
|
|||||||
// Accounting
|
// Accounting
|
||||||
{
|
{
|
||||||
path: `${BASE_URL}/accounting/make-journal-entry`,
|
path: `${BASE_URL}/accounting/make-journal-entry`,
|
||||||
name: 'dashboard.accounting.make.journal',
|
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () =>
|
loader: () =>
|
||||||
import('containers/Dashboard/Accounting/MakeJournalEntriesPage')
|
import('containers/Dashboard/Accounting/MakeJournalEntriesPage')
|
||||||
}),
|
}),
|
||||||
text: 'Make Journal Entry'
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: `${BASE_URL}/accounting/manual-journals/:id/edit`,
|
path: `${BASE_URL}/accounting/manual-journals/:id/edit`,
|
||||||
name: 'dashboard.manual.journal.edit',
|
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () =>
|
loader: () =>
|
||||||
import('containers/Dashboard/Accounting/MakeJournalEntriesPage')
|
import('containers/Dashboard/Accounting/MakeJournalEntriesPage')
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: `${BASE_URL}/accounting/manual-journals`,
|
path: `${BASE_URL}/accounting/manual-journals`,
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () =>
|
loader: () =>
|
||||||
import('containers/Dashboard/Accounting/ManualJournalsTable')
|
import('containers/Dashboard/Accounting/ManualJournalsTable')
|
||||||
}),
|
}),
|
||||||
text: 'Manual Journals'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `${BASE_URL}/items/categories`,
|
path: `${BASE_URL}/items/categories`,
|
||||||
@@ -89,8 +75,6 @@ export default [
|
|||||||
loader: () => import('containers/Dashboard/Items/ItemsCategoryList')
|
loader: () => import('containers/Dashboard/Items/ItemsCategoryList')
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
path: `${BASE_URL}/items/new`,
|
path: `${BASE_URL}/items/new`,
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
@@ -109,7 +93,6 @@ export default [
|
|||||||
// Financial Reports.
|
// Financial Reports.
|
||||||
{
|
{
|
||||||
path: `${BASE_URL}/accounting/general-ledger`,
|
path: `${BASE_URL}/accounting/general-ledger`,
|
||||||
name: 'dashboard.accounting.general.ledger',
|
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () =>
|
loader: () =>
|
||||||
import(
|
import(
|
||||||
@@ -119,7 +102,6 @@ export default [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `${BASE_URL}/accounting/balance-sheet`,
|
path: `${BASE_URL}/accounting/balance-sheet`,
|
||||||
name: 'dashboard.accounting.balance.sheet',
|
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () =>
|
loader: () =>
|
||||||
import(
|
import(
|
||||||
@@ -129,7 +111,6 @@ export default [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `${BASE_URL}/accounting/trial-balance-sheet`,
|
path: `${BASE_URL}/accounting/trial-balance-sheet`,
|
||||||
name: 'dashboard.accounting.trial.balance',
|
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () =>
|
loader: () =>
|
||||||
import(
|
import(
|
||||||
@@ -139,7 +120,6 @@ export default [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `${BASE_URL}/accounting/profit-loss-sheet`,
|
path: `${BASE_URL}/accounting/profit-loss-sheet`,
|
||||||
name: 'dashboard.accounting.profit.loss.sheet',
|
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () =>
|
loader: () =>
|
||||||
import(
|
import(
|
||||||
@@ -149,10 +129,9 @@ export default [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `${BASE_URL}/accounting/journal-sheet`,
|
path: `${BASE_URL}/accounting/journal-sheet`,
|
||||||
name: 'dashboard.accounting.journal.sheet',
|
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () =>
|
loader: () =>
|
||||||
import('containers/Dashboard/FinancialStatements/Journal/Journal')
|
import('containers/Dashboard/FinancialStatements/Journal/Journal')
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -18,25 +18,32 @@ export const fetchAccountTypes = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const fetchAccountsList = ({ query } = {}) => {
|
export const fetchAccountsList = ({ query } = {}) => {
|
||||||
return dispatch =>
|
return dispatch => new Promise((resolve, reject) => {
|
||||||
new Promise((resolve, reject) => {
|
dispatch({
|
||||||
ApiService.get('accounts', { params: query })
|
type: t.SET_DASHBOARD_REQUEST_LOADING,
|
||||||
.then(response => {
|
|
||||||
dispatch({
|
|
||||||
type: t.ACCOUNTS_PAGE_SET,
|
|
||||||
accounts: response.data.accounts,
|
|
||||||
customViewId: response.data.customViewId
|
|
||||||
});
|
|
||||||
dispatch({
|
|
||||||
type: t.ACCOUNTS_ITEMS_SET,
|
|
||||||
accounts: response.data.accounts
|
|
||||||
});
|
|
||||||
resolve(response);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
reject(error);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
ApiService.get('accounts', { params: query }).then(response => {
|
||||||
|
dispatch({
|
||||||
|
type: t.ACCOUNTS_PAGE_SET,
|
||||||
|
accounts: response.data.accounts,
|
||||||
|
customViewId: response.data.customViewId
|
||||||
|
});
|
||||||
|
dispatch({
|
||||||
|
type: t.ACCOUNTS_ITEMS_SET,
|
||||||
|
accounts: response.data.accounts
|
||||||
|
});
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
|
||||||
|
});
|
||||||
|
resolve(response);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
|
||||||
|
});
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchAccountsTable = ({ query } = {}) => {
|
export const fetchAccountsTable = ({ query } = {}) => {
|
||||||
@@ -54,6 +61,9 @@ export const fetchAccountsTable = ({ query } = {}) => {
|
|||||||
type: t.ACCOUNTS_TABLE_LOADING,
|
type: t.ACCOUNTS_TABLE_LOADING,
|
||||||
loading: true,
|
loading: true,
|
||||||
});
|
});
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_LOADING,
|
||||||
|
});
|
||||||
ApiService.get('accounts', { params: { ...pageQuery, ...query } })
|
ApiService.get('accounts', { params: { ...pageQuery, ...query } })
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
@@ -69,9 +79,15 @@ export const fetchAccountsTable = ({ query } = {}) => {
|
|||||||
type: t.ACCOUNTS_TABLE_LOADING,
|
type: t.ACCOUNTS_TABLE_LOADING,
|
||||||
loading: false,
|
loading: false,
|
||||||
});
|
});
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
|
||||||
|
});
|
||||||
resolve(response);
|
resolve(response);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
|
||||||
|
});
|
||||||
reject(error);
|
reject(error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -96,12 +112,17 @@ export const fetchAccountsDataTable = ({ query }) => {
|
|||||||
export const submitAccount = ({ form }) => {
|
export const submitAccount = ({ form }) => {
|
||||||
return dispatch =>
|
return dispatch =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_LOADING,
|
||||||
|
});
|
||||||
ApiService.post('accounts', form)
|
ApiService.post('accounts', form)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: t.ACCOUNT_ERRORS_CLEAR,
|
type: t.ACCOUNT_ERRORS_CLEAR,
|
||||||
});
|
});
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
|
||||||
|
});
|
||||||
resolve(response);
|
resolve(response);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
@@ -118,31 +139,42 @@ export const submitAccount = ({ form }) => {
|
|||||||
payload: { errors },
|
payload: { errors },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
|
||||||
|
});
|
||||||
reject(errors);
|
reject(errors);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const editAccount = ({ id, form }) => {
|
export const editAccount = ({ id, form }) => {
|
||||||
return dispatch =>
|
return dispatch => new Promise((resolve, reject) => {
|
||||||
new Promise((resolve, reject) => {
|
dispatch({
|
||||||
ApiService.post(`accounts/${id}`, form)
|
type: t.SET_DASHBOARD_REQUEST_LOADING,
|
||||||
.then(response => {
|
|
||||||
dispatch({ type: t.CLEAR_ACCOUNT_FORM_ERRORS });
|
|
||||||
resolve(response);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
const { response } = error;
|
|
||||||
const { data } = response;
|
|
||||||
const { errors } = data;
|
|
||||||
|
|
||||||
dispatch({ type: t.CLEAR_ACCOUNT_FORM_ERRORS });
|
|
||||||
if (errors) {
|
|
||||||
dispatch({ type: t.ACCOUNT_FORM_ERRORS, errors });
|
|
||||||
}
|
|
||||||
reject(errors);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
ApiService.post(`accounts/${id}`, form)
|
||||||
|
.then(response => {
|
||||||
|
dispatch({ type: t.CLEAR_ACCOUNT_FORM_ERRORS });
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
|
||||||
|
});
|
||||||
|
resolve(response);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
const { response } = error;
|
||||||
|
const { data } = response;
|
||||||
|
const { errors } = data;
|
||||||
|
|
||||||
|
dispatch({ type: t.CLEAR_ACCOUNT_FORM_ERRORS });
|
||||||
|
if (errors) {
|
||||||
|
dispatch({ type: t.ACCOUNT_FORM_ERRORS, errors });
|
||||||
|
}
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
|
||||||
|
});
|
||||||
|
reject(errors);
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const activeAccount = ({ id }) => {
|
export const activeAccount = ({ id }) => {
|
||||||
|
|||||||
@@ -21,16 +21,9 @@ export default function login({ form }) {
|
|||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
const { response } = error;
|
const { response } = error;
|
||||||
const { data } = response;
|
const { data } = response;
|
||||||
const { errors } = data;
|
const { errors = [] } = data;
|
||||||
|
|
||||||
dispatch({type: t.LOGIN_CLEAR_ERRORS});
|
reject(errors);
|
||||||
|
|
||||||
if (errors){
|
|
||||||
dispatch({
|
|
||||||
type: t.LOGIN_FAILURE, errors,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
reject(error);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,20 +8,25 @@ export const submitItemCategory = ({ form }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const fetchItemCategories = () => {
|
export const fetchItemCategories = () => {
|
||||||
return (dispatch, getState) =>
|
return (dispatch, getState) => new Promise((resolve, reject) => {
|
||||||
new Promise((resolve, reject) => {
|
dispatch({
|
||||||
ApiService.get('item_categories')
|
type: t.SET_DASHBOARD_REQUEST_LOADING,
|
||||||
.then((response) => {
|
|
||||||
dispatch({
|
|
||||||
type: t.ITEMS_CATEGORY_LIST_SET,
|
|
||||||
categories: response.data.categories,
|
|
||||||
});
|
|
||||||
resolve(response);
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
reject(error);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
ApiService.get('item_categories')
|
||||||
|
.then((response) => {
|
||||||
|
dispatch({
|
||||||
|
type: t.ITEMS_CATEGORY_LIST_SET,
|
||||||
|
categories: response.data.categories,
|
||||||
|
});
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
|
||||||
|
});
|
||||||
|
resolve(response);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const editItemCategory = (id, form) => {
|
export const editItemCategory = (id, form) => {
|
||||||
|
|||||||
@@ -11,12 +11,15 @@ export const editItem = ({ id, form }) => {
|
|||||||
|
|
||||||
export const fetchItems = ({ query }) => {
|
export const fetchItems = ({ query }) => {
|
||||||
return (dispatch, getState) => new Promise((resolve, reject) => {
|
return (dispatch, getState) => new Promise((resolve, reject) => {
|
||||||
const pageQuery = getState().accounts.tableQuery;
|
const pageQuery = getState().items.tableQuery;
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: t.ITEMS_TABLE_LOADING,
|
type: t.ITEMS_TABLE_LOADING,
|
||||||
payload: { loading: true },
|
payload: { loading: true },
|
||||||
});
|
});
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_LOADING,
|
||||||
|
});
|
||||||
ApiService.get(`items`, { params: { ...pageQuery, ...query } }).then(response => {
|
ApiService.get(`items`, { params: { ...pageQuery, ...query } }).then(response => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: t.ITEMS_SET,
|
type: t.ITEMS_SET,
|
||||||
@@ -32,8 +35,16 @@ export const fetchItems = ({ query }) => {
|
|||||||
type: t.ITEMS_TABLE_LOADING,
|
type: t.ITEMS_TABLE_LOADING,
|
||||||
payload: { loading: false },
|
payload: { loading: false },
|
||||||
});
|
});
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
|
||||||
|
});
|
||||||
resolve(response);
|
resolve(response);
|
||||||
}).catch(error => { reject(error); });
|
}).catch((error) => {
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
|
||||||
|
});
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,22 @@ export const deleteManualJournal = ({ id }) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const deleteBulkManualJournals = ({ ids }) => {
|
||||||
|
return (dispatch) => new Promise((resolve, reject) => {
|
||||||
|
ApiService.delete('accounting/manual-journals', { params: { ids } })
|
||||||
|
.then((response) => {
|
||||||
|
dispatch({
|
||||||
|
type: t.MANUAL_JOURNALS_BULK_DELETE,
|
||||||
|
payload: { ids },
|
||||||
|
});
|
||||||
|
resolve(response);
|
||||||
|
}).catch((error) => {
|
||||||
|
reject(error.response.data.errors || []);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const publishManualJournal = ({ id }) => {
|
export const publishManualJournal = ({ id }) => {
|
||||||
return (dispatch) =>
|
return (dispatch) =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
@@ -66,6 +82,9 @@ export const fetchManualJournalsTable = ({ query } = {}) => {
|
|||||||
return (dispatch, getState) =>
|
return (dispatch, getState) =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
const pageQuery = getState().manualJournals.tableQuery;
|
const pageQuery = getState().manualJournals.tableQuery;
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_LOADING,
|
||||||
|
});
|
||||||
dispatch({
|
dispatch({
|
||||||
type: t.MANUAL_JOURNALS_TABLE_LOADING,
|
type: t.MANUAL_JOURNALS_TABLE_LOADING,
|
||||||
loading: true,
|
loading: true,
|
||||||
@@ -74,20 +93,22 @@ export const fetchManualJournalsTable = ({ query } = {}) => {
|
|||||||
params: { ...pageQuery, ...query },
|
params: { ...pageQuery, ...query },
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: t.MANUAL_JOURNALS_PAGE_SET,
|
type: t.MANUAL_JOURNALS_PAGE_SET,
|
||||||
manual_journals: response.data.manualJournals,
|
manual_journals: response.data.manualJournals.results,
|
||||||
customViewId: response.data.customViewId,
|
customViewId: response.data.customViewId || -1,
|
||||||
});
|
});
|
||||||
dispatch({
|
dispatch({
|
||||||
type: t.MANUAL_JOURNALS_ITEMS_SET,
|
type: t.MANUAL_JOURNALS_ITEMS_SET,
|
||||||
manual_journals: response.data.manualJournals,
|
manual_journals: response.data.manualJournals.results,
|
||||||
});
|
});
|
||||||
dispatch({
|
dispatch({
|
||||||
type: t.MANUAL_JOURNALS_TABLE_LOADING,
|
type: t.MANUAL_JOURNALS_TABLE_LOADING,
|
||||||
loading: false,
|
loading: false,
|
||||||
});
|
});
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
|
||||||
|
});
|
||||||
resolve(response);
|
resolve(response);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import t from 'store/types';
|
import t from 'store/types';
|
||||||
import { createReducer } from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
|
import { createTableQueryReducers } from 'store/queryReducers';
|
||||||
import { omit } from 'lodash';
|
import { omit } from 'lodash';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
@@ -10,7 +11,7 @@ const initialState = {
|
|||||||
tableQuery: {},
|
tableQuery: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default createReducer(initialState, {
|
const reducer = createReducer(initialState, {
|
||||||
|
|
||||||
[t.MANUAL_JOURNAL_SET]: (state, action) => {
|
[t.MANUAL_JOURNAL_SET]: (state, action) => {
|
||||||
const { id, manualJournal } = action.payload;
|
const { id, manualJournal } = action.payload;
|
||||||
@@ -59,9 +60,22 @@ export default createReducer(initialState, {
|
|||||||
[t.MANUAL_JOURNAL_REMOVE]: (state, action) => {
|
[t.MANUAL_JOURNAL_REMOVE]: (state, action) => {
|
||||||
const { id } = action.payload;
|
const { id } = action.payload;
|
||||||
state.items = omit(state.items, [id]);
|
state.items = omit(state.items, [id]);
|
||||||
}
|
},
|
||||||
|
|
||||||
|
[t.MANUAL_JOURNALS_BULK_DELETE]: (state, action) => {
|
||||||
|
const { ids } = action.payload;
|
||||||
|
const items = { ...state.items };
|
||||||
|
|
||||||
|
ids.forEach((id) => {
|
||||||
|
if (typeof items[id] !== 'undefined') {
|
||||||
|
delete items[id];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
state.items = items;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default createTableQueryReducers('manual_journals', reducer);
|
||||||
|
|
||||||
export const getManualJournal = (state, id) => {
|
export const getManualJournal = (state, id) => {
|
||||||
return state.manualJournals.items[id];
|
return state.manualJournals.items[id];
|
||||||
|
|||||||
@@ -10,4 +10,5 @@ export default {
|
|||||||
MANUAL_JOURNAL_REMOVE: 'MANUAL_JOURNAL_REMOVE',
|
MANUAL_JOURNAL_REMOVE: 'MANUAL_JOURNAL_REMOVE',
|
||||||
|
|
||||||
MANUAL_JOURNAL_PUBLISH: 'MANUAL_JOURNAL_PUBLISH',
|
MANUAL_JOURNAL_PUBLISH: 'MANUAL_JOURNAL_PUBLISH',
|
||||||
|
MANUAL_JOURNALS_BULK_DELETE: 'MANUAL_JOURNALS_BULK_DELETE',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,12 +3,18 @@ import t from 'store/types';
|
|||||||
|
|
||||||
export const fetchResourceColumns = ({ resourceSlug }) => {
|
export const fetchResourceColumns = ({ resourceSlug }) => {
|
||||||
return (dispatch) => new Promise((resolve, reject) => {
|
return (dispatch) => new Promise((resolve, reject) => {
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_LOADING,
|
||||||
|
});
|
||||||
ApiService.get(`resources/${resourceSlug}/columns`).then((response) => {
|
ApiService.get(`resources/${resourceSlug}/columns`).then((response) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: t.RESOURCE_COLUMNS_SET,
|
type: t.RESOURCE_COLUMNS_SET,
|
||||||
columns: response.data.resource_columns,
|
columns: response.data.resource_columns,
|
||||||
resource_slug: resourceSlug,
|
resource_slug: resourceSlug,
|
||||||
});
|
});
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
|
||||||
|
});
|
||||||
resolve(response);
|
resolve(response);
|
||||||
}).catch((error) => { reject(error); });
|
}).catch((error) => { reject(error); });
|
||||||
});
|
});
|
||||||
@@ -16,12 +22,18 @@ export const fetchResourceColumns = ({ resourceSlug }) => {
|
|||||||
|
|
||||||
export const fetchResourceFields = ({ resourceSlug }) => {
|
export const fetchResourceFields = ({ resourceSlug }) => {
|
||||||
return (dispatch) => new Promise((resolve, reject) => {
|
return (dispatch) => new Promise((resolve, reject) => {
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_LOADING,
|
||||||
|
});
|
||||||
ApiService.get(`resources/${resourceSlug}/fields`).then((response) => {
|
ApiService.get(`resources/${resourceSlug}/fields`).then((response) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: t.RESOURCE_FIELDS_SET,
|
type: t.RESOURCE_FIELDS_SET,
|
||||||
fields: response.data.resource_fields,
|
fields: response.data.resource_fields,
|
||||||
resource_slug: resourceSlug,
|
resource_slug: resourceSlug,
|
||||||
});
|
});
|
||||||
|
dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
|
||||||
|
});
|
||||||
resolve(response);
|
resolve(response);
|
||||||
}).catch((error) => { reject(error); });
|
}).catch((error) => { reject(error); });
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export const pickItemsFromIds = (items, ids) => {
|
|||||||
export const getCurrentPageResults = (items, pages, pageNumber) => {
|
export const getCurrentPageResults = (items, pages, pageNumber) => {
|
||||||
const currentPage = pages[pageNumber]
|
const currentPage = pages[pageNumber]
|
||||||
return typeof currentPage == 'undefined' ?
|
return typeof currentPage == 'undefined' ?
|
||||||
[] : Object.values(pick(items || [], currentPage.ids));
|
[] : pickItemsFromIds(items, currentPage.ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getCurrentTotalResultsCount = (pagination, name) => {
|
export const getCurrentTotalResultsCount = (pagination, name) => {
|
||||||
|
|||||||
@@ -164,7 +164,8 @@
|
|||||||
|
|
||||||
h1{
|
h1{
|
||||||
font-size: 26px;
|
font-size: 26px;
|
||||||
font-weight: 100;
|
font-weight: 200;
|
||||||
|
color: #4d4c4c;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
h3{
|
h3{
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ $sidebar-popover-submenu-bg: rgb(1, 20, 62);
|
|||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
|
|
||||||
svg{
|
svg{
|
||||||
opacity: 0.35;
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,7 +185,6 @@ export default {
|
|||||||
check('entries.*.debit').optional({ nullable: true }).isNumeric().toInt(),
|
check('entries.*.debit').optional({ nullable: true }).isNumeric().toInt(),
|
||||||
check('entries.*.account_id').isNumeric().toInt(),
|
check('entries.*.account_id').isNumeric().toInt(),
|
||||||
check('entries.*.note').optional(),
|
check('entries.*.note').optional(),
|
||||||
check('attachment').optional(),
|
|
||||||
],
|
],
|
||||||
async handler(req, res) {
|
async handler(req, res) {
|
||||||
const validationErrors = validationResult(req);
|
const validationErrors = validationResult(req);
|
||||||
@@ -244,28 +243,9 @@ export default {
|
|||||||
if (journalNumber.length > 0) {
|
if (journalNumber.length > 0) {
|
||||||
errorReasons.push({ type: 'JOURNAL.NUMBER.ALREADY.EXISTS', code: 300 });
|
errorReasons.push({ type: 'JOURNAL.NUMBER.ALREADY.EXISTS', code: 300 });
|
||||||
}
|
}
|
||||||
|
|
||||||
const { attachment } = req.files;
|
|
||||||
const supportedMimes = ['image/png', 'image/jpeg'];
|
|
||||||
|
|
||||||
if (attachment && supportedMimes.indexOf(attachment.mimeType) === -1) {
|
|
||||||
errorReasons.push({ type: 'ATTACHMENT.MINETYPE.NOT.SUPPORTED', code: 400 });
|
|
||||||
}
|
|
||||||
if (errorReasons.length > 0) {
|
if (errorReasons.length > 0) {
|
||||||
return res.status(400).send({ errors: errorReasons });
|
return res.status(400).send({ errors: errorReasons });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attachment) {
|
|
||||||
const publicPath = 'storage/app/public/';
|
|
||||||
try {
|
|
||||||
await attachment.mv(`${publicPath}${req.organizationId}/${attachment.md5}.png`);
|
|
||||||
} catch (error) {
|
|
||||||
return res.status(400).send({
|
|
||||||
errors: [{ type: 'ATTACHMENT.UPLOAD.FAILED', code: 600 }],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save manual journal transaction.
|
// Save manual journal transaction.
|
||||||
const manualJournal = await ManualJournal.query().insert({
|
const manualJournal = await ManualJournal.query().insert({
|
||||||
reference: form.reference,
|
reference: form.reference,
|
||||||
@@ -276,7 +256,6 @@ export default {
|
|||||||
description: form.description,
|
description: form.description,
|
||||||
status: form.status,
|
status: form.status,
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
attachment_file: (attachment) ? `${attachment.md5}.png` : null,
|
|
||||||
});
|
});
|
||||||
const journalPoster = new JournalPoster();
|
const journalPoster = new JournalPoster();
|
||||||
|
|
||||||
@@ -682,13 +661,12 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes bulk manual journals.
|
* Deletes bulk manual journals.
|
||||||
*/
|
*/
|
||||||
deleteBulkManualJournals: {
|
deleteBulkManualJournals: {
|
||||||
validation: [
|
validation: [
|
||||||
query('ids').isArray({ min: 2 }),
|
query('ids').isArray({ min: 1 }),
|
||||||
query('ids.*').isNumeric().toInt(),
|
query('ids.*').isNumeric().toInt(),
|
||||||
],
|
],
|
||||||
async handler(req, res) {
|
async handler(req, res) {
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export default {
|
|||||||
check('name').exists(),
|
check('name').exists(),
|
||||||
check('type').exists().trim().escape()
|
check('type').exists().trim().escape()
|
||||||
.isIn(['service', 'non-inventory', 'inventory']),
|
.isIn(['service', 'non-inventory', 'inventory']),
|
||||||
check('sku').optional().trim().escape(),
|
check('sku').optional({ nullable: true }).trim().escape(),
|
||||||
check('cost_price').exists().isNumeric().toFloat(),
|
check('cost_price').exists().isNumeric().toFloat(),
|
||||||
check('sell_price').exists().isNumeric().toFloat(),
|
check('sell_price').exists().isNumeric().toFloat(),
|
||||||
check('cost_account_id').exists().isInt().toInt(),
|
check('cost_account_id').exists().isInt().toInt(),
|
||||||
@@ -61,14 +61,13 @@ export default {
|
|||||||
.exists()
|
.exists()
|
||||||
.isInt()
|
.isInt()
|
||||||
.toInt(),
|
.toInt(),
|
||||||
check('category_id').optional().isInt().toInt(),
|
check('category_id').optional({ nullable: true }).isInt().toInt(),
|
||||||
|
|
||||||
check('custom_fields').optional().isArray({ min: 1 }),
|
check('custom_fields').optional().isArray({ min: 1 }),
|
||||||
check('custom_fields.*.key').exists().isNumeric().toInt(),
|
check('custom_fields.*.key').exists().isNumeric().toInt(),
|
||||||
check('custom_fields.*.value').exists(),
|
check('custom_fields.*.value').exists(),
|
||||||
|
|
||||||
check('note').optional(),
|
check('note').optional(),
|
||||||
check('attachment').optional(),
|
|
||||||
],
|
],
|
||||||
async handler(req, res) {
|
async handler(req, res) {
|
||||||
const validationErrors = validationResult(req);
|
const validationErrors = validationResult(req);
|
||||||
@@ -119,13 +118,6 @@ export default {
|
|||||||
errorReasons.push({ type: 'FIELD_KEY_NOT_FOUND', code: 150, fields: notFoundFields });
|
errorReasons.push({ type: 'FIELD_KEY_NOT_FOUND', code: 150, fields: notFoundFields });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const { attachment } = req.files;
|
|
||||||
const attachmentsMimes = ['image/png', 'image/jpeg'];
|
|
||||||
|
|
||||||
// Validate the attachment.
|
|
||||||
if (attachment && attachmentsMimes.indexOf(attachment.mimetype) === -1) {
|
|
||||||
errorReasons.push({ type: 'ATTACHMENT.MINETYPE.NOT.SUPPORTED', code: 160 });
|
|
||||||
}
|
|
||||||
const [
|
const [
|
||||||
costAccount,
|
costAccount,
|
||||||
sellAccount,
|
sellAccount,
|
||||||
@@ -150,10 +142,6 @@ export default {
|
|||||||
if (errorReasons.length > 0) {
|
if (errorReasons.length > 0) {
|
||||||
return res.boom.badRequest(null, { errors: errorReasons });
|
return res.boom.badRequest(null, { errors: errorReasons });
|
||||||
}
|
}
|
||||||
if (attachment) {
|
|
||||||
const publicPath = 'storage/app/public/';
|
|
||||||
await attachment.mv(`${publicPath}${req.organizationId}/${attachment.md5}.png`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const item = await Item.query().insertAndFetch({
|
const item = await Item.query().insertAndFetch({
|
||||||
name: form.name,
|
name: form.name,
|
||||||
@@ -164,7 +152,6 @@ export default {
|
|||||||
cost_account_id: form.cost_account_id,
|
cost_account_id: form.cost_account_id,
|
||||||
currency_code: form.currency_code,
|
currency_code: form.currency_code,
|
||||||
note: form.note,
|
note: form.note,
|
||||||
attachment_file: (attachment) ? `${attachment.md5}.png` : null,
|
|
||||||
});
|
});
|
||||||
return res.status(200).send({ id: item.id });
|
return res.status(200).send({ id: item.id });
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user