feat: universal search.

This commit is contained in:
a.bouhuolia
2021-08-21 18:59:49 +02:00
parent a7b0f1a8d2
commit 79c1b2ab67
82 changed files with 2497 additions and 317 deletions

View File

@@ -0,0 +1,106 @@
import React from 'react';
import { MenuItem } from '@blueprintjs/core';
import { Choose, T, Icon } from 'components';
import { RESOURCES_TYPES } from "../../../../common/resourcesTypes";
import withDrawerActions from "../../../Drawer/withDrawerActions";
/**
* Estimate universal search item select action.
*/
function EstimateUniversalSearchSelectComponent({
// #ownProps
resourceType,
resourceId,
// #withDrawerActions
openDrawer,
}) {
if (resourceType === RESOURCES_TYPES.ESTIMATE) {
openDrawer('estimate-drawer', { estimateId: resourceId });
}
return null;
}
export const EstimateUniversalSearchSelect = withDrawerActions(
EstimateUniversalSearchSelectComponent,
);
/**
* Status accessor.
*/
export const EstimateStatus = ({ estimate }) => (
<Choose>
<Choose.When condition={estimate.is_delivered && estimate.is_approved}>
<span class="approved">
<T id={'approved'} />
</span>
</Choose.When>
<Choose.When condition={estimate.is_delivered && estimate.is_rejected}>
<span class="reject">
<T id={'rejected'} />
</span>
</Choose.When>
<Choose.When
condition={
estimate.is_delivered && !estimate.is_rejected && !estimate.is_approved
}
>
<span class="delivered">
<T id={'delivered'} />
</span>
</Choose.When>
<Choose.Otherwise>
<span class="draft">
<T id={'draft'} />
</span>
</Choose.Otherwise>
</Choose>
);
/**
* Estimate universal search item.
*/
export function EstimateUniversalSearchItem(
item,
{ handleClick, modifiers, query },
) {
return (
<MenuItem
text={
<div>
<div>{item.text}</div>
<span class="bp3-text-muted">
{item.reference.estimate_number}{' '}
<Icon icon={'caret-right-16'} iconSize={16} />
{item.reference.formatted_estimate_date}
</span>
</div>
}
label={
<>
<div class="amount">{item.reference.formatted_amount}</div>
<EstimateStatus estimate={item.reference} />
</>
}
onClick={handleClick}
className={'universal-search__item--estimate'}
/>
);
}
const transformEstimatesToSearch = (estimate) => ({
text: estimate.customer.display_name,
label: estimate.formatted_balance,
reference: estimate,
});
export const universalSearchEstimateBind = () => ({
resourceType: RESOURCES_TYPES.ESTIMATE,
optionItemLabel: 'Estimates',
selectItemAction: EstimateUniversalSearchSelect,
itemRenderer: EstimateUniversalSearchItem,
itemSelect: transformEstimatesToSearch
});

View File

@@ -35,7 +35,7 @@ function EstimateActionsBar({
setEstimatesTableState,
// #withEstimates
estimatesFilterRoles
estimatesFilterRoles,
}) {
const history = useHistory();
@@ -51,20 +51,24 @@ function EstimateActionsBar({
const { refresh } = useRefreshEstimates();
// Handle tab change.
const handleTabChange = (customView) => {
const handleTabChange = (view) => {
setEstimatesTableState({
customViewId: customView.id || null,
viewSlug: view ? view.slug : null,
});
};
// Handle click a refresh sale estimates
const handleRefreshBtnClick = () => { refresh(); };
const handleRefreshBtnClick = () => {
refresh();
};
return (
<DashboardActionsBar>
<NavbarGroup>
<DashboardActionViewsList
resourceName={'estimates'}
allMenuItem={true}
allMenuItemText={<T id={'all'} />}
views={estimatesViews}
onChange={handleTabChange}
/>

View File

@@ -0,0 +1,121 @@
import React from 'react';
import intl from 'react-intl-universal';
import { MenuItem } from '@blueprintjs/core';
import { T, Choose, Icon } from 'components';
import { highlightText } from 'utils';
import { RESOURCES_TYPES } from 'common/resourcesTypes';
import withDrawerActions from '../../Drawer/withDrawerActions';
/**
* Universal search invoice item select action.
*/
function InvoiceUniversalSearchSelectComponent({
// #ownProps
resourceType,
resourceId,
// #withDrawerActions
openDrawer,
}) {
if (resourceType === RESOURCES_TYPES.INVOICE) {
openDrawer('invoice-drawer', { invoiceId: resourceId });
}
return null;
}
export const InvoiceUniversalSearchSelect = withDrawerActions(
InvoiceUniversalSearchSelectComponent,
);
/**
* Invoice status.
*/
function InvoiceStatus(customer) {
return (
<Choose>
<Choose.When condition={customer.is_fully_paid && customer.is_delivered}>
<span class="status status-success">
<T id={'paid'} />
</span>
</Choose.When>
<Choose.When condition={customer.is_delivered}>
<Choose>
<Choose.When condition={customer.is_overdue}>
<span className={'status status-warning'}>
{intl.get('overdue_by', { overdue: customer.overdue_days })}
</span>
</Choose.When>
<Choose.Otherwise>
<span className={'status status-warning'}>
{intl.get('due_in', { due: customer.remaining_days })}
</span>
</Choose.Otherwise>
</Choose>
</Choose.When>
<Choose.Otherwise>
<span class="status status--gray">
<T id={'draft'} />
</span>
</Choose.Otherwise>
</Choose>
);
}
/**
* Universal search invoice item.
*/
export function InvoiceUniversalSearchItem(
item,
{ handleClick, modifiers, query },
) {
return (
<MenuItem
active={modifiers.active}
text={
<div>
<div>{highlightText(item.text, query)}</div>
<span class="bp3-text-muted">
{highlightText(item.reference.invoice_no, query)}{' '}
<Icon icon={'caret-right-16'} iconSize={16} />
{highlightText(item.reference.formatted_invoice_date, query)}
</span>
</div>
}
label={
<>
<div class="amount">${item.reference.balance}</div>
<InvoiceStatus customer={item.reference} />
</>
}
onClick={handleClick}
className={'universal-search__item--invoice'}
/>
);
}
/**
* Transformes invoices to search.
* @param {*} invoice
* @returns
*/
const transformInvoicesToSearch = (invoice) => ({
id: invoice.id,
text: invoice.customer.display_name,
label: invoice.formatted_balance,
reference: invoice,
});
/**
* Binds universal search invoice configure.
*/
export const universalSearchInvoiceBind = () => ({
resourceType: RESOURCES_TYPES.INVOICE,
optionItemLabel: 'Invoices',
selectItemAction: InvoiceUniversalSearchSelect,
itemRenderer: InvoiceUniversalSearchItem,
itemSelect: transformInvoicesToSearch,
});

View File

@@ -51,8 +51,8 @@ function InvoiceActionsBar({
const { refresh } = useRefreshInvoices();
// Handle views tab change.
const handleTabChange = (customView) => {
setInvoicesTableState({ customViewId: customView.id || null });
const handleTabChange = (view) => {
setInvoicesTableState({ viewSlug: view ? view.slug : null });
};
// Handle click a refresh sale invoices
@@ -64,6 +64,7 @@ function InvoiceActionsBar({
<DashboardActionsBar>
<NavbarGroup>
<DashboardActionViewsList
allMenuItem={true}
resourceName={'invoices'}
views={invoicesViews}
onChange={handleTabChange}

View File

@@ -210,4 +210,4 @@ export function useInvoicesTableColumns() {
],
[],
);
}
}

View File

@@ -0,0 +1,78 @@
import React from 'react';
import { MenuItem } from '@blueprintjs/core';
import { RESOURCES_TYPES } from "../../../common/resourcesTypes";
import withDrawerActions from "../../Drawer/withDrawerActions";
import { highlightText } from 'utils';
import { Icon } from 'components';
/**
* Payment receive universal search item select action.
*/
function PaymentReceiveUniversalSearchSelectComponent({
// #ownProps
resourceType,
resourceId,
// #withDrawerActions
openDrawer,
}) {
if (resourceType === RESOURCES_TYPES.PAYMENT_RECEIVE) {
openDrawer('payment-receive-drawer', { paymentReceiveId: resourceId });
}
return null;
}
export const PaymentReceiveUniversalSearchSelect = withDrawerActions(
PaymentReceiveUniversalSearchSelectComponent,
);
/**
* Payment receive universal search item.
*/
export function PaymentReceiveUniversalSearchItem(
item,
{ handleClick, modifiers, query },
) {
return (
<MenuItem
active={modifiers.active}
text={
<div>
<div>{highlightText(item.text, query)}</div>
<span class="bp3-text-muted">
{highlightText(item.reference.payment_receive_no, query)}{' '}
<Icon icon={'caret-right-16'} iconSize={16} />
{highlightText(item.reference.formatted_payment_date, query)}
</span>
</div>
}
label={<div class="amount">{item.reference.formatted_amount}</div>}
onClick={handleClick}
className={'universal-search__item--invoice'}
/>
);
}
/**
* Transformes payment receives to search.
* @param {*} payment
* @returns
*/
const paymentReceivesToSearch = (payment) => ({
text: payment.customer.display_name,
subText: payment.formatted_payment_date,
label: payment.formatted_amount,
reference: payment,
});
/**
* Binds universal search payment receive configure.
*/
export const universalSearchPaymentReceiveBind = () => ({
resourceType: RESOURCES_TYPES.PAYMENT_RECEIVE,
optionItemLabel: 'Payment receive',
selectItemAction: PaymentReceiveUniversalSearchSelect,
itemRenderer: PaymentReceiveUniversalSearchItem,
itemSelect: paymentReceivesToSearch,
});

View File

@@ -0,0 +1,100 @@
import React from 'react';
import { MenuItem } from '@blueprintjs/core';
import { Icon, Choose, T } from 'components';
import { RESOURCES_TYPES } from "../../../common/resourcesTypes";
import withDrawerActions from "../../Drawer/withDrawerActions";
/**
* Receipt universal search item select action.
*/
function ReceiptUniversalSearchSelectComponent({
// #ownProps
resourceType,
resourceId,
onAction,
// #withDrawerActions
openDrawer,
}) {
if (resourceType === RESOURCES_TYPES.RECEIPT) {
openDrawer('receipt-drawer', { estimateId: resourceId });
}
return null;
}
export const ReceiptUniversalSearchSelect = withDrawerActions(
ReceiptUniversalSearchSelectComponent,
);
/**
* Status accessor.
*/
function ReceiptStatus({ receipt }) {
return (
<Choose>
<Choose.When condition={receipt.is_closed}>
<span class="closed"><T id={'closed'} /></span>
</Choose.When>
<Choose.Otherwise>
<span class="draft"><T id={'draft'} /></span>
</Choose.Otherwise>
</Choose>
);
}
/**
* Receipt universal search item.
*/
export function ReceiptUniversalSearchItem(
item,
{ handleClick, modifiers, query },
) {
return (
<MenuItem
active={modifiers.active}
text={
<div>
<div>{item.text}</div>
<span class="bp3-text-muted">
{item.reference.receipt_number}{' '}
<Icon icon={'caret-right-16'} iconSize={16} />
{item.reference.formatted_receipt_date}
</span>
</div>
}
label={
<>
<div class="amount">${item.reference.amount}</div>
<ReceiptStatus receipt={item.reference} />
</>
}
onClick={handleClick}
className={'universal-search__item--receipt'}
/>
);
}
/**
* Transformes receipt resource item to search item.
*/
const transformReceiptsToSearch = (receipt) => ({
text: receipt.customer.display_name,
label: receipt.formatted_amount,
reference: receipt,
});
/**
* Receipt universal search bind configuration.
*/
export const universalSearchReceiptBind = () => ({
resourceType: RESOURCES_TYPES.RECEIPT,
optionItemLabel: 'Receipts',
selectItemAction: ReceiptUniversalSearchSelect,
itemRenderer: ReceiptUniversalSearchItem,
itemSelect: transformReceiptsToSearch,
});

View File

@@ -49,22 +49,24 @@ function ReceiptActionsBar({
// Sale receipt refresh action.
const { refresh } = useRefreshReceipts();
const handleTabChange = (customView) => {
const handleTabChange = (view) => {
setReceiptsTableState({
customViewId: customView.id || null,
viewSlug: view ? view.slug : null,
});
};
// Handle click a refresh sale estimates
const handleRefreshBtnClick = () => { refresh(); };
console.log(receiptsFilterConditions, fields, 'XXX');
const handleRefreshBtnClick = () => {
refresh();
};
return (
<DashboardActionsBar>
<NavbarGroup>
<DashboardActionViewsList
resourceName={'receipts'}
allMenuItem={true}
allMenuItemText={<T id={'all'} />}
views={receiptsViews}
onChange={handleTabChange}
/>