mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 21:30:31 +00:00
feat: accounts list as tree structure.
This commit is contained in:
@@ -40,6 +40,8 @@ const CLASSES = {
|
||||
DATATABLE_EMPTY_STATUS_DESC: 'datatable-empty-status__desc',
|
||||
DATATABLE_EMPTY_STATUS_ACTIONS: 'datatable-empty-status__actions',
|
||||
|
||||
SELECT_LIST_FILL_POPOVER: 'select-list--fill-popover',
|
||||
|
||||
...Classes,
|
||||
};
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Select } from '@blueprintjs/select';
|
||||
import { FormattedMessage as T } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { CLASSES } from 'common/classes';
|
||||
|
||||
export default function AccountsSelectList({
|
||||
accounts,
|
||||
@@ -12,6 +13,7 @@ export default function AccountsSelectList({
|
||||
defaultSelectText = 'Select account',
|
||||
onAccountSelected,
|
||||
disabled = false,
|
||||
popoverFill = false,
|
||||
filterByRootTypes = [],
|
||||
filterByTypes = [],
|
||||
filterByNormal
|
||||
@@ -61,7 +63,7 @@ export default function AccountsSelectList({
|
||||
const accountItem = useCallback((item, { handleClick, modifiers, query }) => {
|
||||
return (
|
||||
<MenuItem
|
||||
text={item.name}
|
||||
text={item.htmlName || item.name}
|
||||
label={item.code}
|
||||
key={item.id}
|
||||
onClick={handleClick}
|
||||
@@ -100,11 +102,13 @@ export default function AccountsSelectList({
|
||||
noResults={<MenuItem disabled={true} text={<T id={'no_accounts'} />} />}
|
||||
itemRenderer={accountItem}
|
||||
itemPredicate={filterAccountsPredicater}
|
||||
popoverProps={{ minimal: true }}
|
||||
popoverProps={{ minimal: true, usePortal: !popoverFill, inline: popoverFill }}
|
||||
filterable={true}
|
||||
onItemSelect={onAccountSelect}
|
||||
disabled={disabled}
|
||||
className={classNames('form-group--select-list')}
|
||||
className={classNames('form-group--select-list', {
|
||||
[CLASSES.SELECT_LIST_FILL_POPOVER]: popoverFill,
|
||||
})}
|
||||
>
|
||||
<Button
|
||||
disabled={disabled}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import { repeat } from 'lodash';
|
||||
import { pickItemsFromIds, getItemById } from 'store/selectors';
|
||||
import { flatToNestedArray } from 'utils';
|
||||
import { flatToNestedArray, treeToList } from 'utils';
|
||||
|
||||
const accountsViewsSelector = (state) => state.accounts.views;
|
||||
const accountsDataSelector = (state) => state.accounts.items;
|
||||
const accountsCurrentViewSelector = (state) => state.accounts.currentViewId;
|
||||
const accountIdPropSelector = (state, props) => props.accountId;
|
||||
const accountsListSelector = (state) => state.accounts.list;
|
||||
const accountsListSelector = (state) => state.accounts.listTree;
|
||||
|
||||
export const getAccountsItems = createSelector(
|
||||
accountsViewsSelector,
|
||||
@@ -30,8 +31,23 @@ export const getAccountsListFactory = () =>
|
||||
createSelector(
|
||||
accountsListSelector,
|
||||
accountsDataSelector,
|
||||
(accounts, accountsItems) => {
|
||||
return pickItemsFromIds(accountsItems, accounts);
|
||||
(accountsTree, accountsItems) => {
|
||||
return treeToList(accountsTree, {
|
||||
idFieldKey: 'id',
|
||||
childrenFieldKey: 'children',
|
||||
nodeMapper: (node, depth) => {
|
||||
const account = accountsItems[node.id];
|
||||
const spaceChar = String.fromCharCode(160);
|
||||
|
||||
return {
|
||||
...account,
|
||||
htmlName: (depth > 1)
|
||||
? (`${repeat(spaceChar, (depth - 1) * 2)}${account.name}`) :
|
||||
account.name,
|
||||
depth,
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import moment from 'moment';
|
||||
import _ from 'lodash';
|
||||
import {
|
||||
Intent,
|
||||
} from '@blueprintjs/core';
|
||||
import { Intent } from '@blueprintjs/core';
|
||||
import Currency from 'js-money/lib/currency';
|
||||
import PProgress from 'p-progress';
|
||||
import accounting from 'accounting';
|
||||
@@ -270,13 +268,12 @@ export const orderingLinesIndexes = (lines, attribute = 'index') => {
|
||||
return lines.map((line, index) => ({ ...line, [attribute]: index + 1 }));
|
||||
};
|
||||
|
||||
|
||||
export const transformToObject = (arr, key) => {
|
||||
return arr.reduce(function(acc, cur, i) {
|
||||
return arr.reduce(function (acc, cur, i) {
|
||||
acc[key ? cur[key] : i] = cur;
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
};
|
||||
|
||||
export const itemsStartWith = (items, char) => {
|
||||
return items.filter((item) => item.indexOf(char) === 0);
|
||||
@@ -284,15 +281,90 @@ export const itemsStartWith = (items, char) => {
|
||||
|
||||
export const saveInvoke = (func, ...rest) => {
|
||||
return func && func(...rest);
|
||||
}
|
||||
};
|
||||
|
||||
export const transformToForm = (obj, emptyInitialValues) => {
|
||||
return _.pickBy(
|
||||
obj,
|
||||
(val, key) => val !== null && Object.keys(emptyInitialValues).includes(key),
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
export function inputIntent({ error, touched }) {
|
||||
return error && touched ? Intent.DANGER : '';
|
||||
}
|
||||
|
||||
export function inputIntent({ error, touched }){
|
||||
return error && touched ? Intent.DANGER : '';
|
||||
}
|
||||
export function listToTree(
|
||||
inputList,
|
||||
{
|
||||
idFieldKey = 'id',
|
||||
parentFieldKey = 'parent_account_id',
|
||||
nodeMapper = (node) => ({ ...node }),
|
||||
},
|
||||
) {
|
||||
var map = {},
|
||||
node,
|
||||
roots = [],
|
||||
i;
|
||||
const list = inputList.map((item) => nodeMapper(item));
|
||||
|
||||
for (i = 0; i < list.length; i += 1) {
|
||||
map[list[i][idFieldKey]] = i;
|
||||
list[i].children = [];
|
||||
}
|
||||
for (i = 0; i < list.length; i += 1) {
|
||||
node = list[i];
|
||||
|
||||
if (node[parentFieldKey]) {
|
||||
list[map[node[parentFieldKey]]].children.push(node);
|
||||
} else {
|
||||
roots.push(node);
|
||||
}
|
||||
}
|
||||
return roots;
|
||||
}
|
||||
|
||||
export function treeToList(
|
||||
list,
|
||||
{
|
||||
idFieldKey = 'id',
|
||||
childrenFieldKey = 'children',
|
||||
nodeMapper = (node, depth) => node,
|
||||
},
|
||||
) {
|
||||
let depth = 0;
|
||||
|
||||
const walker = (tree) => {
|
||||
return tree.reduce(function (acc, o) {
|
||||
depth += 1;
|
||||
|
||||
if (o[idFieldKey]) {
|
||||
acc.push(nodeMapper(o, depth));
|
||||
}
|
||||
if (o[childrenFieldKey]) {
|
||||
acc = acc.concat(walker(o.children));
|
||||
}
|
||||
depth -= 1;
|
||||
return acc;
|
||||
}, []);
|
||||
};
|
||||
return walker(list);
|
||||
}
|
||||
|
||||
export function defaultToTransform(
|
||||
value,
|
||||
defaultOrTransformedValue,
|
||||
defaultValue,
|
||||
) {
|
||||
const _defaultValue =
|
||||
typeof defaultValue === 'undefined'
|
||||
? defaultOrTransformedValue
|
||||
: defaultValue;
|
||||
|
||||
const _transfromedValue =
|
||||
typeof defaultValue === 'undefined' ? value : defaultOrTransformedValue;
|
||||
|
||||
return value == null || value !== value || value === ''
|
||||
? _defaultValue
|
||||
: _transfromedValue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user