mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 14:20:31 +00:00
WIP Feature : categoriesSelectList & Fix: Items
This commit is contained in:
49
client/src/components/CategoriesSelectList.js
Normal file
49
client/src/components/CategoriesSelectList.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import React, { useCallback } from 'react';
|
||||||
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
|
import { ListSelect } from 'components';
|
||||||
|
import { MenuItem } from '@blueprintjs/core';
|
||||||
|
|
||||||
|
export default function CategoriesSelectList({
|
||||||
|
categoriesList,
|
||||||
|
selecetedCategoryId,
|
||||||
|
defaultSelectText = <T id={'select_category'} />,
|
||||||
|
onCategorySelected,
|
||||||
|
...restProps
|
||||||
|
}) {
|
||||||
|
|
||||||
|
// Filter Items Category
|
||||||
|
const filterItemCategory = (query, item, _index, exactMatch) => {
|
||||||
|
const normalizedTitle = item.name.toLowerCase();
|
||||||
|
const normalizedQuery = query.toLowerCase();
|
||||||
|
if (exactMatch) {
|
||||||
|
return normalizedTitle === normalizedQuery;
|
||||||
|
} else {
|
||||||
|
return `${item.code} ${normalizedTitle}`.indexOf(normalizedQuery) >= 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleItemCategorySelected = useCallback(
|
||||||
|
(ItemCategory) => onCategorySelected && onCategorySelected(ItemCategory),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
const categoryItem = useCallback(
|
||||||
|
(item, { handleClick }) => (
|
||||||
|
<MenuItem key={item.id} text={item.name} onClick={handleClick} />
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ListSelect
|
||||||
|
items={categoriesList}
|
||||||
|
selectedItemProp={'id'}
|
||||||
|
selectedItem={selecetedCategoryId}
|
||||||
|
labelProp={'name'}
|
||||||
|
defaultText={defaultSelectText}
|
||||||
|
onItemSelect={handleItemCategorySelected}
|
||||||
|
itemPredicate={filterItemCategory}
|
||||||
|
itemRenderer={categoryItem}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -25,6 +25,8 @@ import Dialog from './Dialog/Dialog';
|
|||||||
import DialogContent from './Dialog/DialogContent';
|
import DialogContent from './Dialog/DialogContent';
|
||||||
import DialogSuspense from './Dialog/DialogSuspense';
|
import DialogSuspense from './Dialog/DialogSuspense';
|
||||||
import InputPrependButton from './Forms/InputPrependButton';
|
import InputPrependButton from './Forms/InputPrependButton';
|
||||||
|
import CategoriesSelectList from './CategoriesSelectList';
|
||||||
|
|
||||||
const Hint = FieldHint;
|
const Hint = FieldHint;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@@ -55,5 +57,6 @@ export {
|
|||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogSuspense,
|
DialogSuspense,
|
||||||
InputPrependButton
|
InputPrependButton,
|
||||||
};
|
CategoriesSelectList
|
||||||
|
};
|
||||||
|
|||||||
@@ -23,7 +23,11 @@ import ErrorMessage from 'components/ErrorMessage';
|
|||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
import MoneyInputGroup from 'components/MoneyInputGroup';
|
import MoneyInputGroup from 'components/MoneyInputGroup';
|
||||||
import Dragzone from 'components/Dragzone';
|
import Dragzone from 'components/Dragzone';
|
||||||
import { ListSelect, AccountsSelectList, If } from 'components';
|
import {
|
||||||
|
ListSelect,
|
||||||
|
AccountsSelectList,
|
||||||
|
CategoriesSelectList,
|
||||||
|
} from 'components';
|
||||||
|
|
||||||
import withItemsActions from 'containers/Items/withItemsActions';
|
import withItemsActions from 'containers/Items/withItemsActions';
|
||||||
import withItemCategories from 'containers/Items/withItemCategories';
|
import withItemCategories from 'containers/Items/withItemCategories';
|
||||||
@@ -170,7 +174,7 @@ const ItemForm = ({
|
|||||||
},
|
},
|
||||||
onSubmit: (values, { setSubmitting, resetForm, setErrors }) => {
|
onSubmit: (values, { setSubmitting, resetForm, setErrors }) => {
|
||||||
const saveItem = (mediaIds) => {
|
const saveItem = (mediaIds) => {
|
||||||
const formValues = { ...values, media_ids: mediaIds };
|
const formValues = { ...values };
|
||||||
if (itemDetail && itemDetail.id) {
|
if (itemDetail && itemDetail.id) {
|
||||||
requestEditItem(itemDetail.id, formValues)
|
requestEditItem(itemDetail.id, formValues)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
@@ -222,29 +226,6 @@ const ItemForm = ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const accountItem = useCallback(
|
|
||||||
(item, { handleClick }) => (
|
|
||||||
<MenuItem
|
|
||||||
key={item.id}
|
|
||||||
text={item.name}
|
|
||||||
label={item.code}
|
|
||||||
onClick={handleClick}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
// Filter Account Items
|
|
||||||
const filterAccounts = (query, item, _index, exactMatch) => {
|
|
||||||
const normalizedTitle = item.name.toLowerCase();
|
|
||||||
const normalizedQuery = query.toLowerCase();
|
|
||||||
if (exactMatch) {
|
|
||||||
return normalizedTitle === normalizedQuery;
|
|
||||||
} else {
|
|
||||||
return `${item.code} ${normalizedTitle}`.indexOf(normalizedQuery) >= 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onItemAccountSelect = useCallback(
|
const onItemAccountSelect = useCallback(
|
||||||
(filedName) => {
|
(filedName) => {
|
||||||
return (account) => {
|
return (account) => {
|
||||||
@@ -254,13 +235,6 @@ const ItemForm = ({
|
|||||||
[setFieldValue],
|
[setFieldValue],
|
||||||
);
|
);
|
||||||
|
|
||||||
const categoryItem = useCallback(
|
|
||||||
(item, { handleClick }) => (
|
|
||||||
<MenuItem key={item.id} text={item.name} onClick={handleClick} />
|
|
||||||
),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const requiredSpan = useMemo(() => <span class="required">*</span>, []);
|
const requiredSpan = useMemo(() => <span class="required">*</span>, []);
|
||||||
const infoIcon = useMemo(() => <Icon icon="info-circle" iconSize={12} />, []);
|
const infoIcon = useMemo(() => <Icon icon="info-circle" iconSize={12} />, []);
|
||||||
|
|
||||||
@@ -374,17 +348,11 @@ const ItemForm = ({
|
|||||||
Classes.FILL,
|
Classes.FILL,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<ListSelect
|
<CategoriesSelectList
|
||||||
items={categoriesList}
|
categoriesList={categoriesList}
|
||||||
noResults={<MenuItem disabled={true} text="No results." />}
|
selecetedCategoryId={values.category_id}
|
||||||
itemRenderer={categoryItem}
|
onCategorySelected={onItemAccountSelect('category_id')}
|
||||||
itemPredicate={filterAccounts}
|
|
||||||
popoverProps={{ minimal: true }}
|
popoverProps={{ minimal: true }}
|
||||||
onItemSelect={onItemAccountSelect('category_id')}
|
|
||||||
selectedItem={values.customer_id}
|
|
||||||
selectedItemProp={'id'}
|
|
||||||
defaultText={<T id={'select_category'} />}
|
|
||||||
labelProp={'name'}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -40,11 +40,8 @@ const ItemFormContainer = ({
|
|||||||
const fetchItemDetail = useQuery(
|
const fetchItemDetail = useQuery(
|
||||||
['item', id],
|
['item', id],
|
||||||
(key, _id) => requestFetchItem(_id),
|
(key, _id) => requestFetchItem(_id),
|
||||||
{
|
{ enabled: id && id },
|
||||||
enabled: !!id,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleFormSubmit = useCallback(
|
const handleFormSubmit = useCallback(
|
||||||
(payload) => {
|
(payload) => {
|
||||||
payload.redirect && history.push('/items');
|
payload.redirect && history.push('/items');
|
||||||
|
|||||||
@@ -9,9 +9,7 @@ import {
|
|||||||
Intent,
|
Intent,
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||||
import DataTable from 'components/DataTable';
|
import { Icon, DataTable, Money, If, Choose } from 'components';
|
||||||
import Icon from 'components/Icon';
|
|
||||||
import Money from 'components/Money';
|
|
||||||
|
|
||||||
import LoadingIndicator from 'components/LoadingIndicator';
|
import LoadingIndicator from 'components/LoadingIndicator';
|
||||||
import withItems from 'containers/Items/withItems';
|
import withItems from 'containers/Items/withItems';
|
||||||
@@ -56,14 +54,19 @@ const ItemsDataTable = ({
|
|||||||
const actionMenuList = useCallback(
|
const actionMenuList = useCallback(
|
||||||
(item) => (
|
(item) => (
|
||||||
<Menu>
|
<Menu>
|
||||||
<MenuItem text={formatMessage({ id: 'view_details' })} />
|
<MenuItem
|
||||||
|
icon={<Icon icon="reader-18" />}
|
||||||
|
text={formatMessage({ id: 'view_details' })}
|
||||||
|
/>
|
||||||
<MenuDivider />
|
<MenuDivider />
|
||||||
<MenuItem
|
<MenuItem
|
||||||
|
icon={<Icon icon="pen-18" />}
|
||||||
text={formatMessage({ id: 'edit_item' })}
|
text={formatMessage({ id: 'edit_item' })}
|
||||||
onClick={handleEditItem(item)}
|
onClick={handleEditItem(item)}
|
||||||
/>
|
/>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
text={formatMessage({ id: 'delete_item' })}
|
text={formatMessage({ id: 'delete_item' })}
|
||||||
|
icon={<Icon icon="trash-16" iconSize={16} />}
|
||||||
onClick={handleDeleteItem(item)}
|
onClick={handleDeleteItem(item)}
|
||||||
intent={Intent.DANGER}
|
intent={Intent.DANGER}
|
||||||
/>
|
/>
|
||||||
@@ -72,9 +75,12 @@ const ItemsDataTable = ({
|
|||||||
[handleEditItem, handleDeleteItem, formatMessage],
|
[handleEditItem, handleDeleteItem, formatMessage],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleRowContextMenu = useCallback((cell) => {
|
const handleRowContextMenu = useCallback(
|
||||||
return actionMenuList(cell.row.original);
|
(cell) => {
|
||||||
}, [actionMenuList]);
|
return actionMenuList(cell.row.original);
|
||||||
|
},
|
||||||
|
[actionMenuList],
|
||||||
|
);
|
||||||
|
|
||||||
const columns = useMemo(
|
const columns = useMemo(
|
||||||
() => [
|
() => [
|
||||||
@@ -155,7 +161,6 @@ const ItemsDataTable = ({
|
|||||||
},
|
},
|
||||||
[onSelectedRowsChange],
|
[onSelectedRowsChange],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LoadingIndicator loading={loading} mount={false}>
|
<LoadingIndicator loading={loading} mount={false}>
|
||||||
<DataTable
|
<DataTable
|
||||||
|
|||||||
@@ -211,6 +211,8 @@ export default {
|
|||||||
once_delete_this_item_you_will_able_to_restore_it: `Once you delete this item, you won\'t be able to restore the item later. Are you sure you want to delete ?<br /><br />If you're not sure, you can inactivate it instead.`,
|
once_delete_this_item_you_will_able_to_restore_it: `Once you delete this item, you won\'t be able to restore the item later. Are you sure you want to delete ?<br /><br />If you're not sure, you can inactivate it instead.`,
|
||||||
the_item_has_been_successfully_deleted:
|
the_item_has_been_successfully_deleted:
|
||||||
'The item has been successfully deleted.',
|
'The item has been successfully deleted.',
|
||||||
|
the_item_has_been_successfully_edited:
|
||||||
|
'The item #{number} has been successfully edited.',
|
||||||
the_item_category_has_been_successfully_created:
|
the_item_category_has_been_successfully_created:
|
||||||
'The item category has been successfully created.',
|
'The item category has been successfully created.',
|
||||||
the_item_category_has_been_successfully_edited:
|
the_item_category_has_been_successfully_edited:
|
||||||
|
|||||||
Reference in New Issue
Block a user