- feat: Update react-query package to V 2.1.1.

- feat: Favicon setup.
- feat: Fix accounts inactivate/activate 1 account.
- feat: Seed accounts, expenses and manual journals resource fields.
- feat: Validate make journal receivable/payable without contact.
- feat: Validate make journal contact without receivable or payable.
- feat: More components abstractions.
- feat: Use reselect.js to memorize components properties.
- fix: Journal type of manual journal.
- fix: Sidebar style optimization.
- fix: Data-table check-box style optimization.
- fix: Data-table spinner style dimensions.
- fix: Submit journal with contact_id and contact_type.
This commit is contained in:
Ahmed Bouhuolia
2020-07-01 12:51:12 +02:00
parent 111aa83908
commit 4718f63c94
94 changed files with 1706 additions and 1001 deletions

View File

@@ -27,11 +27,29 @@ export default function AccountsSelectList({
onAccountSelected && onAccountSelected(account);
}, [setSelectedAccount, onAccountSelected]);
// Filters accounts items.
const filterAccountsPredicater = useCallback(
(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
);
}
},
[],
);
return (
<Select
items={accounts}
noResults={<MenuItem disabled={true} text='No results.' />}
itemRenderer={accountItem}
itemPredicate={filterAccountsPredicater}
popoverProps={{ minimal: true }}
filterable={true}
onItemSelect={onAccountSelect}>

View File

@@ -17,9 +17,9 @@ function App({ locale }) {
const history = createBrowserHistory();
const queryConfig = {
refetchAllOnWindowFocus: false,
cacheTime: 10000,
staleTime: 10000,
queries: {
refetchOnWindowFocus: true,
}
};
return (
<IntlProvider locale={locale} messages={messages}>

View File

@@ -32,7 +32,7 @@ export default function ContactsListField({
const onContactSelect = useCallback((contact) => {
setSelectedContact(contact.id);
onContactSelected && onContactSelected(contact.id);
onContactSelected && onContactSelected(contact);
}, [setSelectedContact, onContactSelected]);
return (

View File

@@ -9,11 +9,15 @@ import {
import {
Select
} from '@blueprintjs/select';
import classNames from 'classnames';
import { FormattedMessage as T } from 'react-intl';
export default function CurrenciesSelectList(props) {
const {formGroupProps, selectProps, onItemSelect} = props;
export default function CurrenciesSelectList({
formGroupProps,
selectProps,
onItemSelect,
className,
}) {
const currencies = [{
name: 'USD US dollars', key: 'USD',
name: 'CAD Canadian dollars', key: 'CAD',
@@ -41,7 +45,13 @@ export default function CurrenciesSelectList(props) {
return (
<FormGroup
label={<T id={'currency'}/>}
className={'form-group--select-list form-group--currency'}
className={
classNames(
'form-group--select-list',
'form-group--currency',
className,
)
}
{...formGroupProps}
>
<Select
@@ -54,7 +64,6 @@ export default function CurrenciesSelectList(props) {
{...selectProps}
>
<Button
rightIcon='caret-down'
text={'USD US dollars'}
/>
</Select>

View File

@@ -14,17 +14,15 @@ import { FormattedMessage as T } from 'react-intl';
import DashboardTopbarUser from 'components/Dashboard/TopbarUser';
import DashboardBreadcrumbs from 'components/Dashboard/DashboardBreadcrumbs';
import Icon from 'components/Icon';
import { Icon, If } from 'components';
import withSearch from 'containers/GeneralSearch/withSearch'
import withSearch from 'containers/GeneralSearch/withSearch';
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
import withDashboard from 'containers/Dashboard/withDashboard';
import { compose } from 'utils';
function DashboardTopbar({
// #withDashboard
pageTitle,
pageSubtitle,
@@ -42,69 +40,75 @@ function DashboardTopbar({
history.push(`/custom_views/${editViewId}/edit`);
};
const maybleRenderPageSubtitle = pageSubtitle && <h3>{pageSubtitle}</h3>;
const maybeRenderEditViewBtn = pageSubtitle && editViewId && (
<Button
className={Classes.MINIMAL + ' button--view-edit'}
icon={<Icon icon='pen' iconSize={13} />}
onClick={handlerClickEditView}
/>
);
const handleSidebarToggleBtn = () => {
toggleSidebarExpend();
};
return (
<div class='dashboard__topbar'>
<div class='dashboard__topbar-left'>
<div class='dashboard__topbar-sidebar-toggle'>
<Tooltip content={<T id={'close_sidebar'} />} position={Position.RIGHT}>
<div class="dashboard__topbar">
<div class="dashboard__topbar-left">
<div class="dashboard__topbar-sidebar-toggle">
<Tooltip
content={<T id={'close_sidebar'} />}
position={Position.RIGHT}
>
<Button minimal={true} onClick={handleSidebarToggleBtn}>
<svg
xmlns='http://www.w3.org/2000/svg'
width='20'
height='20'
viewBox='0 0 20 20'
role='img'
focusable='false'
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 20 20"
role="img"
focusable="false"
>
<title><T id={'menu'}/></title>
<title>
<T id={'menu'} />
</title>
<path
stroke='currentColor'
stroke-linecap='round'
stroke-miterlimit='5'
stroke-width='2'
d='M4 7h15M4 12h15M4 17h15'
stroke="currentColor"
stroke-linecap="round"
stroke-miterlimit="5"
stroke-width="2"
d="M4 7h15M4 12h15M4 17h15"
></path>
</svg>
</Button>
</Tooltip>
</div>
<div class='dashboard__title'>
<div class="dashboard__title">
<h1>{pageTitle}</h1>
{maybleRenderPageSubtitle}
{maybeRenderEditViewBtn}
<If condition={pageSubtitle}>
<h3>{ pageSubtitle }</h3>
</If>
<If condition={pageSubtitle && editViewId}>
<Button
className={Classes.MINIMAL + ' button--view-edit'}
icon={<Icon icon="pen" iconSize={13} />}
onClick={handlerClickEditView}
/>
</If>
</div>
<div class='dashboard__breadcrumbs'>
<div class="dashboard__breadcrumbs">
<DashboardBreadcrumbs />
</div>
</div>
<div class='dashboard__topbar-right'>
<Navbar class='dashboard__topbar-navbar'>
<div class="dashboard__topbar-right">
<Navbar class="dashboard__topbar-navbar">
<NavbarGroup>
<Button
onClick={() => openGlobalSearch(true)}
className={Classes.MINIMAL}
icon={<Icon icon={'search-24'} iconSize={20} />}
text={<T id={'quick_find'}/>}
text={<T id={'quick_find'} />}
/>
<Button
className={Classes.MINIMAL}
icon={<Icon icon={'plus-24'} iconSize={20} />}
text={<T id={'quick_new'}/>}
text={<T id={'quick_new'} />}
/>
<Button
className={Classes.MINIMAL}
@@ -113,13 +117,13 @@ function DashboardTopbar({
<Button
className={Classes.MINIMAL}
icon={<Icon icon={'help-24'} iconSize={20} />}
text={<T id={'help'} />} />
text={<T id={'help'} />}
/>
<NavbarDivider />
</NavbarGroup>
</Navbar>
<div class='dashboard__topbar-user'>
<div class="dashboard__topbar-user">
<DashboardTopbarUser />
</div>
</div>
@@ -129,8 +133,10 @@ function DashboardTopbar({
export default compose(
withSearch,
withDashboard(({ pageTitle, pageSubtitle, editViewId }) => ({
pageTitle, pageSubtitle, editViewId
withDashboard(({ pageTitle, pageSubtitle, editViewId }) => ({
pageTitle,
pageSubtitle,
editViewId,
})),
withDashboardActions,
)(DashboardTopbar);

View File

@@ -5,6 +5,7 @@ import { Button, Tabs, Tab, Tooltip, Position } from '@blueprintjs/core';
import { If, Icon } from 'components';
export default function DashboardViewsTabs({
initialViewId = 0,
tabs,
allTab = true,
newViewTab = true,
@@ -12,7 +13,7 @@ export default function DashboardViewsTabs({
onChange,
onTabClick,
}) {
const [currentView, setCurrentView] = useState(0);
const [currentView, setCurrentView] = useState(initialViewId || 0);
const handleClickNewView = () => {
onNewViewTabClick && onNewViewTabClick();

View File

@@ -45,7 +45,7 @@ export default function DataTable({
expandable = false,
expandToggleColumn = 2,
noInitialFetch = false,
spinnerProps = { size: 40 },
spinnerProps = { size: 30 },
pagination = false,
pagesCount: controlledPageCount,
@@ -282,6 +282,7 @@ export default function DataTable({
className={classnames('bigcapital-datatable', className, {
'has-sticky': sticky,
'is-expandable': expandable,
'is-loading': loading,
'has-virtualized-rows': virtualizedRows,
})}
>
@@ -357,19 +358,19 @@ export default function DataTable({
<div class="td">{noResults}</div>
</div>
</If>
<If condition={loading}>
<div class="loading">
<Spinner size={spinnerProps.size} />
</div>
</If>
</div>
<If condition={loading}>
<div class="loading">
<Spinner size={spinnerProps.size} />
</div>
</If>
</div>
</ScrollSyncPane>
</div>
</ScrollSync>
<If condition={pagination && pageCount}>
<If condition={pagination && pageCount && !loading}>
<Pagination
initialPage={pageIndex + 1}
total={pageSize * pageCount}

View File

@@ -9,8 +9,11 @@ export default function ContactsListCellRenderer({
cell: { value: initialValue },
payload: { contacts, updateData, errors }
}) {
const handleContactSelected = useCallback((contactId) => {
updateData(index, id, contactId)
const handleContactSelected = useCallback((contact) => {
updateData(index, {
contact_id: contact.id,
contact_type: contact.contact_type,
});
}, [updateData, index, id]);
const initialContact = useMemo(() => {

View File

@@ -1,20 +1,21 @@
import React from 'react';
import { connect } from 'react-redux';
import { isDialogOpen, getDialogPayload } from 'store/dashboard/dashboard.selectors';
import {
isDialogOpenFactory,
getDialogPayloadFactory,
} from 'store/dashboard/dashboard.selectors';
export default (Dialog) => {
function DialogReduxConnect(props) {
return (<Dialog {...props} />);
};
export default (mapState, dialogName) => {
const isDialogOpen = isDialogOpenFactory(dialogName);
const getDialogPayload = getDialogPayloadFactory(dialogName);
const mapStateToProps = (state, props) => {
return {
const mapped = {
dialogName,
isOpen: isDialogOpen(state, props),
payload: getDialogPayload(state, props),
};
return mapState ? mapState(mapped) : mapped;
};
return connect(
mapStateToProps,
)(DialogReduxConnect);
}
return connect(mapStateToProps);
};

View File

@@ -8,13 +8,13 @@ import ExchangeRateDialog from 'containers/Dialogs/ExchangeRateDialog';
export default function DialogsContainer() {
return (
<>
<div>
<ExchangeRateDialog />
<InviteUserDialog />
{/* <InviteUserDialog /> */}
<CurrencyDialog />
<ItemCategoryDialog />
<AccountFormDialog />
<UserFormDialog />
</>
{/* <UserFormDialog /> */}
</div>
);
}

View File

@@ -53,7 +53,7 @@ function DynamicFilterValueField({
const [localValue, setLocalValue] = useState();
const fetchResourceData = useQuery(
resourceName && ['resource-data', resourceName],
['resource-data', resourceName && resourceName],
(k, resName) => requestResourceData(resName),
{ manual: true },
);

View File

@@ -1,10 +1,13 @@
import React from 'react';
import { Tooltip, Position } from '@blueprintjs/core';
import Icon from './Icon';
export default function FieldHint({ hint }) {
export default function FieldHint({ content, position }) {
return (
<span class="hint">
<Icon icon="info-circle" iconSize={12} />
<Tooltip content={content} position={position}>
<Icon icon="info-circle" iconSize={12} />
</Tooltip>
</span>
);
}

View File

@@ -1,5 +1,4 @@
import { FieldRequiredHint } from "components"
import React from 'react';
export default function FieldRequiredHint() {

View File

@@ -15,6 +15,9 @@ export default function ListSelect ({
selectedItem,
selectedItemProp = 'id',
// itemTextProp,
// itemLabelProp,
...selectProps
}) {
const [currentItem, setCurrentItem] = useState(null);
@@ -29,8 +32,13 @@ export default function ListSelect ({
const noResults = isLoading ?
('loading') : <MenuItem disabled={true} text={noResultsText} />;
const itemRenderer = (item, { handleClick, modifiers, query }) => {
return (<MenuItem text={item[labelProp]} key={item[selectedItemProp]} />);
};
return (
<Select
itemRenderer={itemRenderer}
{...selectProps}
noResults={noResults}
>

View File

@@ -13,6 +13,11 @@ import FieldHint from './FieldHint';
import MenuItemLabel from './MenuItemLabel';
import Pagination from './Pagination';
import DashboardViewsTabs from './Dashboard/DashboardViewsTabs';
import CurrenciesSelectList from './CurrenciesSelectList';
import FieldRequiredHint from './FieldRequiredHint';
import Dialog from './Dialog';
import AppToaster from './AppToaster';
import DataTable from './DataTable';
const Hint = FieldHint;
@@ -33,5 +38,9 @@ export {
MenuItemLabel,
Pagination,
DashboardViewsTabs,
// For,
CurrenciesSelectList,
FieldRequiredHint,
Dialog,
AppToaster,
DataTable,
};