mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-21 15:20:34 +00:00
refactor(webapp): Accounts Select and MultiSelect components
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@blueprintjs-formik/core": "^0.2.1",
|
"@blueprintjs-formik/core": "^0.2.1",
|
||||||
"@blueprintjs-formik/datetime": "^0.3.4",
|
"@blueprintjs-formik/datetime": "^0.3.4",
|
||||||
"@blueprintjs-formik/select": "^0.1.4",
|
"@blueprintjs-formik/select": "^0.2.2",
|
||||||
"@blueprintjs/core": "^3.50.2",
|
"@blueprintjs/core": "^3.50.2",
|
||||||
"@blueprintjs/datetime": "^3.23.12",
|
"@blueprintjs/datetime": "^3.23.12",
|
||||||
"@blueprintjs/popover2": "^0.11.1",
|
"@blueprintjs/popover2": "^0.11.1",
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
// @ts-nocheck
|
|
||||||
import React from 'react';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import { MenuItem } from '@blueprintjs/core';
|
|
||||||
import { FMultiSelect } from '../Forms';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { Classes } from '@blueprintjs/popover2';
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {*} query
|
|
||||||
* @param {*} account
|
|
||||||
* @param {*} _index
|
|
||||||
* @param {*} exactMatch
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
const accountItemPredicate = (query, account, _index, exactMatch) => {
|
|
||||||
const normalizedTitle = account.name.toLowerCase();
|
|
||||||
const normalizedQuery = query.toLowerCase();
|
|
||||||
|
|
||||||
if (exactMatch) {
|
|
||||||
return normalizedTitle === normalizedQuery;
|
|
||||||
} else {
|
|
||||||
return `${account.code}. ${normalizedTitle}`.indexOf(normalizedQuery) >= 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {*} account
|
|
||||||
* @param {*} param1
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
const accountItemRenderer = (
|
|
||||||
account,
|
|
||||||
{ handleClick, modifiers, query },
|
|
||||||
{ isSelected },
|
|
||||||
) => {
|
|
||||||
return (
|
|
||||||
<MenuItem
|
|
||||||
icon={isSelected ? 'tick' : 'blank'}
|
|
||||||
text={account.name}
|
|
||||||
label={account.code}
|
|
||||||
key={account.id}
|
|
||||||
onClick={handleClick}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const accountSelectProps = {
|
|
||||||
itemPredicate: accountItemPredicate,
|
|
||||||
itemRenderer: accountItemRenderer,
|
|
||||||
valueAccessor: (item) => item.id,
|
|
||||||
labelAccessor: (item) => item.code,
|
|
||||||
tagRenderer: (item) => item.name,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* branches mulit select.
|
|
||||||
* @param {*} param0
|
|
||||||
* @returns {JSX.Element}
|
|
||||||
*/
|
|
||||||
export function AccountMultiSelect({ accounts, ...rest }) {
|
|
||||||
return (
|
|
||||||
<FMultiSelect
|
|
||||||
items={accounts}
|
|
||||||
popoverProps={{
|
|
||||||
minimal: true,
|
|
||||||
}}
|
|
||||||
{...accountSelectProps}
|
|
||||||
{...rest}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,31 +1,79 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { MenuItem } from '@blueprintjs/core';
|
import { MenuItem } from '@blueprintjs/core';
|
||||||
import { MultiSelect } from '../MultiSelectTaggable';
|
import { FMultiSelect } from '../Forms';
|
||||||
|
import { accountPredicate } from './_components';
|
||||||
|
import { filterAccountsByQuery, nestedArrayToflatten } from '@/utils';
|
||||||
|
import { MenuItemNestedText } from '../Menu';
|
||||||
|
|
||||||
export function AccountsMultiSelect({ ...multiSelectProps }) {
|
/**
|
||||||
|
* Default account item renderer of the list.
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
*/
|
||||||
|
const accountRenderer = (
|
||||||
|
item,
|
||||||
|
{ handleClick, modifiers, query },
|
||||||
|
{ isSelected },
|
||||||
|
) => {
|
||||||
|
if (!modifiers.matchesPredicate) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<MultiSelect
|
<MenuItem
|
||||||
itemRenderer={(
|
active={modifiers.active}
|
||||||
item,
|
disabled={modifiers.disabled}
|
||||||
{ active, selected, handleClick, modifiers, query },
|
text={<MenuItemNestedText level={item.account_level} text={item.name} />}
|
||||||
) => {
|
key={item.id}
|
||||||
return (
|
onClick={handleClick}
|
||||||
<MenuItem
|
icon={isSelected ? 'tick' : 'blank'}
|
||||||
active={active}
|
/>
|
||||||
icon={selected ? 'tick' : 'blank'}
|
);
|
||||||
text={item.name}
|
};
|
||||||
label={item.code}
|
|
||||||
key={item.id}
|
/**
|
||||||
onClick={handleClick}
|
* Accounts multi-select field binded with Formik form.
|
||||||
/>
|
* @param {*} param0
|
||||||
);
|
* @returns {JSX.Element}
|
||||||
}}
|
*/
|
||||||
|
export function AccountsMultiSelect({
|
||||||
|
items,
|
||||||
|
|
||||||
|
filterByRootTypes,
|
||||||
|
filterByParentTypes,
|
||||||
|
filterByTypes,
|
||||||
|
filterByNormal,
|
||||||
|
|
||||||
|
...rest
|
||||||
|
}) {
|
||||||
|
// Filters accounts based on the given filter props.
|
||||||
|
const filteredAccounts = useMemo(() => {
|
||||||
|
const flattenAccounts = nestedArrayToflatten(items);
|
||||||
|
|
||||||
|
return filterAccountsByQuery(flattenAccounts, {
|
||||||
|
filterByRootTypes,
|
||||||
|
filterByParentTypes,
|
||||||
|
filterByTypes,
|
||||||
|
filterByNormal,
|
||||||
|
});
|
||||||
|
}, [
|
||||||
|
items,
|
||||||
|
filterByRootTypes,
|
||||||
|
filterByParentTypes,
|
||||||
|
filterByTypes,
|
||||||
|
filterByNormal,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FMultiSelect
|
||||||
|
items={filteredAccounts}
|
||||||
|
valueAccessor={'id'}
|
||||||
|
textAccessor={'name'}
|
||||||
|
labelAccessor={'code'}
|
||||||
|
tagAccessor={'name'}
|
||||||
popoverProps={{ minimal: true }}
|
popoverProps={{ minimal: true }}
|
||||||
fill={true}
|
itemPredicate={accountPredicate}
|
||||||
tagRenderer={(item) => item.name}
|
itemRenderer={accountRenderer}
|
||||||
resetOnSelect={true}
|
{...rest}
|
||||||
{...multiSelectProps}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
105
packages/webapp/src/components/Accounts/AccountsSelect.tsx
Normal file
105
packages/webapp/src/components/Accounts/AccountsSelect.tsx
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React, { useMemo } from 'react';
|
||||||
|
import * as R from 'ramda';
|
||||||
|
import intl from 'react-intl-universal';
|
||||||
|
import { MenuItem } from '@blueprintjs/core';
|
||||||
|
import {
|
||||||
|
MenuItemNestedText,
|
||||||
|
FormattedMessage as T,
|
||||||
|
FSelect,
|
||||||
|
} from '@/components';
|
||||||
|
import { filterAccountsByQuery, nestedArrayToflatten } from '@/utils';
|
||||||
|
import { accountPredicate } from './_components';
|
||||||
|
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||||
|
|
||||||
|
// Create new account renderer.
|
||||||
|
const createNewItemRenderer = (query, active, handleClick) => {
|
||||||
|
return (
|
||||||
|
<MenuItem
|
||||||
|
icon="add"
|
||||||
|
text={intl.get('list.create', { value: `"${query}"` })}
|
||||||
|
active={active}
|
||||||
|
onClick={handleClick}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create new item from the given query string.
|
||||||
|
const createNewItemFromQuery = (name) => {
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default account item renderer.
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
*/
|
||||||
|
const accountRenderer = (item, { handleClick, modifiers, query }) => {
|
||||||
|
if (!modifiers.matchesPredicate) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<MenuItem
|
||||||
|
active={modifiers.active}
|
||||||
|
disabled={modifiers.disabled}
|
||||||
|
label={item.code}
|
||||||
|
key={item.id}
|
||||||
|
text={<MenuItemNestedText level={item.account_level} text={item.name} />}
|
||||||
|
onClick={handleClick}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accounts select field binded with Formik form.
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
*/
|
||||||
|
function AccountsSelectRoot({
|
||||||
|
// #withDialogActions
|
||||||
|
openDialog,
|
||||||
|
|
||||||
|
// #ownProps
|
||||||
|
items,
|
||||||
|
|
||||||
|
filterByParentTypes,
|
||||||
|
filterByTypes,
|
||||||
|
filterByNormal,
|
||||||
|
filterByRootTypes,
|
||||||
|
|
||||||
|
...restProps
|
||||||
|
}) {
|
||||||
|
// Filters accounts based on filter props.
|
||||||
|
const filteredAccounts = useMemo(() => {
|
||||||
|
const flattenAccounts = nestedArrayToflatten(items);
|
||||||
|
|
||||||
|
const filteredAccounts = filterAccountsByQuery(flattenAccounts, {
|
||||||
|
filterByRootTypes,
|
||||||
|
filterByParentTypes,
|
||||||
|
filterByTypes,
|
||||||
|
filterByNormal,
|
||||||
|
});
|
||||||
|
return filteredAccounts;
|
||||||
|
}, [
|
||||||
|
items,
|
||||||
|
filterByRootTypes,
|
||||||
|
filterByParentTypes,
|
||||||
|
filterByTypes,
|
||||||
|
filterByNormal,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FSelect
|
||||||
|
items={filteredAccounts}
|
||||||
|
textAccessor={'name'}
|
||||||
|
labelAccessor={'code'}
|
||||||
|
valueAccessor={'id'}
|
||||||
|
popoverProps={{ minimal: true, usePortal: true, inline: false }}
|
||||||
|
itemPredicate={accountPredicate}
|
||||||
|
itemRenderer={accountRenderer}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AccountsSelect = R.compose(withDialogActions)(AccountsSelectRoot);
|
||||||
@@ -1,177 +0,0 @@
|
|||||||
// @ts-nocheck
|
|
||||||
import React, { useCallback, useState, useEffect, useMemo } from 'react';
|
|
||||||
import intl from 'react-intl-universal';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { MenuItem, Button } from '@blueprintjs/core';
|
|
||||||
import { Select } from '@blueprintjs/select';
|
|
||||||
import * as R from 'ramda';
|
|
||||||
|
|
||||||
import { MenuItemNestedText, FormattedMessage as T } from '@/components';
|
|
||||||
import { nestedArrayToflatten, filterAccountsByQuery } from '@/utils';
|
|
||||||
|
|
||||||
import { CLASSES } from '@/constants/classes';
|
|
||||||
import { DialogsName } from '@/constants/dialogs';
|
|
||||||
|
|
||||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
|
||||||
|
|
||||||
// Create new account renderer.
|
|
||||||
const createNewItemRenderer = (query, active, handleClick) => {
|
|
||||||
return (
|
|
||||||
<MenuItem
|
|
||||||
icon="add"
|
|
||||||
text={intl.get('list.create', { value: `"${query}"` })}
|
|
||||||
active={active}
|
|
||||||
onClick={handleClick}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create new item from the given query string.
|
|
||||||
const createNewItemFromQuery = (name) => {
|
|
||||||
return {
|
|
||||||
name,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Filters accounts items.
|
|
||||||
const filterAccountsPredicater = (query, account, _index, exactMatch) => {
|
|
||||||
const normalizedTitle = account.name.toLowerCase();
|
|
||||||
const normalizedQuery = query.toLowerCase();
|
|
||||||
|
|
||||||
if (exactMatch) {
|
|
||||||
return normalizedTitle === normalizedQuery;
|
|
||||||
} else {
|
|
||||||
return `${account.code} ${normalizedTitle}`.indexOf(normalizedQuery) >= 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accounts select list.
|
|
||||||
*/
|
|
||||||
function AccountsSelectListRoot({
|
|
||||||
// #withDialogActions
|
|
||||||
openDialog,
|
|
||||||
|
|
||||||
// #ownProps
|
|
||||||
accounts,
|
|
||||||
initialAccountId,
|
|
||||||
selectedAccountId,
|
|
||||||
defaultSelectText = 'Select account',
|
|
||||||
onAccountSelected,
|
|
||||||
disabled = false,
|
|
||||||
popoverFill = false,
|
|
||||||
|
|
||||||
filterByParentTypes,
|
|
||||||
filterByTypes,
|
|
||||||
filterByNormal,
|
|
||||||
filterByRootTypes,
|
|
||||||
|
|
||||||
allowCreate,
|
|
||||||
|
|
||||||
buttonProps = {},
|
|
||||||
}) {
|
|
||||||
const flattenAccounts = useMemo(
|
|
||||||
() => nestedArrayToflatten(accounts),
|
|
||||||
[accounts],
|
|
||||||
);
|
|
||||||
|
|
||||||
// Filters accounts based on filter props.
|
|
||||||
const filteredAccounts = useMemo(() => {
|
|
||||||
let filteredAccounts = filterAccountsByQuery(flattenAccounts, {
|
|
||||||
filterByRootTypes,
|
|
||||||
filterByParentTypes,
|
|
||||||
filterByTypes,
|
|
||||||
filterByNormal,
|
|
||||||
});
|
|
||||||
return filteredAccounts;
|
|
||||||
}, [
|
|
||||||
flattenAccounts,
|
|
||||||
filterByRootTypes,
|
|
||||||
filterByParentTypes,
|
|
||||||
filterByTypes,
|
|
||||||
filterByNormal,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Find initial account object to set it as default account in initial render.
|
|
||||||
const initialAccount = useMemo(
|
|
||||||
() => filteredAccounts.find((a) => a.id === initialAccountId),
|
|
||||||
[initialAccountId, filteredAccounts],
|
|
||||||
);
|
|
||||||
|
|
||||||
// Select account item.
|
|
||||||
const [selectedAccount, setSelectedAccount] = useState(
|
|
||||||
initialAccount || null,
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (typeof selectedAccountId !== 'undefined') {
|
|
||||||
const account = selectedAccountId
|
|
||||||
? filteredAccounts.find((a) => a.id === selectedAccountId)
|
|
||||||
: null;
|
|
||||||
setSelectedAccount(account);
|
|
||||||
}
|
|
||||||
}, [selectedAccountId, filteredAccounts, setSelectedAccount]);
|
|
||||||
|
|
||||||
// Account item of select accounts field.
|
|
||||||
const accountItem = useCallback((item, { handleClick, modifiers, query }) => {
|
|
||||||
return (
|
|
||||||
<MenuItem
|
|
||||||
text={<MenuItemNestedText level={item.level} text={item.name} />}
|
|
||||||
label={item.code}
|
|
||||||
key={item.id}
|
|
||||||
onClick={handleClick}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Handle the account item select.
|
|
||||||
const handleAccountSelect = useCallback(
|
|
||||||
(account) => {
|
|
||||||
if (account.id) {
|
|
||||||
setSelectedAccount({ ...account });
|
|
||||||
onAccountSelected && onAccountSelected(account);
|
|
||||||
} else {
|
|
||||||
openDialog(DialogsName.AccountForm);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[setSelectedAccount, onAccountSelected, openDialog],
|
|
||||||
);
|
|
||||||
|
|
||||||
// Maybe inject new item props to select component.
|
|
||||||
const maybeCreateNewItemRenderer = allowCreate ? createNewItemRenderer : null;
|
|
||||||
const maybeCreateNewItemFromQuery = allowCreate
|
|
||||||
? createNewItemFromQuery
|
|
||||||
: null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Select
|
|
||||||
items={filteredAccounts}
|
|
||||||
noResults={<MenuItem disabled={true} text={<T id={'no_accounts'} />} />}
|
|
||||||
itemRenderer={accountItem}
|
|
||||||
itemPredicate={filterAccountsPredicater}
|
|
||||||
popoverProps={{
|
|
||||||
minimal: true,
|
|
||||||
usePortal: !popoverFill,
|
|
||||||
inline: popoverFill,
|
|
||||||
}}
|
|
||||||
filterable={true}
|
|
||||||
onItemSelect={handleAccountSelect}
|
|
||||||
disabled={disabled}
|
|
||||||
className={classNames('form-group--select-list', {
|
|
||||||
[CLASSES.SELECT_LIST_FILL_POPOVER]: popoverFill,
|
|
||||||
})}
|
|
||||||
createNewItemRenderer={maybeCreateNewItemRenderer}
|
|
||||||
createNewItemFromQuery={maybeCreateNewItemFromQuery}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
disabled={disabled}
|
|
||||||
text={selectedAccount ? selectedAccount.name : defaultSelectText}
|
|
||||||
{...buttonProps}
|
|
||||||
/>
|
|
||||||
</Select>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const AccountsSelectList = R.compose(withDialogActions)(
|
|
||||||
AccountsSelectListRoot,
|
|
||||||
);
|
|
||||||
@@ -1,49 +1,15 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React, { useCallback } from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
import { FSelect } from '@/components/Forms';
|
||||||
import { ListSelect } from '@/components';
|
|
||||||
import { CLASSES } from '@/constants/classes';
|
|
||||||
|
|
||||||
export function AccountsTypesSelect({
|
|
||||||
accountsTypes,
|
|
||||||
selectedTypeId,
|
|
||||||
defaultSelectText = 'Select account type',
|
|
||||||
onTypeSelected,
|
|
||||||
disabled = false,
|
|
||||||
popoverFill = false,
|
|
||||||
...restProps
|
|
||||||
}) {
|
|
||||||
// Filters accounts types items.
|
|
||||||
const filterAccountTypeItems = (query, accountType, _index, exactMatch) => {
|
|
||||||
const normalizedTitle = accountType.label.toLowerCase();
|
|
||||||
const normalizedQuery = query.toLowerCase();
|
|
||||||
|
|
||||||
if (exactMatch) {
|
|
||||||
return normalizedTitle === normalizedQuery;
|
|
||||||
} else {
|
|
||||||
return normalizedTitle.indexOf(normalizedQuery) >= 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle item selected.
|
|
||||||
const handleItemSelected = (accountType) => {
|
|
||||||
onTypeSelected && onTypeSelected(accountType);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
export function AccountsTypesSelect({ ...props }) {
|
||||||
return (
|
return (
|
||||||
<ListSelect
|
<FSelect
|
||||||
items={accountsTypes}
|
valueAccessor={'key'}
|
||||||
selectedItemProp={'key'}
|
labelAccessor={'label'}
|
||||||
selectedItem={selectedTypeId}
|
textAccessor={'label'}
|
||||||
textProp={'label'}
|
placeholder={'Select an account...'}
|
||||||
defaultText={defaultSelectText}
|
{...props}
|
||||||
onItemSelect={handleItemSelected}
|
|
||||||
itemPredicate={filterAccountTypeItems}
|
|
||||||
disabled={disabled}
|
|
||||||
className={classNames('form-group--select-list', {
|
|
||||||
[CLASSES.SELECT_LIST_FILL_POPOVER]: popoverFill,
|
|
||||||
})}
|
|
||||||
{...restProps}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
16
packages/webapp/src/components/Accounts/_components.tsx
Normal file
16
packages/webapp/src/components/Accounts/_components.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { MenuItem } from '@blueprintjs/core';
|
||||||
|
import { MenuItemNestedText } from '../Menu';
|
||||||
|
|
||||||
|
|
||||||
|
// Filters accounts items.
|
||||||
|
export const accountPredicate = (query, account, _index, exactMatch) => {
|
||||||
|
const normalizedTitle = account.name.toLowerCase();
|
||||||
|
const normalizedQuery = query.toLowerCase();
|
||||||
|
|
||||||
|
if (exactMatch) {
|
||||||
|
return normalizedTitle === normalizedQuery;
|
||||||
|
} else {
|
||||||
|
return `${account.code} ${normalizedTitle}`.indexOf(normalizedQuery) >= 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
export * from './AccountMultiSelect';
|
export * from './AccountsSelect';
|
||||||
export * from './AccountsMultiSelect';
|
export * from './AccountsMultiSelect';
|
||||||
export * from './AccountsSelectList';
|
|
||||||
export * from './AccountsSuggestField';
|
export * from './AccountsSuggestField';
|
||||||
export * from './AccountsTypesSelect';
|
export * from './AccountsTypesSelect';
|
||||||
|
|||||||
@@ -45,13 +45,6 @@ const currencyItemRenderer = (currency, { handleClick, modifiers, query }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const currencySelectProps = {
|
|
||||||
itemPredicate: currencyItemPredicate,
|
|
||||||
itemRenderer: currencyItemRenderer,
|
|
||||||
valueAccessor: 'currency_code',
|
|
||||||
labelAccessor: 'currency_code',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {*} currencies
|
* @param {*} currencies
|
||||||
@@ -60,7 +53,10 @@ const currencySelectProps = {
|
|||||||
export function CurrencySelect({ currencies, ...rest }) {
|
export function CurrencySelect({ currencies, ...rest }) {
|
||||||
return (
|
return (
|
||||||
<FSelect
|
<FSelect
|
||||||
{...currencySelectProps}
|
itemPredicate={currencyItemPredicate}
|
||||||
|
itemRenderer={currencyItemRenderer}
|
||||||
|
valueAccessor={'currency_code'}
|
||||||
|
labelAccessor={'currency_code'}
|
||||||
{...rest}
|
{...rest}
|
||||||
items={currencies}
|
items={currencies}
|
||||||
input={CurrnecySelectButton}
|
input={CurrnecySelectButton}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
import {
|
import {
|
||||||
FormGroup,
|
FormGroup,
|
||||||
InputGroup,
|
InputGroup,
|
||||||
@@ -9,9 +10,23 @@ import {
|
|||||||
EditableText,
|
EditableText,
|
||||||
TextArea,
|
TextArea,
|
||||||
} from '@blueprintjs-formik/core';
|
} from '@blueprintjs-formik/core';
|
||||||
|
import { Button } from '@blueprintjs/core';
|
||||||
import { Select, MultiSelect } from '@blueprintjs-formik/select';
|
import { Select, MultiSelect } from '@blueprintjs-formik/select';
|
||||||
import { DateInput } from '@blueprintjs-formik/datetime';
|
import { DateInput } from '@blueprintjs-formik/datetime';
|
||||||
|
|
||||||
|
function FSelect({ ...props }) {
|
||||||
|
const input = ({ activeItem, text, label, value }) => {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
text={text || props.placeholder || 'Select an item ...'}
|
||||||
|
rightIcon="double-caret-vertical"
|
||||||
|
{...props.buttonProps}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return <Select input={input} {...props} />;
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
FormGroup as FFormGroup,
|
FormGroup as FFormGroup,
|
||||||
InputGroup as FInputGroup,
|
InputGroup as FInputGroup,
|
||||||
@@ -19,7 +34,7 @@ export {
|
|||||||
Checkbox as FCheckbox,
|
Checkbox as FCheckbox,
|
||||||
RadioGroup as FRadioGroup,
|
RadioGroup as FRadioGroup,
|
||||||
Switch as FSwitch,
|
Switch as FSwitch,
|
||||||
Select as FSelect,
|
FSelect,
|
||||||
MultiSelect as FMultiSelect,
|
MultiSelect as FMultiSelect,
|
||||||
EditableText as FEditableText,
|
EditableText as FEditableText,
|
||||||
TextArea as FTextArea,
|
TextArea as FTextArea,
|
||||||
|
|||||||
@@ -1,28 +1,23 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
import { Form, ErrorMessage, useFormikContext } from 'formik';
|
||||||
import { Form, FastField, Field, ErrorMessage, useFormikContext } from 'formik';
|
import { Button, Classes, FormGroup, Intent } from '@blueprintjs/core';
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Classes,
|
|
||||||
FormGroup,
|
|
||||||
InputGroup,
|
|
||||||
Intent,
|
|
||||||
TextArea,
|
|
||||||
Checkbox,
|
|
||||||
} from '@blueprintjs/core';
|
|
||||||
import {
|
import {
|
||||||
If,
|
If,
|
||||||
FieldRequiredHint,
|
FieldRequiredHint,
|
||||||
Hint,
|
Hint,
|
||||||
AccountsSelectList,
|
AccountsSelect,
|
||||||
AccountsTypesSelect,
|
AccountsTypesSelect,
|
||||||
CurrencySelect,
|
CurrencySelect,
|
||||||
FormattedMessage as T,
|
FormattedMessage as T,
|
||||||
|
FFormGroup,
|
||||||
|
FInputGroup,
|
||||||
|
FCheckbox,
|
||||||
|
FTextArea,
|
||||||
} from '@/components';
|
} from '@/components';
|
||||||
import withAccounts from '@/containers/Accounts/withAccounts';
|
import withAccounts from '@/containers/Accounts/withAccounts';
|
||||||
|
|
||||||
import { inputIntent, compose } from '@/utils';
|
import { compose } from '@/utils';
|
||||||
import { useAutofocus } from '@/hooks';
|
import { useAutofocus } from '@/hooks';
|
||||||
import { FOREIGN_CURRENCY_ACCOUNTS } from '@/constants/accountTypes';
|
import { FOREIGN_CURRENCY_ACCOUNTS } from '@/constants/accountTypes';
|
||||||
import { useAccountDialogContext } from './AccountDialogProvider';
|
import { useAccountDialogContext } from './AccountDialogProvider';
|
||||||
@@ -36,7 +31,7 @@ function AccountFormDialogFields({
|
|||||||
onClose,
|
onClose,
|
||||||
action,
|
action,
|
||||||
}) {
|
}) {
|
||||||
const { values, isSubmitting } = useFormikContext();
|
const { values, isSubmitting, setFieldValue } = useFormikContext();
|
||||||
const accountNameFieldRef = useAutofocus();
|
const accountNameFieldRef = useAutofocus();
|
||||||
|
|
||||||
// Account form context.
|
// Account form context.
|
||||||
@@ -46,146 +41,117 @@ function AccountFormDialogFields({
|
|||||||
return (
|
return (
|
||||||
<Form>
|
<Form>
|
||||||
<div className={Classes.DIALOG_BODY}>
|
<div className={Classes.DIALOG_BODY}>
|
||||||
<Field name={'account_type'}>
|
<FFormGroup
|
||||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
inline={true}
|
||||||
<FormGroup
|
label={<T id={'account_type'} />}
|
||||||
label={<T id={'account_type'} />}
|
labelInfo={<FieldRequiredHint />}
|
||||||
labelInfo={<FieldRequiredHint />}
|
name={'account_type'}
|
||||||
className={classNames('form-group--account-type', Classes.FILL)}
|
fastField={true}
|
||||||
inline={true}
|
|
||||||
helperText={<ErrorMessage name="account_type" />}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
>
|
|
||||||
<AccountsTypesSelect
|
|
||||||
accountsTypes={accountsTypes}
|
|
||||||
selectedTypeId={value}
|
|
||||||
defaultSelectText={<T id={'select_account_type'} />}
|
|
||||||
onTypeSelected={(accountType) => {
|
|
||||||
form.setFieldValue('account_type', accountType.key);
|
|
||||||
form.setFieldValue('currency_code', '');
|
|
||||||
}}
|
|
||||||
disabled={fieldsDisabled.accountType}
|
|
||||||
popoverProps={{ minimal: true }}
|
|
||||||
popoverFill={true}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</Field>
|
|
||||||
|
|
||||||
<FastField name={'name'}>
|
|
||||||
{({ field, meta: { error, touched } }) => (
|
|
||||||
<FormGroup
|
|
||||||
label={<T id={'account_name'} />}
|
|
||||||
labelInfo={<FieldRequiredHint />}
|
|
||||||
className={'form-group--account-name'}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name="name" />}
|
|
||||||
inline={true}
|
|
||||||
>
|
|
||||||
<InputGroup
|
|
||||||
medium={true}
|
|
||||||
inputRef={(ref) => (accountNameFieldRef.current = ref)}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
|
|
||||||
<FastField name={'code'}>
|
|
||||||
{({ form, field, meta: { error, touched } }) => (
|
|
||||||
<FormGroup
|
|
||||||
label={<T id={'account_code'} />}
|
|
||||||
className={'form-group--account-code'}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name="code" />}
|
|
||||||
inline={true}
|
|
||||||
labelInfo={<Hint content={<T id="account_code_hint" />} />}
|
|
||||||
>
|
|
||||||
<InputGroup medium={true} {...field} />
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
|
|
||||||
<Field name={'subaccount'} type={'checkbox'}>
|
|
||||||
{({ field, meta: { error, touched } }) => (
|
|
||||||
<FormGroup
|
|
||||||
label={' '}
|
|
||||||
className={classNames('form-group--subaccount')}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
inline={true}
|
|
||||||
>
|
|
||||||
<Checkbox
|
|
||||||
inline={true}
|
|
||||||
label={<T id={'sub_account'} />}
|
|
||||||
name={'subaccount'}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</Field>
|
|
||||||
|
|
||||||
<FastField
|
|
||||||
name={'parent_account_id'}
|
|
||||||
shouldUpdate={parentAccountShouldUpdate}
|
|
||||||
>
|
>
|
||||||
{({
|
<AccountsTypesSelect
|
||||||
form: { values, setFieldValue },
|
name={'account_type'}
|
||||||
field: { value },
|
items={accountsTypes}
|
||||||
meta: { error, touched },
|
onItemSelect={(accountType) => {
|
||||||
}) => (
|
setFieldValue('account_type', accountType.key);
|
||||||
<FormGroup
|
setFieldValue('currency_code', '');
|
||||||
label={<T id={'parent_account'} />}
|
}}
|
||||||
className={classNames('form-group--parent-account', Classes.FILL)}
|
disabled={fieldsDisabled.accountType}
|
||||||
inline={true}
|
popoverProps={{ minimal: true }}
|
||||||
intent={inputIntent({ error, touched })}
|
fastField={true}
|
||||||
helperText={<ErrorMessage name="parent_account_id" />}
|
/>
|
||||||
>
|
</FFormGroup>
|
||||||
<AccountsSelectList
|
|
||||||
accounts={accounts}
|
<FFormGroup
|
||||||
onAccountSelected={(account) => {
|
name={'name'}
|
||||||
setFieldValue('parent_account_id', account.id);
|
label={<T id={'account_name'} />}
|
||||||
}}
|
labelInfo={<FieldRequiredHint />}
|
||||||
defaultSelectText={<T id={'select_parent_account'} />}
|
helperText={<ErrorMessage name="name" />}
|
||||||
selectedAccountId={value}
|
inline={true}
|
||||||
popoverFill={true}
|
fastField={true}
|
||||||
filterByTypes={values.account_type}
|
>
|
||||||
disabled={!values.subaccount}
|
<FInputGroup
|
||||||
/>
|
medium={true}
|
||||||
</FormGroup>
|
inputRef={(ref) => (accountNameFieldRef.current = ref)}
|
||||||
)}
|
name={'name'}
|
||||||
</FastField>
|
fastField={true}
|
||||||
|
/>
|
||||||
|
</FFormGroup>
|
||||||
|
|
||||||
|
<FFormGroup
|
||||||
|
label={<T id={'account_code'} />}
|
||||||
|
name={'code'}
|
||||||
|
helperText={<ErrorMessage name="code" />}
|
||||||
|
labelInfo={<Hint content={<T id="account_code_hint" />} />}
|
||||||
|
inline={true}
|
||||||
|
fastField={true}
|
||||||
|
>
|
||||||
|
<FInputGroup medium={true} name={'code'} fastField={true} />
|
||||||
|
</FFormGroup>
|
||||||
|
|
||||||
|
<FFormGroup
|
||||||
|
label={' '}
|
||||||
|
name={'subaccount'}
|
||||||
|
inline={true}
|
||||||
|
fastField={true}
|
||||||
|
>
|
||||||
|
<FCheckbox
|
||||||
|
inline={true}
|
||||||
|
label={<T id={'sub_account'} />}
|
||||||
|
name={'subaccount'}
|
||||||
|
fastField={true}
|
||||||
|
/>
|
||||||
|
</FFormGroup>
|
||||||
|
|
||||||
|
{values.subaccount && (
|
||||||
|
<FFormGroup
|
||||||
|
name={'parent_account_id'}
|
||||||
|
shouldUpdate={parentAccountShouldUpdate}
|
||||||
|
label={<T id={'parent_account'} />}
|
||||||
|
inline={true}
|
||||||
|
fastField={true}
|
||||||
|
>
|
||||||
|
<AccountsSelect
|
||||||
|
name={'parent_account_id'}
|
||||||
|
items={accounts}
|
||||||
|
shouldUpdate={parentAccountShouldUpdate}
|
||||||
|
placeholder={<T id={'select_parent_account'} />}
|
||||||
|
filterByTypes={values.account_type}
|
||||||
|
buttonProps={{ disabled: !values.subaccount }}
|
||||||
|
fastField={true}
|
||||||
|
/>
|
||||||
|
</FFormGroup>
|
||||||
|
)}
|
||||||
|
|
||||||
<If condition={FOREIGN_CURRENCY_ACCOUNTS.includes(values.account_type)}>
|
<If condition={FOREIGN_CURRENCY_ACCOUNTS.includes(values.account_type)}>
|
||||||
{/*------------ Currency -----------*/}
|
{/*------------ Currency -----------*/}
|
||||||
<FastField name={'currency_code'}>
|
<FFormGroup
|
||||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
label={<T id={'currency'} />}
|
||||||
<FormGroup
|
name={'currency_code'}
|
||||||
label={<T id={'currency'} />}
|
inline={true}
|
||||||
className={classNames('form-group--select-list', Classes.FILL)}
|
fastField={true}
|
||||||
inline={true}
|
>
|
||||||
>
|
<CurrencySelect
|
||||||
<CurrencySelect
|
name={'currency_code'}
|
||||||
name={'currency_code'}
|
currencies={currencies}
|
||||||
currencies={currencies}
|
popoverProps={{ minimal: true }}
|
||||||
popoverProps={{ minimal: true }}
|
fastField={true}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FFormGroup>
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
</If>
|
</If>
|
||||||
<FastField name={'description'}>
|
|
||||||
{({ field, meta: { error, touched } }) => (
|
<FFormGroup
|
||||||
<FormGroup
|
label={<T id={'description'} />}
|
||||||
label={<T id={'description'} />}
|
name={'description'}
|
||||||
className={'form-group--description'}
|
inline={true}
|
||||||
intent={inputIntent({ error, touched })}
|
fastField={true}
|
||||||
helperText={<ErrorMessage name={'description'} />}
|
>
|
||||||
inline={true}
|
<FTextArea
|
||||||
>
|
name={'description'}
|
||||||
<TextArea growVertically={true} height={280} {...field} />
|
growVertically={true}
|
||||||
</FormGroup>
|
height={280}
|
||||||
)}
|
fastField={true}
|
||||||
</FastField>
|
/>
|
||||||
|
</FFormGroup>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={Classes.DIALOG_FOOTER}>
|
<div className={Classes.DIALOG_FOOTER}>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from 'react';
|
|||||||
import { Classes } from '@blueprintjs/core';
|
import { Classes } from '@blueprintjs/core';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AccountMultiSelect,
|
AccountsMultiSelect,
|
||||||
Row,
|
Row,
|
||||||
Col,
|
Col,
|
||||||
FormattedMessage as T,
|
FormattedMessage as T,
|
||||||
@@ -54,7 +54,7 @@ function GLHeaderGeneralPaneContent() {
|
|||||||
name={'accountsIds'}
|
name={'accountsIds'}
|
||||||
className={Classes.FILL}
|
className={Classes.FILL}
|
||||||
>
|
>
|
||||||
<AccountMultiSelect name="accountsIds" accounts={accounts} />
|
<AccountsMultiSelect name="accountsIds" items={accounts} />
|
||||||
</FFormGroup>
|
</FFormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|||||||
@@ -242,7 +242,7 @@
|
|||||||
"organization": "Organization.",
|
"organization": "Organization.",
|
||||||
"check_your_email_for_a_link_to_reset": "Check your email for a link to reset your password.If it doesn’t appear within a few minutes, check your spam folder.",
|
"check_your_email_for_a_link_to_reset": "Check your email for a link to reset your password.If it doesn’t appear within a few minutes, check your spam folder.",
|
||||||
"we_couldn_t_find_your_account_with_that_email": "We couldn't find your account with that email.",
|
"we_couldn_t_find_your_account_with_that_email": "We couldn't find your account with that email.",
|
||||||
"select_parent_account": "Select Parent Account",
|
"select_parent_account": "Select Parent Account...",
|
||||||
"the_exchange_rate_has_been_edited_successfully": "The exchange rate has been edited successfully",
|
"the_exchange_rate_has_been_edited_successfully": "The exchange rate has been edited successfully",
|
||||||
"the_exchange_rate_has_been_created_successfully": "The exchange rate has been created successfully",
|
"the_exchange_rate_has_been_created_successfully": "The exchange rate has been created successfully",
|
||||||
"the_user_details_has_been_updated": "The user details has been updated",
|
"the_user_details_has_been_updated": "The user details has been updated",
|
||||||
|
|||||||
Reference in New Issue
Block a user