mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 05:10:31 +00:00
fix bugs in items form.
This commit is contained in:
@@ -117,8 +117,7 @@ function AccountsChart({
|
||||
console.log(accounts);
|
||||
};
|
||||
|
||||
const handleFilterChanged = useCallback(() => {
|
||||
|
||||
const handleFilterChanged = useCallback(() => {
|
||||
fetchAccountsHook.execute();
|
||||
}, [fetchAccountsHook]);
|
||||
|
||||
|
||||
@@ -6,11 +6,13 @@ import ItemForm from 'components/Items/ItemForm';
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import ItemsConnect from 'connectors/Items.connect';
|
||||
import AccountsConnect from 'connectors/Accounts.connector';
|
||||
import ItemCategoryConnect from 'connectors/ItemsCategory.connect';
|
||||
import { compose } from 'utils';
|
||||
|
||||
const ItemFormContainer = ({
|
||||
changePageTitle,
|
||||
fetchAccounts,
|
||||
requestFetchAccounts,
|
||||
requestFetchItemCategories,
|
||||
}) => {
|
||||
const { id } = useParams();
|
||||
useEffect(() => {
|
||||
@@ -21,11 +23,12 @@ const ItemFormContainer = ({
|
||||
|
||||
const fetchHook = useAsync(async () => {
|
||||
await Promise.all([
|
||||
fetchAccounts(),
|
||||
requestFetchAccounts(),
|
||||
requestFetchItemCategories(),
|
||||
]);
|
||||
});
|
||||
return (
|
||||
<DashboardInsider isLoading={fetchHook.loading} name={'item-form'}>
|
||||
<DashboardInsider loading={fetchHook.loading} name={'item-form'}>
|
||||
<ItemForm />
|
||||
</DashboardInsider>
|
||||
);
|
||||
@@ -35,4 +38,5 @@ export default compose(
|
||||
DashboardConnect,
|
||||
ItemsConnect,
|
||||
AccountsConnect,
|
||||
ItemCategoryConnect,
|
||||
)(ItemFormContainer);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import React, { useMemo, useCallback } from 'react';
|
||||
import { useRouteMatch, useHistory } from 'react-router-dom';
|
||||
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
Position,
|
||||
Button,
|
||||
Classes,
|
||||
Intent
|
||||
Intent,
|
||||
} from '@blueprintjs/core';
|
||||
import classNames from 'classnames';
|
||||
import Icon from 'components/Icon';
|
||||
@@ -28,8 +28,9 @@ const ItemsActionsBar = ({
|
||||
getResourceFields,
|
||||
getResourceViews,
|
||||
views,
|
||||
onFilterChange,
|
||||
bulkSelected
|
||||
onFilterChanged,
|
||||
bulkSelected,
|
||||
addItemsTableQueries,
|
||||
}) => {
|
||||
const { path } = useRouteMatch();
|
||||
const history = useHistory();
|
||||
@@ -46,7 +47,12 @@ const ItemsActionsBar = ({
|
||||
|
||||
const filterDropdown = FilterDropdown({
|
||||
fields: itemsFields,
|
||||
onFilterChange
|
||||
onFilterChange: (filterConditions) => {
|
||||
addItemsTableQueries({
|
||||
filter_roles: filterConditions || '',
|
||||
});
|
||||
onFilterChanged && onFilterChanged(filterConditions);
|
||||
}
|
||||
});
|
||||
|
||||
const hasBulkActionsSelected = useMemo(
|
||||
@@ -54,9 +60,9 @@ const ItemsActionsBar = ({
|
||||
[bulkSelected]
|
||||
);
|
||||
|
||||
const onClickNewCategory = () => {
|
||||
const onClickNewCategory = useCallback(() => {
|
||||
openDialog('item-form', {});
|
||||
};
|
||||
}, [openDialog]);
|
||||
|
||||
return (
|
||||
<DashboardActionsBar>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {useEffect, useMemo} from 'react';
|
||||
import React, {useEffect, useCallback, useMemo} from 'react';
|
||||
import {
|
||||
Button,
|
||||
Popover,
|
||||
@@ -6,87 +6,76 @@ import {
|
||||
MenuItem,
|
||||
MenuDivider,
|
||||
Position,
|
||||
Checkbox,
|
||||
} from '@blueprintjs/core'
|
||||
import LoadingIndicator from 'components/LoadingIndicator';
|
||||
import CustomViewConnect from 'connectors/View.connector';
|
||||
import ItemsConnect from 'connectors/Items.connect';
|
||||
import {useParams} from 'react-router-dom'
|
||||
import {compose} from 'utils';
|
||||
import useAsync from 'hooks/async';
|
||||
import DataTable from 'components/DataTable';
|
||||
import Icon from 'components/Icon';
|
||||
import {handleBooleanChange} from 'utils';
|
||||
import Money from 'components/Money';
|
||||
|
||||
|
||||
const ItemsDataTable = ({
|
||||
requestFetchItems,
|
||||
filterConditions,
|
||||
itemsTableLoading,
|
||||
currentPageItems,
|
||||
onEditItem,
|
||||
onDeleteItem,
|
||||
addBulkActionItem,
|
||||
removeBulkActionItem,
|
||||
onFetchData,
|
||||
}) => {
|
||||
const { custom_view_id: customViewId } = useParams();
|
||||
|
||||
const fetchHook = useAsync(async () => {
|
||||
await Promise.all([
|
||||
requestFetchItems({
|
||||
custom_view_id: customViewId,
|
||||
stringified_filter_roles: JSON.stringify(filterConditions),
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
const handleEditItem = (item) => () => { onEditItem(item); };
|
||||
const handleDeleteItem = (item) => () => { onDeleteItem(item); };
|
||||
const handleClickCheckboxBulk = (item) => handleBooleanChange((value) => {
|
||||
if (value) {
|
||||
addBulkActionItem(item.id);
|
||||
} else {
|
||||
removeBulkActionItem(item.id);
|
||||
}
|
||||
});
|
||||
|
||||
const actionMenuList = (item) =>
|
||||
|
||||
const actionMenuList = useCallback((item) =>
|
||||
(<Menu>
|
||||
<MenuItem text="View Details" />
|
||||
<MenuDivider />
|
||||
<MenuItem text="Edit Item" onClick={handleEditItem(item)} />
|
||||
<MenuItem text="Delete Item" onClick={handleDeleteItem(item)} />
|
||||
</Menu>);
|
||||
</Menu>), [handleEditItem, handleDeleteItem]);
|
||||
|
||||
const columns = useMemo(() => [
|
||||
{
|
||||
id: 'bulk_select',
|
||||
Cell: ({ cell }) =>
|
||||
(<Checkbox onChange={handleClickCheckboxBulk(cell.row.original)} />),
|
||||
},
|
||||
{
|
||||
Header: 'Item Name',
|
||||
accessor: 'name',
|
||||
className: "actions",
|
||||
},
|
||||
{
|
||||
Header: 'Cost Account',
|
||||
accessor: 'cost_account.name',
|
||||
className: "cost-account",
|
||||
},
|
||||
{
|
||||
Header: 'Sell Account',
|
||||
accessor: 'sell_account.name',
|
||||
className: "sell-account",
|
||||
},
|
||||
{
|
||||
Header: 'Inventory Account',
|
||||
accessor: 'inventory_account.name',
|
||||
className: "inventory-account",
|
||||
Header: 'SKU',
|
||||
accessor: 'sku',
|
||||
className: "sku",
|
||||
},
|
||||
{
|
||||
Header: 'Category',
|
||||
accessor: 'category.name',
|
||||
className: 'category',
|
||||
},
|
||||
{
|
||||
Header: 'Sell Price',
|
||||
accessor: row => (<Money amount={row.sell_price} currency={'USD'} />),
|
||||
className: 'sell-price',
|
||||
},
|
||||
{
|
||||
Header: 'Cost Price',
|
||||
accessor: row => (<Money amount={row.cost_price} currency={'USD'} />),
|
||||
className: 'cost-price',
|
||||
},
|
||||
// {
|
||||
// Header: 'Cost Account',
|
||||
// accessor: 'cost_account.name',
|
||||
// className: "cost-account",
|
||||
// },
|
||||
// {
|
||||
// Header: 'Sell Account',
|
||||
// accessor: 'sell_account.name',
|
||||
// className: "sell-account",
|
||||
// },
|
||||
// {
|
||||
// Header: 'Inventory Account',
|
||||
// accessor: 'inventory_account.name',
|
||||
// className: "inventory-account",
|
||||
// },
|
||||
|
||||
{
|
||||
id: 'actions',
|
||||
Cell: ({ cell }) => (
|
||||
@@ -96,14 +85,28 @@ const ItemsDataTable = ({
|
||||
<Button icon={<Icon icon="ellipsis-h" />} />
|
||||
</Popover>
|
||||
),
|
||||
className: 'actions',
|
||||
width: 50,
|
||||
},
|
||||
]);
|
||||
], [actionMenuList]);
|
||||
|
||||
const selectionColumn = useMemo(() => ({
|
||||
minWidth: 42,
|
||||
width: 42,
|
||||
maxWidth: 42,
|
||||
}), []);
|
||||
|
||||
const handleFetchData = useCallback((...args) => {
|
||||
onFetchData && onFetchData(...args)
|
||||
}, [onFetchData])
|
||||
|
||||
return (
|
||||
<LoadingIndicator loading={fetchHook.pending} spinnerSize={30}>
|
||||
<LoadingIndicator loading={itemsTableLoading} spinnerSize={30}>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={currentPageItems} />
|
||||
data={currentPageItems}
|
||||
selectionColumn={selectionColumn}
|
||||
onFetchData={handleFetchData} />
|
||||
</LoadingIndicator>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect, useCallback, useState } from 'react';
|
||||
import {
|
||||
Route,
|
||||
Switch,
|
||||
@@ -17,22 +17,24 @@ import ResourceConnect from 'connectors/Resource.connector';
|
||||
import DashboardConnect from 'connectors/Dashboard.connector';
|
||||
import ItemsConnect from 'connectors/Items.connect';
|
||||
import CustomViewsConnect from 'connectors/CustomView.connector'
|
||||
import DashboardViewsTabs from 'components/Accounts/AccountsViewsTabs';
|
||||
import ItemsViewsTabs from 'containers/Dashboard/Items/ItemsViewsTabs';
|
||||
import AppToaster from 'components/AppToaster';
|
||||
|
||||
|
||||
function ItemsList({
|
||||
changePageTitle,
|
||||
fetchResourceViews,
|
||||
fetchResourceFields,
|
||||
views,
|
||||
requestDeleteItem,
|
||||
requestFetchItems,
|
||||
addItemsTableQueries,
|
||||
}) {
|
||||
const [filterConditions, setFilterConditions] = useState([]);
|
||||
const [deleteItem, setDeleteItem] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
changePageTitle('Items List');
|
||||
}, []);
|
||||
}, [changePageTitle]);
|
||||
|
||||
const fetchHook = useAsync(async () => {
|
||||
await Promise.all([
|
||||
@@ -40,31 +42,68 @@ function ItemsList({
|
||||
fetchResourceFields('items'),
|
||||
])
|
||||
});
|
||||
const handleDeleteItem = (item) => { setDeleteItem(item); };
|
||||
|
||||
const fetchItems = useAsync(async () => {
|
||||
await Promise.all([
|
||||
requestFetchItems({ }),
|
||||
])
|
||||
});
|
||||
|
||||
const handleDeleteItem = useCallback((item) => {
|
||||
setDeleteItem(item);
|
||||
}, [setDeleteItem]);
|
||||
|
||||
const handleEditItem = () => {};
|
||||
const handleCancelDeleteItem = () => { setDeleteItem(false) };
|
||||
const handleConfirmDeleteItem = () => {
|
||||
|
||||
const handleCancelDeleteItem = useCallback(() => {
|
||||
setDeleteItem(false);
|
||||
}, [setDeleteItem]);
|
||||
|
||||
const handleConfirmDeleteItem = useCallback(() => {
|
||||
requestDeleteItem(deleteItem.id).then(() => {
|
||||
AppToaster.show({ message: 'the_item_has_been_deleted' });
|
||||
setDeleteItem(false);
|
||||
});
|
||||
};
|
||||
}, [requestDeleteItem, deleteItem]);
|
||||
|
||||
const handleFilterChange = (filter) => { setFilterConditions(filter); };
|
||||
const handleFetchData = useCallback(({ pageIndex, pageSize, sortBy }) => {
|
||||
addItemsTableQueries({
|
||||
...(sortBy.length > 0) ? {
|
||||
column_sort_by: sortBy[0].id,
|
||||
sort_by: sortBy[0].desc ? 'desc' : 'asc',
|
||||
} : {},
|
||||
});
|
||||
fetchItems.execute();
|
||||
}, [fetchItems, addItemsTableQueries]);
|
||||
|
||||
const handleFilterChanged = useCallback(() => {
|
||||
fetchItems.execute();
|
||||
}, [fetchItems]);
|
||||
|
||||
const handleCustomViewChanged = useCallback(() => {
|
||||
fetchItems.execute();
|
||||
}, [fetchItems]);
|
||||
|
||||
return (
|
||||
<DashboardInsider isLoading={fetchHook.pending} name={'items-list'}>
|
||||
<ItemsActionsBar views={views} onFilterChange={handleFilterChange} />
|
||||
<ItemsActionsBar
|
||||
onFilterChanged={handleFilterChanged}
|
||||
views={views} />
|
||||
|
||||
<DashboardPageContent>
|
||||
<Switch>
|
||||
<Route>
|
||||
<DashboardViewsTabs resourceName={'items'} />
|
||||
<Route
|
||||
exact={true}
|
||||
path={[
|
||||
'/dashboard/items/:custom_view_id/custom_view',
|
||||
'/dashboard/items'
|
||||
]}>
|
||||
<ItemsViewsTabs onViewChanged={handleCustomViewChanged} />
|
||||
|
||||
<ItemsDataTable
|
||||
filterConditions={filterConditions}
|
||||
onDeleteItem={handleDeleteItem}
|
||||
onEditItem={handleEditItem} />
|
||||
onEditItem={handleEditItem}
|
||||
onFetchData={handleFetchData} />
|
||||
|
||||
<Alert
|
||||
cancelButtonText="Cancel"
|
||||
|
||||
94
client/src/containers/Dashboard/Items/ItemsViewsTabs.js
Normal file
94
client/src/containers/Dashboard/Items/ItemsViewsTabs.js
Normal file
@@ -0,0 +1,94 @@
|
||||
import React, {useEffect} from 'react';
|
||||
import { useHistory } from 'react-router';
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
Alignment,
|
||||
Navbar,
|
||||
NavbarGroup,
|
||||
Tabs,
|
||||
Tab,
|
||||
Button
|
||||
} from '@blueprintjs/core';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import Icon from 'components/Icon';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { compose } from 'utils';
|
||||
import ItemsConnect from 'connectors/Items.connect';
|
||||
import DashboardConnect from 'connectors/Dashboard.connector';
|
||||
import {useUpdateEffect} from 'hooks';
|
||||
|
||||
function ItemsViewsTabs({
|
||||
views,
|
||||
setTopbarEditView,
|
||||
customViewChanged,
|
||||
addItemsTableQueries,
|
||||
onViewChanged,
|
||||
}) {
|
||||
const history = useHistory();
|
||||
const { custom_view_id: customViewId } = useParams();
|
||||
|
||||
const handleClickNewView = () => {
|
||||
setTopbarEditView(null);
|
||||
history.push('/dashboard/custom_views/items/new');
|
||||
};
|
||||
const handleViewLinkClick = () => {
|
||||
setTopbarEditView(customViewId);
|
||||
}
|
||||
|
||||
useUpdateEffect(() => {
|
||||
customViewChanged && customViewChanged(customViewId);
|
||||
|
||||
addItemsTableQueries({
|
||||
custom_view_id: customViewId || null,
|
||||
});
|
||||
onViewChanged && onViewChanged(customViewId);
|
||||
}, [customViewId]);
|
||||
|
||||
useEffect(() => {
|
||||
addItemsTableQueries({
|
||||
custom_view_id: customViewId,
|
||||
})
|
||||
}, [customViewId, addItemsTableQueries]);
|
||||
|
||||
const tabs = views.map(view => {
|
||||
const baseUrl = '/dashboard/items';
|
||||
const link = (
|
||||
<Link
|
||||
to={`${baseUrl}/${view.id}/custom_view`}
|
||||
onClick={handleViewLinkClick}
|
||||
>{view.name}</Link>
|
||||
);
|
||||
return <Tab
|
||||
id={`custom_view_${view.id}`}
|
||||
title={link} />;
|
||||
});
|
||||
return (
|
||||
<Navbar className='navbar--dashboard-views'>
|
||||
<NavbarGroup align={Alignment.LEFT}>
|
||||
<Tabs
|
||||
id='navbar'
|
||||
large={true}
|
||||
selectedTabId={`custom_view_${customViewId}`}
|
||||
className='tabs--dashboard-views'
|
||||
>
|
||||
<Tab
|
||||
id='all'
|
||||
title={<Link to={`/dashboard/items`}>All</Link>} />
|
||||
|
||||
{tabs}
|
||||
<Button
|
||||
className='button--new-view'
|
||||
icon={<Icon icon='plus' />}
|
||||
onClick={handleClickNewView}
|
||||
minimal={true}
|
||||
/>
|
||||
</Tabs>
|
||||
</NavbarGroup>
|
||||
</Navbar>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
ItemsConnect,
|
||||
DashboardConnect,
|
||||
)(ItemsViewsTabs);
|
||||
Reference in New Issue
Block a user