From 23e8e251a156808fc3e81baa73ea209676862988 Mon Sep 17 00:00:00 2001 From: "a.bouhuolia" Date: Tue, 10 Aug 2021 19:38:36 +0200 Subject: [PATCH] feat: WIP advanced filter. --- client/package.json | 1 + .../AdvancedFilter/AdvancedFilter.schema.js | 13 + .../AdvancedFilter/AdvancedFilter.schema.ts | 13 - .../AdvancedFilterCompatatorField.js | 27 ++ .../AdvancedFilterCompatatorField.tsx | 24 -- .../AdvancedFilter/AdvancedFilterDropdown.js | 397 ++++++++++++++++++ .../AdvancedFilter/AdvancedFilterDropdown.tsx | 306 -------------- .../AdvancedFilterDropdownContext.js | 84 ++++ .../AdvancedFilterDropdownContext.tsx | 47 --- .../AdvancedFilter/AdvancedFilterPopover.js | 32 ++ .../AdvancedFilterValueField.js | 131 ++++++ .../AdvancedFilterValueField.tsx | 209 --------- .../AdvancedFilterValueField2.tsx | 104 ----- .../{components.tsx => components.js} | 2 +- .../components/AdvancedFilter/interfaces.ts | 27 ++ client/src/components/AdvancedFilter/utils.js | 110 +++++ client/src/components/AdvancedFilter/utils.ts | 98 ----- .../Dashboard/DashboardFilterButton.js | 26 ++ .../Dashboard/DashboardRowsHeightButton.js | 36 ++ client/src/components/FilterDropdown2.js | 276 ------------ client/src/components/ListSelect.js | 15 + client/src/components/index.js | 4 + .../ManualJournalActionsBar.js | 54 +-- .../ManualJournalsListProvider.js | 37 +- .../containers/Accounts/AccountsActionsBar.js | 98 ++--- .../src/containers/Accounts/AccountsChart.js | 19 +- .../Accounts/AccountsChartProvider.js | 32 +- .../CustomersLanding/CustomersActionsBar.js | 45 +- .../CustomersLanding/CustomersList.js | 20 +- .../CustomersLanding/CustomersListProvider.js | 38 +- .../ExpensesLanding/ExpenseActionsBar.js | 49 ++- .../Expenses/ExpensesLanding/ExpensesList.js | 19 +- .../ExpensesLanding/ExpensesListProvider.js | 37 +- .../Expenses/ExpensesLanding/withExpenses.js | 1 - .../src/containers/Items/ItemsActionsBar.js | 41 +- .../src/containers/Items/ItemsListProvider.js | 58 ++- .../ItemsCategories/ItemCategoriesList.js | 17 +- .../ItemsCategoriesProvider.js | 34 +- .../ItemsCategoryActionsBar.js | 58 +-- .../ItemsCategories/withItemCategories.js | 2 +- .../Bills/BillsLanding/BillsActionsBar.js | 61 +-- .../Purchases/Bills/BillsLanding/BillsList.js | 19 +- .../Bills/BillsLanding/BillsListProvider.js | 36 +- .../PaymentsLanding/PaymentMadeActionsBar.js | 52 ++- .../PaymentsLanding/PaymentMadeList.js | 17 + .../PaymentMadesListProvider.js | 20 +- .../PaymentMdesListProvider.js | 8 +- .../EstimatesLanding/EstimatesActionsBar.js | 62 +-- .../EstimatesLanding/EstimatesList.js | 17 + .../EstimatesLanding/EstimatesListProvider.js | 29 +- .../InvoicesLanding/InvoicesActionsBar.js | 62 +-- .../Invoices/InvoicesLanding/InvoicesList.js | 17 + .../InvoicesLanding/InvoicesListProvider.js | 26 +- .../PaymentReceiptsListProvider.js | 21 +- .../PaymentReceiveActionsBar.js | 41 +- .../PaymentsLanding/PaymentReceivesList.js | 17 + .../PaymentReceivesListProvider.js | 19 +- .../ReceiptsLanding/ReceiptActionsBar.js | 62 +-- .../Receipts/ReceiptsLanding/ReceiptsList.js | 17 + .../ReceiptsLanding/ReceiptsListProvider.js | 37 +- .../VendorsLanding/VendorActionsBar.js | 42 +- .../Vendors/VendorsLanding/VendorsList.js | 19 +- .../VendorsLanding/VendorsListProvider.js | 25 +- client/src/hooks/query/views.js | 32 +- client/src/hooks/useRequest.js | 4 +- client/src/lang/en/index.json | 7 +- client/src/store/Bills/bills.reducer.js | 3 +- .../src/store/Estimate/estimates.reducer.js | 3 +- client/src/store/Invoice/invoices.reducer.js | 3 +- .../PaymentMades/paymentMades.reducer.js | 1 + .../paymentReceives.reducer.js | 3 +- client/src/store/accounts/accounts.reducer.js | 8 +- .../src/store/customers/customers.reducer.js | 3 +- client/src/store/expenses/expenses.reducer.js | 3 +- .../itemCategories/itemsCategory.reducer.js | 6 +- .../itemCategories/itemsCateory.reducer.js | 3 + client/src/store/items/items.reducer.js | 2 +- .../manualJournals/manualJournals.reducers.js | 3 +- client/src/store/receipts/receipts.reducer.js | 3 +- client/src/store/vendors/vendors.reducer.js | 3 +- client/src/style/objects/buttons.scss | 4 + client/src/style/views/filter-dropdown.scss | 180 ++++---- client/src/utils.js | 47 ++- server/.env.example | 2 +- server/src/api/controllers/Resources.ts | 78 +--- server/src/models/Account.Settings.ts | 2 + server/src/models/Bill.Settings.ts | 12 +- server/src/models/Customer.Settings.ts | 5 +- server/src/models/Expense.Settings.ts | 4 +- server/src/models/ItemCategory.Settings.ts | 8 +- server/src/models/ManualJournal.Settings.ts | 22 +- server/src/models/ModelSetting.ts | 4 +- server/src/models/SaleEstimate.Settings.ts | 10 +- server/src/models/SaleInvoice.Settings.ts | 15 +- server/src/models/SaleReceipt.Settings.ts | 8 +- server/src/models/Vendor.Settings.ts | 3 +- .../src/services/Resource/ResourceService.ts | 84 +--- 97 files changed, 2008 insertions(+), 1937 deletions(-) create mode 100644 client/src/components/AdvancedFilter/AdvancedFilter.schema.js delete mode 100644 client/src/components/AdvancedFilter/AdvancedFilter.schema.ts create mode 100644 client/src/components/AdvancedFilter/AdvancedFilterCompatatorField.js delete mode 100644 client/src/components/AdvancedFilter/AdvancedFilterCompatatorField.tsx create mode 100644 client/src/components/AdvancedFilter/AdvancedFilterDropdown.js delete mode 100644 client/src/components/AdvancedFilter/AdvancedFilterDropdown.tsx create mode 100644 client/src/components/AdvancedFilter/AdvancedFilterDropdownContext.js delete mode 100644 client/src/components/AdvancedFilter/AdvancedFilterDropdownContext.tsx create mode 100644 client/src/components/AdvancedFilter/AdvancedFilterPopover.js create mode 100644 client/src/components/AdvancedFilter/AdvancedFilterValueField.js delete mode 100644 client/src/components/AdvancedFilter/AdvancedFilterValueField.tsx delete mode 100644 client/src/components/AdvancedFilter/AdvancedFilterValueField2.tsx rename client/src/components/AdvancedFilter/{components.tsx => components.js} (88%) create mode 100644 client/src/components/AdvancedFilter/utils.js delete mode 100644 client/src/components/AdvancedFilter/utils.ts create mode 100644 client/src/components/Dashboard/DashboardFilterButton.js create mode 100644 client/src/components/Dashboard/DashboardRowsHeightButton.js delete mode 100644 client/src/components/FilterDropdown2.js diff --git a/client/package.json b/client/package.json index c4dcc5020..43e6e59e3 100644 --- a/client/package.json +++ b/client/package.json @@ -138,6 +138,7 @@ "@types/react": "^17.0.0", "@types/react-dom": "^17.0.0", "@types/react-router-dom": "^5.1.8", + "@types/yup": "^0.29.13", "@welldone-software/why-did-you-render": "^6.0.0-rc.1", "compression-webpack-plugin": "^6.1.0", "http-proxy-middleware": "^1.0.0", diff --git a/client/src/components/AdvancedFilter/AdvancedFilter.schema.js b/client/src/components/AdvancedFilter/AdvancedFilter.schema.js new file mode 100644 index 000000000..b40e41a90 --- /dev/null +++ b/client/src/components/AdvancedFilter/AdvancedFilter.schema.js @@ -0,0 +1,13 @@ +import * as Yup from 'yup'; + +export const getFilterDropdownSchema = () => + Yup.object().shape({ + conditions: Yup.array().of( + Yup.object().shape({ + fieldKey: Yup.string(), + value: Yup.string().nullable(), + condition: Yup.string().nullable(), + comparator: Yup.string().nullable(), + }), + ), + }); diff --git a/client/src/components/AdvancedFilter/AdvancedFilter.schema.ts b/client/src/components/AdvancedFilter/AdvancedFilter.schema.ts deleted file mode 100644 index 6efa7d699..000000000 --- a/client/src/components/AdvancedFilter/AdvancedFilter.schema.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as Yup from 'yup'; -import { DATATYPES_LENGTH } from 'common/dataTypes'; - -export const getFilterDropdownSchema = () => Yup.object().shape({ - conditions: Yup.array().of( - Yup.object().shape({ - fieldKey: Yup.string().max(DATATYPES_LENGTH.TEXT), - value: Yup.string().nullable().max(DATATYPES_LENGTH.TEXT), - condition: Yup.string().nullable().max(DATATYPES_LENGTH.TEXT), - comparator: Yup.string().nullable().max(DATATYPES_LENGTH.TEXT), - }), - ), -}); diff --git a/client/src/components/AdvancedFilter/AdvancedFilterCompatatorField.js b/client/src/components/AdvancedFilter/AdvancedFilterCompatatorField.js new file mode 100644 index 000000000..9170c5dd8 --- /dev/null +++ b/client/src/components/AdvancedFilter/AdvancedFilterCompatatorField.js @@ -0,0 +1,27 @@ +import React from 'react'; +import { Classes } from '@blueprintjs/core'; +import ListSelect from '../ListSelect'; +import { getConditionTypeCompatators } from './utils'; + +export default function DynamicFilterCompatatorField({ + dataType, + ...restProps +}) { + const options = getConditionTypeCompatators(dataType); + + return ( + + ); +} diff --git a/client/src/components/AdvancedFilter/AdvancedFilterCompatatorField.tsx b/client/src/components/AdvancedFilter/AdvancedFilterCompatatorField.tsx deleted file mode 100644 index 7dffe6f0e..000000000 --- a/client/src/components/AdvancedFilter/AdvancedFilterCompatatorField.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React, { useMemo } from 'react'; -import { HTMLSelect, Classes } from '@blueprintjs/core'; -import intl from 'react-intl-universal'; -import { getConditionTypeCompatators } from './utils'; - -export default function DynamicFilterCompatatorField({ - dataType, - ...restProps -}) { - const options = useMemo( - () => getConditionTypeCompatators(dataType).map(comp => ({ - value: comp.value, label: intl.get(comp.label), - })), - [dataType] - ); - - return ( - - ); -} diff --git a/client/src/components/AdvancedFilter/AdvancedFilterDropdown.js b/client/src/components/AdvancedFilter/AdvancedFilterDropdown.js new file mode 100644 index 000000000..867bf06ba --- /dev/null +++ b/client/src/components/AdvancedFilter/AdvancedFilterDropdown.js @@ -0,0 +1,397 @@ +import React from 'react'; +import { Formik, FastField, FieldArray, useFormikContext } from 'formik'; +import { + Button, + FormGroup, + Classes, + InputGroup, + MenuItem, +} from '@blueprintjs/core'; +import { get, first, defaultTo, isEqual, isEmpty } from 'lodash'; +import intl from 'react-intl-universal'; +import { Choose, Icon, FormattedMessage as T, ListSelect } from 'components'; +import { useUpdateEffect } from 'hooks'; +import { + AdvancedFilterDropdownProvider, + FilterConditionProvider, + useFilterCondition, + useAdvancedFilterContext, +} from './AdvancedFilterDropdownContext'; +import AdvancedFilterCompatatorField from './AdvancedFilterCompatatorField'; +import AdvancedFilterValueField from './AdvancedFilterValueField'; +import { + filterConditionRoles, + getConditionalsOptions, + transformFieldsToOptions, + shouldFilterValueFieldUpdate, + getConditionTypeCompatators, +} from './utils'; +import { getFilterDropdownSchema } from './AdvancedFilter.schema'; +import { useAdvancedFilterAutoSubmit } from './components'; + +/** + * Condition item list renderer. + */ +function ConditionItemRenderer(condition, { handleClick, modifiers, query }) { + return ( + +
{condition.label}
+ {condition.text} + + } + key={condition.value} + onClick={handleClick} + /> + ); +} + +/** + * Filter condition field. + */ +function FilterConditionField() { + const conditionalsOptions = getConditionalsOptions(); + const { conditionIndex, getConditionFieldPath } = useFilterCondition(); + + const conditionFieldPath = getConditionFieldPath('condition'); + + return ( + + {({ form, field }) => ( + + + + + + + + { + form.setFieldValue(conditionFieldPath, option.value); + }} + popoverProps={{ + inline: true, + minimal: true, + captureDismiss: true, + }} + itemRenderer={ConditionItemRenderer} + /> + + + + )} + + ); +} + +/** + * Compatator field. + */ +function FilterCompatatorFilter() { + const { getConditionFieldPath, fieldMeta } = useFilterCondition(); + + const comparatorFieldPath = getConditionFieldPath('comparator'); + const fieldType = get(fieldMeta, 'fieldType'); + + return ( + + {({ form, field }) => ( + + { + form.setFieldValue(comparatorFieldPath, option.value); + }} + /> + + )} + + ); +} + +/** + * Changes default value of comparator field in the condition row once the + * field option changing. + */ +function useDefaultComparatorFieldValue({ + getConditionValue, + setConditionValue, + fieldMeta, +}) { + const fieldKeyValue = getConditionValue('fieldKey'); + + const comparatorsOptions = React.useMemo( + () => getConditionTypeCompatators(fieldMeta.fieldType), + [fieldMeta.fieldType], + ); + + useUpdateEffect(() => { + if (fieldKeyValue) { + const defaultValue = get(first(comparatorsOptions), 'value'); + setConditionValue('comparator', defaultValue); + } + }, [fieldKeyValue, setConditionValue, comparatorsOptions]); +} + +/** + * Resource fields field. + */ +function FilterFieldsField() { + const { + getConditionFieldPath, + getConditionValue, + setConditionValue, + fieldMeta, + } = useFilterCondition(); + + const { fields } = useAdvancedFilterContext(); + + const fieldPath = getConditionFieldPath('fieldKey'); + const valueFieldPath = getConditionFieldPath('value'); + + useDefaultComparatorFieldValue({ + getConditionValue, + setConditionValue, + fieldMeta, + }); + + return ( + + {({ field, form }) => ( + + { + form.setFieldValue(fieldPath, option.value); + + // Resets the value field to empty once the field option changing. + form.setFieldValue(valueFieldPath, ''); + }} + popoverProps={{ + inline: true, + minimal: true, + captureDismiss: true, + }} + /> + + )} + + ); +} + +/** + * Advanced filter value field. + */ +function FilterValueField() { + const { conditionIndex, fieldMeta, getConditionFieldPath } = + useFilterCondition(); + + // Can't continue if the given field key is not selected yet. + if (!fieldMeta) { + return null; + } + // Field meta type, name and options. + const fieldType = get(fieldMeta, 'fieldType'); + const fieldName = get(fieldMeta, 'name'); + const options = get(fieldMeta, 'options'); + + const valueFieldPath = getConditionFieldPath('value'); + + return ( + + {({ form: { setFieldValue }, field }) => ( + + { + setFieldValue(valueFieldPath, value); + }} + /> + + )} + + ); +} + +/** + * Advanced filter condition line. + */ +function AdvancedFilterDropdownCondition({ conditionIndex, onRemoveClick }) { + // Handle click remove condition. + const handleClickRemoveCondition = () => { + onRemoveClick && onRemoveClick(conditionIndex); + }; + + return ( +
+ + + + + + +
+ ); +} + +/** + * Advanced filter dropdown condition. + */ +function AdvancedFilterDropdownConditions({ push, remove, replace, form }) { + const { initialCondition } = useAdvancedFilterContext(); + + // Handle remove condition. + const handleClickRemoveCondition = (conditionIndex) => { + if (form.values.conditions.length > 1) { + remove(conditionIndex); + } else { + replace(0, { ...initialCondition }); + } + }; + // Handle new condition button click. + const handleNewConditionBtnClick = (index) => { + push({ ...initialCondition }); + }; + + return ( +
+
+ {form.values.conditions.map((condition, index) => ( + + ))} +
+ +
+ ); +} + +/** + * Advanced filter dropdown form. + */ +function AdvancedFilterDropdownForm() { + // Advanced filter auto-save. + useAdvancedFilterAutoSubmit(); + + return ( +
+ ( + + )} + /> +
+ ); +} + +/** + * Advanced filter dropdown footer. + */ +function AdvancedFilterDropdownFooter({ onClick }) { + // Handle new filter condition button click. + const onClickNewFilter = (event) => { + onClick && onClick(event); + }; + return ( +
+ +
+ ); +} + +/** + * Advanced filter dropdown. + */ +export function AdvancedFilterDropdown({ + fields, + conditions, + defaultFieldKey, + defaultComparator, + defaultValue, + defaultCondition, + onFilterChange, +}) { + // Initial condition. + const initialCondition = { + fieldKey: defaultFieldKey, + comparator: defaultTo(defaultComparator, 'contain'), + condition: defaultTo(defaultCondition, 'or'), + value: defaultTo(defaultValue, ''), + }; + // Initial conditions. + const initialConditions = !isEmpty(conditions) + ? conditions + : [initialCondition, initialCondition]; + + const [prevConditions, setPrevConditions] = React.useState(initialConditions); + + // Handle the filter dropdown form submit. + const handleFitlerDropdownSubmit = (values) => { + const conditions = filterConditionRoles(values.conditions); + + // Campare the current conditions with previous conditions, if they were equal + // there is no need to execute `onFilterChange` function. + if (!isEqual(prevConditions, conditions)) { + onFilterChange && onFilterChange(conditions); + setPrevConditions(conditions); + } + }; + // Filter dropdown validation schema. + const validationSchema = getFilterDropdownSchema(); + + // Initial values. + const initialValues = { + conditions: initialConditions, + }; + + return ( +
+ + + +
+ ); +} diff --git a/client/src/components/AdvancedFilter/AdvancedFilterDropdown.tsx b/client/src/components/AdvancedFilter/AdvancedFilterDropdown.tsx deleted file mode 100644 index d18d23958..000000000 --- a/client/src/components/AdvancedFilter/AdvancedFilterDropdown.tsx +++ /dev/null @@ -1,306 +0,0 @@ -import React from 'react'; -import { Formik, Field, FieldArray, useFormikContext } from 'formik'; -import { - Button, - Intent, - FormGroup, - Classes, - HTMLSelect, -} from '@blueprintjs/core'; -import { get, defaultTo, isEqual } from 'lodash'; -import { Icon, FormattedMessage as T } from 'components'; -import { - AdvancedFilterDropdownProvider, - FilterConditionProvider, - useFilterCondition, - useAdvancedFilterContext, -} from './AdvancedFilterDropdownContext'; -import AdvancedFilterCompatatorField from './AdvancedFilterCompatatorField'; -import AdvancedFilterValueField from './AdvancedFilterValueField2'; -import { - filterConditionRoles, - getConditionalsOptions, - transformFieldsToOptions, -} from './utils'; -import { getFilterDropdownSchema } from './AdvancedFilter.schema'; -import { - IAdvancedFilterDropdown, - IAdvancedFilterDropdownFooter, - IFilterDropdownFormikValues, - IAdvancedFilterDropdownConditionsProps, - IAdvancedFilterDropdownCondition, - IFilterRole, -} from './interfaces'; -import { useAdvancedFilterAutoSubmit } from './components'; - -/** - * Filter condition field. - */ -function FilterConditionField() { - const conditionalsOptions = getConditionalsOptions(); - const { conditionIndex } = useFilterCondition(); - - return ( - - {({ field }) => ( - - - - )} - - ); -} - -/** - * Compatator field. - */ -function FilterCompatatorFilter() { - const { conditionIndex } = useFilterCondition(); - - return ( - - {({ field }) => ( - - - - )} - - ); -} - -/** - * Resource fields field. - */ -function FilterFieldsField() { - const { conditionIndex } = useFilterCondition(); - const { fields } = useAdvancedFilterContext(); - - return ( - - {({ field }) => ( - - - - )} - - ); -} - -/** - * Advanced filter value field. - */ -function FilterValueField(): JSX.Element | null { - const { values } = useFormikContext(); - const { conditionIndex } = useFilterCondition(); - const { fieldsByKey } = useAdvancedFilterContext(); - - // Current condition field key. - const conditionFieldKey = get( - values.conditions, - `[${conditionIndex}].fieldKey`, - ); - // Field meta. - const fieldMeta = fieldsByKey[conditionFieldKey]; - - // Can't continue if the given field key is not selected yet. - if (!conditionFieldKey || !fieldMeta) { - return null; - } - // Field meta type, name and options. - const fieldType = get(fieldMeta, 'fieldType'); - const fieldName = get(fieldMeta, 'name'); - const options = get(fieldMeta, 'options'); - - const valueFieldPath = `conditions[${conditionIndex}].value`; - - return ( - - {({ form: { setFieldValue } }) => ( - - { - setFieldValue(valueFieldPath, value); - }} - /> - - )} - - ); -} - -/** - * Advanced filter condition line. - */ -function AdvancedFilterDropdownCondition({ - conditionIndex, - onRemoveClick, -}: IAdvancedFilterDropdownCondition) { - // Handle click remove condition. - const handleClickRemoveCondition = () => { - onRemoveClick && onRemoveClick(conditionIndex); - }; - - return ( -
- - - - - - -
- ); -} - -/** - * Advanced filter dropdown condition. - */ -function AdvancedFilterDropdownConditions({ - push, - remove, - form, -}: IAdvancedFilterDropdownConditionsProps) { - const { initialCondition } = useAdvancedFilterContext(); - - // Handle remove condition. - const handleClickRemoveCondition = (conditionIndex: number) => { - remove(conditionIndex); - }; - // Handle new condition button click. - const handleNewConditionBtnClick = (index: number) => { - push({ ...initialCondition }); - }; - - return ( -
-
- {form.values.conditions.map((condition: IFilterRole, index: number) => ( - - ))} -
- -
- ); -} - -/** - * Advanced filter dropdown form. - */ -function AdvancedFilterDropdownForm() { - // - useAdvancedFilterAutoSubmit(); - - return ( -
- ( - - )} - /> -
- ); -} - -/** - * Advanced filter dropdown footer. - */ -function AdvancedFilterDropdownFooter({ - onClick, -}: IAdvancedFilterDropdownFooter) { - // Handle new filter condition button click. - const onClickNewFilter = (event) => { - onClick && onClick(event); - }; - - return ( -
- -
- ); -} - -/** - * Advanced filter dropdown. - */ -export default function AdvancedFilterDropdown({ - fields, - defaultFieldKey, - defaultComparator, - defaultValue, - onFilterChange, -}: IAdvancedFilterDropdown) { - const [prevConditions, setPrevConditions] = React.useState({}); - - // Handle the filter dropdown form submit. - const handleFitlerDropdownSubmit = (values: IFilterDropdownFormikValues) => { - const conditions = filterConditionRoles(values.conditions); - - // Campare the current conditions with previous conditions, if they were equal - // there is no need to execute `onFilterChange` function. - if (!isEqual(prevConditions, conditions) && conditions.length > 0) { - onFilterChange && onFilterChange(conditions); - - setPrevConditions(conditions); - } - }; - - // Filter dropdown validation schema. - const validationSchema = getFilterDropdownSchema(); - - // Initial condition. - const initialCondition = { - fieldKey: defaultFieldKey, - comparator: defaultTo(defaultComparator, 'equals'), - condition: '', - value: defaultTo(defaultValue, ''), - }; - // Initial values. - const initialValues: IFilterDropdownFormikValues = { - conditions: [initialCondition], - }; - - return ( -
- - - -
- ); -} diff --git a/client/src/components/AdvancedFilter/AdvancedFilterDropdownContext.js b/client/src/components/AdvancedFilter/AdvancedFilterDropdownContext.js new file mode 100644 index 000000000..6e32f8116 --- /dev/null +++ b/client/src/components/AdvancedFilter/AdvancedFilterDropdownContext.js @@ -0,0 +1,84 @@ +import React, { createContext, useContext } from 'react'; +import { get, keyBy } from 'lodash'; +import { useFormikContext } from 'formik'; + +const AdvancedFilterContext = createContext({}); +const FilterConditionContext = createContext({}); + +/** + * Advanced filter dropdown context provider. + */ +function AdvancedFilterDropdownProvider({ + initialCondition, + fields, + ...props +}) { + const fieldsByKey = keyBy(fields, 'key'); + + // Retrieve field meta by the given field key. + const getFieldMetaByKey = React.useCallback( + (key) => get(fieldsByKey, key), + [fieldsByKey], + ); + // Provider payload. + const provider = { initialCondition, fields, fieldsByKey, getFieldMetaByKey }; + + return ; +} + +/** + * Filter condition row context provider. + */ +function FilterConditionProvider({ conditionIndex, ...props }) { + const { setFieldValue, values } = useFormikContext(); + const { getFieldMetaByKey } = useAdvancedFilterContext(); + + // Condition value path. + const conditionPath = `conditions[${conditionIndex}]`; + + // Sets conditions value. + const setConditionValue = React.useCallback( + (field, value) => { + return setFieldValue(`${conditionPath}.${field}`, value); + }, + [conditionPath, setFieldValue], + ); + + // Retrieve condition field value. + const getConditionValue = React.useCallback( + (field) => get(values, `${conditionPath}.${field}`), + [conditionPath, values], + ); + + // The current condition field meta. + const fieldMeta = React.useMemo( + () => getFieldMetaByKey(getConditionValue('fieldKey')), + [getFieldMetaByKey, getConditionValue], + ); + + // Retrieve the condition field path. + const getConditionFieldPath = React.useCallback( + (field) => `${conditionPath}.${field}`, + [conditionPath], + ); + + // Provider payload. + const provider = { + fieldMeta, + conditionIndex, + getConditionValue, + getConditionFieldPath, + setConditionValue, + }; + return ; +} + +const useFilterCondition = () => useContext(FilterConditionContext); +const useAdvancedFilterContext = () => useContext(AdvancedFilterContext); + +export { + AdvancedFilterDropdownProvider, + FilterConditionProvider, + useAdvancedFilterContext, + useFilterCondition, +}; diff --git a/client/src/components/AdvancedFilter/AdvancedFilterDropdownContext.tsx b/client/src/components/AdvancedFilter/AdvancedFilterDropdownContext.tsx deleted file mode 100644 index e6e53654a..000000000 --- a/client/src/components/AdvancedFilter/AdvancedFilterDropdownContext.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import React, { createContext, useContext } from 'react'; -import { keyBy } from 'lodash'; -import { - IAdvancedFilterContextProps, - IFilterConditionContextProps, - IAdvancedFilterProviderProps, - IFilterConditionProviderProps, -} from './interfaces'; - -const AdvancedFilterContext = createContext({}); -const FilterConditionContext = createContext({}); - -/** - * Advanced filter dropdown context provider. - */ -function AdvancedFilterDropdownProvider({ - initialCondition, - fields, - ...props -}: IAdvancedFilterProviderProps) { - const fieldsByKey = keyBy(fields, 'key'); - // Provider payload. - const provider = { initialCondition, fields, fieldsByKey }; - return ; -} - -/** - * Filter condition row context provider. - */ -function FilterConditionProvider({ - conditionIndex, - ...props -}: IFilterConditionProviderProps) { - // Provider payload. - const provider = { conditionIndex }; - return ; -} - -const useFilterCondition = () => useContext(FilterConditionContext); -const useAdvancedFilterContext = () => useContext(AdvancedFilterContext); - -export { - AdvancedFilterDropdownProvider, - FilterConditionProvider, - useAdvancedFilterContext, - useFilterCondition, -}; diff --git a/client/src/components/AdvancedFilter/AdvancedFilterPopover.js b/client/src/components/AdvancedFilter/AdvancedFilterPopover.js new file mode 100644 index 000000000..902af70a0 --- /dev/null +++ b/client/src/components/AdvancedFilter/AdvancedFilterPopover.js @@ -0,0 +1,32 @@ +import React from 'react'; +import { Popover, PopoverInteractionKind, Position } from '@blueprintjs/core'; +import { AdvancedFilterDropdown } from './AdvancedFilterDropdown'; + +/** + * Advanced filter popover. + */ +export function AdvancedFilterPopover({ + popoverProps, + advancedFilterProps, + children, +}) { + return ( + + } + interactionKind={PopoverInteractionKind.CLICK} + position={Position.BOTTOM_LEFT} + canOutsideClickClose={true} + modifiers={{ + offset: { offset: '0, 4' }, + }} + {...popoverProps} + > + {children} + + ); +} diff --git a/client/src/components/AdvancedFilter/AdvancedFilterValueField.js b/client/src/components/AdvancedFilter/AdvancedFilterValueField.js new file mode 100644 index 000000000..04b8fd9f9 --- /dev/null +++ b/client/src/components/AdvancedFilter/AdvancedFilterValueField.js @@ -0,0 +1,131 @@ +import React from 'react'; +import { Position, Checkbox, InputGroup } from '@blueprintjs/core'; +import { DateInput } from '@blueprintjs/datetime'; +import moment from 'moment'; +import intl from 'react-intl-universal'; +import { isUndefined } from 'lodash'; +import { useAutofocus } from 'hooks'; +import { Choose, ListSelect } from 'components'; +import { momentFormatter } from 'utils'; + +function AdvancedFilterEnumerationField({ options, value, ...rest }) { + return ( + + ); +} + +const IFieldType = { + ENUMERATION: 'enumeration', + BOOLEAN: 'boolean', + NUMBER: 'number', + DATE: 'date', +} + + +function tansformDateValue(date, defaultValue = null) { + return date ? moment(date).toDate() : defaultValue; +} +/** + * Advanced filter value field detarminer. + */ +export default function AdvancedFilterValueField2({ + value, + fieldType, + options, + onChange, + isFocus +}) { + const [localValue, setLocalValue] = React.useState(value); + + React.useEffect(() => { + if (localValue !== value && !isUndefined(value)) { + setLocalValue(value) + } + }, [localValue, value]); + + // Input field reference. + const valueRef = useAutofocus(isFocus); + + const triggerOnChange = (value) => onChange && onChange(value); + + // Handle input change. + const handleInputChange = (e) => { + if (e.currentTarget.type === 'checkbox') { + setLocalValue(e.currentTarget.checked); + triggerOnChange(e.currentTarget.checked); + } else { + setLocalValue(e.currentTarget.value); + triggerOnChange(e.currentTarget.value); + } + }; + + // Handle enumeration field type change. + const handleEnumerationChange = (option) => { + setLocalValue(option.key); + triggerOnChange(option.key); + }; + + // Handle date field change. + const handleDateChange = (date) => { + const formattedDate = moment(date).format('YYYY/MM/DD'); + + setLocalValue(formattedDate); + triggerOnChange(formattedDate); + }; + + return ( + + + + + + + + + + + + + + + + + + ); +} \ No newline at end of file diff --git a/client/src/components/AdvancedFilter/AdvancedFilterValueField.tsx b/client/src/components/AdvancedFilter/AdvancedFilterValueField.tsx deleted file mode 100644 index 10a9877ad..000000000 --- a/client/src/components/AdvancedFilter/AdvancedFilterValueField.tsx +++ /dev/null @@ -1,209 +0,0 @@ -import React, { useMemo, useRef, useEffect, useState } from 'react'; -import { - FormGroup, - MenuItem, - InputGroup, - Position, - Checkbox, -} from '@blueprintjs/core'; -import { connect } from 'react-redux'; -import { useQuery } from 'react-query'; -import { DateInput } from '@blueprintjs/datetime'; -import classNames from 'classnames'; -import { FormattedMessage as T } from 'components'; -import intl from 'react-intl-universal'; -import { debounce } from 'lodash'; -import moment from 'moment'; - -import { Choose, ListSelect, MODIFIER } from 'components'; - -import withResourceDetail from 'containers/Resources/withResourceDetails'; -import withResourceActions from 'containers/Resources/withResourcesActions'; - -import { compose, momentFormatter } from 'utils'; - -/** - * Dynamic filter fields. - */ -function DynamicFilterValueField({ - - // #withResourceDetail - resourceName, - resourceData = [], - - requestResourceData, - - // #ownProps - fieldType, - fieldName, - value, - initialValue, - error, - optionsResource, - optionsKey = 'key', - optionsLabel = 'label', - options, - onChange, - inputDebounceWait = 250, -}) { - - const [localValue, setLocalValue] = useState(); - - // Makes `localValue` controlled mode from `value`. - useEffect(() => { - if (value !== localValue) { - setLocalValue(value); - } - }, [value]); - - // Fetches resource data. - const fetchResourceData = useQuery( - ['resource-data', resourceName], - (key, _resourceName) => requestResourceData(_resourceName), - { - enabled: resourceName, - }, - ); - - // Account type item of select filed. - const menuItem = (item, { handleClick, modifiers, query }) => { - return (); - }; - - // Handle list button click. - const handleBtnClick = () => { - - }; - - const listOptions = useMemo(() => [ - ...(resourceData || []), - ...(options || []), - ], [ - resourceData, options, - ]); - - // Filters accounts types items. - const filterItems = (query, item, _index, exactMatch) => { - const normalizedTitle = item.label.toLowerCase(); - const normalizedQuery = query.toLowerCase(); - - if (exactMatch) { - return normalizedTitle === normalizedQuery; - } else { - return normalizedTitle.indexOf(normalizedQuery) >= 0; - } - }; - - // Handle list item selected. - const onItemSelect = (item) => { - onChange && onChange(item[optionsKey]); - }; - - const handleInputChangeThrottled = useRef( - debounce((value) => { onChange && onChange(value); }, inputDebounceWait), - ); - - // Handle input change. - const handleInputChange = (e) => { - if (e.currentTarget.type === 'checkbox') { - setLocalValue(e.currentTarget.checked); - } else { - setLocalValue(e.currentTarget.value); - } - handleInputChangeThrottled.current(e.currentTarget.value); - }; - - // Handle checkbox field change. - const handleCheckboxChange = (e) => { - const value = !!e.currentTarget.checked; - setLocalValue(value); - onChange && onChange(value); - } - - // Handle date field change. - const handleDateChange = (date) => { - setLocalValue(date); - onChange && onChange(date); - }; - - const transformDateValue = (value) => { - return value ? moment(value || new Date()).toDate() : null; - }; - - return ( - - - - - - - - - - - - - - - - - - - - ); -} - -const mapStateToProps = (state, props) => ({ - resourceName: props.optionsResource, -}); - -const withResourceFilterValueField = connect(mapStateToProps); - -export default compose( - withResourceFilterValueField, - withResourceDetail(({ resourceData }) => ({ resourceData })), - withResourceActions, -)(DynamicFilterValueField); diff --git a/client/src/components/AdvancedFilter/AdvancedFilterValueField2.tsx b/client/src/components/AdvancedFilter/AdvancedFilterValueField2.tsx deleted file mode 100644 index c30a07e8a..000000000 --- a/client/src/components/AdvancedFilter/AdvancedFilterValueField2.tsx +++ /dev/null @@ -1,104 +0,0 @@ -import React from 'react'; -import { Position, Checkbox, InputGroup, FormGroup } from '@blueprintjs/core'; -import { DateInput } from '@blueprintjs/datetime'; -import moment from 'moment'; -import intl from 'react-intl-universal'; -import { Choose, ListSelect } from 'components'; -import { momentFormatter, tansformDateValue } from 'utils'; -import { IFieldType, IAdvancedFilterValueField } from './interfaces'; - -function AdvancedFilterEnumerationField({ options, value, ...rest }) { - return ( - - ); -} - -/** - * Advanced filter value field detarminer. - */ -export default function AdvancedFilterValueField2({ - fieldType, - options, - onChange, -}: IAdvancedFilterValueField) { - const [localValue, setLocalValue] = React.useState(''); - - const triggerOnChange = (value: string) => onChange && onChange(value); - - // Handle input change. - const handleInputChange = (e) => { - if (e.currentTarget.type === 'checkbox') { - setLocalValue(e.currentTarget.checked); - triggerOnChange(e.currentTarget.checked); - } else { - setLocalValue(e.currentTarget.value); - triggerOnChange(e.currentTarget.value); - } - }; - - // Handle enumeration field type change. - const handleEnumerationChange = (option) => { - setLocalValue(option.key); - triggerOnChange(option.key); - }; - - // Handle date field change. - const handleDateChange = (date: Date) => { - const formattedDate: string = moment(date).format('YYYY/MM/DD'); - - setLocalValue(formattedDate); - triggerOnChange(formattedDate); - }; - - return ( - - - - - - - - - - - - - - - - - - - - ); -} diff --git a/client/src/components/AdvancedFilter/components.tsx b/client/src/components/AdvancedFilter/components.js similarity index 88% rename from client/src/components/AdvancedFilter/components.tsx rename to client/src/components/AdvancedFilter/components.js index 57b78fd3c..4e139ca65 100644 --- a/client/src/components/AdvancedFilter/components.tsx +++ b/client/src/components/AdvancedFilter/components.js @@ -9,7 +9,7 @@ const DEBOUNCE_MS = 100; */ export function useAdvancedFilterAutoSubmit() { const { submitForm, values } = useFormikContext(); - const [isSubmit, setIsSubmit] = React.useState(false); + const [isSubmit, setIsSubmit] = React.useState(false); const debouncedSubmit = React.useCallback( debounce(() => { diff --git a/client/src/components/AdvancedFilter/interfaces.ts b/client/src/components/AdvancedFilter/interfaces.ts index 6ee8b0a7b..8fe9d705b 100644 --- a/client/src/components/AdvancedFilter/interfaces.ts +++ b/client/src/components/AdvancedFilter/interfaces.ts @@ -1,4 +1,5 @@ import { ArrayHelpers } from 'formik'; +import { IPopoverProps } from '@blueprintjs/core'; export type IResourceFieldType = 'text' | 'number' | 'enumeration' | 'boolean'; @@ -10,9 +11,12 @@ export interface IResourceField { export interface IAdvancedFilterDropdown { fields: IResourceField[]; + conditions?: IFilterRole[]; defaultFieldKey: string; defaultComparator?: string; defaultValue?: string; + defaultCondition?: string; + onFilterChange?: (filterRoles: IFilterRole[]) => void; } export interface IAdvancedFilterDropdownFooter { @@ -69,6 +73,7 @@ export interface IFilterOption { export interface IAdvancedFilterValueField { fieldType: string; + value?: string; key: string; label: string; options?: IFilterOption[]; @@ -82,3 +87,25 @@ export enum IFieldType { ENUMERATION = 'enumeration', BOOLEAN = 'boolean', } + +export interface IConditionTypeOption { + value: string; + label: string; +} + +export interface IConditionOption { + label: string; + value: string; + text?: string; +} + +export interface IAdvancedFilterPopover { + popoverProps?: IPopoverProps; + advancedFilterProps: IAdvancedFilterDropdown; + children: JSX.Element | JSX.Element[]; +} + + +export interface IDynamicFilterCompatatorFieldProps { + dataType: string; +} diff --git a/client/src/components/AdvancedFilter/utils.js b/client/src/components/AdvancedFilter/utils.js new file mode 100644 index 000000000..441864897 --- /dev/null +++ b/client/src/components/AdvancedFilter/utils.js @@ -0,0 +1,110 @@ +import intl from 'react-intl-universal'; +import { + defaultFastFieldShouldUpdate, + uniqueMultiProps, + checkRequiredProperties, +} from 'utils'; + +// Conditions options. +export const getConditionalsOptions = () => [ + { + value: 'and', + label: intl.get('and'), + text: intl.get('filter.all_filters_must_match'), + }, + { + value: 'or', + label: intl.get('or'), + text: intl.get('filter.atleast_one_filter_must_match'), + }, +]; + +export const getBooleanCompatators = () => [ + { value: 'is', label: intl.get('is') }, + { value: 'is_not', label: intl.get('is_not') }, +]; + +export const getTextCompatators = () => [ + { value: 'contain', label: intl.get('contain') }, + { value: 'not_contain', label: intl.get('not_contain') }, + { value: 'equal', label: intl.get('equals') }, + { value: 'not_equal', label: intl.get('not_equals') }, +]; + +export const getDateCompatators = () => [ + { value: 'in', label: intl.get('in') }, + { value: 'after', label: intl.get('after') }, + { value: 'before', label: intl.get('before') }, +]; + +export const getOptionsCompatators = () => [ + { value: 'is', label: intl.get('is') }, + { value: 'is_not', label: intl.get('is_not') }, +]; + +export const getNumberCampatators = () => [ + { value: 'equal', label: intl.get('equals') }, + { value: 'not_equal', label: intl.get('not_equal') }, + { value: 'bigger_than', label: intl.get('bigger_than') }, + { value: 'bigger_or_equal', label: intl.get('bigger_or_equals') }, + { value: 'smaller_than', label: intl.get('smaller_than') }, + { value: 'smaller_or_equal', label: intl.get('smaller_or_equals') }, +]; + +export const getConditionTypeCompatators = ( + dataType, +) => { + return [ + ...(dataType === 'enumeration' + ? [...getOptionsCompatators()] + : dataType === 'date' + ? [...getDateCompatators()] + : dataType === 'boolean' + ? [...getBooleanCompatators()] + : dataType === 'number' + ? [...getNumberCampatators()] + : [...getTextCompatators()]), + ]; +}; + +export const getConditionDefaultCompatator = ( + dataType, +) => { + const compatators = getConditionTypeCompatators(dataType); + return compatators[0]; +}; + +export const transformFieldsToOptions = (fields) => + fields.map((field) => ({ + value: field.key, + label: field.name, + })); + +/** + * Filtered conditions that don't contain atleast on required fields or + * fileds keys that not exists. + * @param {IFilterRole[]} conditions + * @returns + */ +export const filterConditionRoles = ( + conditions, +) => { + const requiredProps = ['fieldKey', 'condition', 'comparator', 'value']; + + const filteredConditions = conditions.filter( + (condition) => + !checkRequiredProperties(condition, requiredProps), + ); + return uniqueMultiProps(filteredConditions, requiredProps); +}; + +/** + * Detarmines the value field when should update. + * @returns {boolean} + */ +export const shouldFilterValueFieldUpdate = (newProps, oldProps) => { + return ( + newProps.fieldKey !== oldProps.fieldKey || + defaultFastFieldShouldUpdate(newProps, oldProps) + ); +}; \ No newline at end of file diff --git a/client/src/components/AdvancedFilter/utils.ts b/client/src/components/AdvancedFilter/utils.ts deleted file mode 100644 index a01044726..000000000 --- a/client/src/components/AdvancedFilter/utils.ts +++ /dev/null @@ -1,98 +0,0 @@ -import intl from 'react-intl-universal'; -import { IResourceField, IFilterRole } from './interfaces'; -import { uniqueMultiProps, checkRequiredProperties } from 'utils'; - -interface IConditionOption { - label: string; - value: string; -} - -// Conditions options. -export const getConditionalsOptions = (): IConditionOption[] => [ - { value: 'and', label: intl.get('and') }, - { value: 'or', label: intl.get('or') }, -]; - -interface IConditionTypeOption { - value: string; - label: string; -} - -export const getBooleanCompatators = (): IConditionTypeOption[] => [ - { value: 'is', label: 'is' }, - { value: 'is_not', label: 'is_not' }, -]; - -export const getTextCompatators = (): IConditionTypeOption[] => [ - { value: 'contain', label: 'contain' }, - { value: 'not_contain', label: 'not_contain' }, - { value: 'equals', label: 'equals' }, - { value: 'not_equal', label: 'not_equals' }, -]; - -export const getDateCompatators = (): IConditionTypeOption[] => [ - { value: 'in', label: 'in' }, - { value: 'after', label: 'after' }, - { value: 'before', label: 'before' }, -]; - -export const getOptionsCompatators = (): IConditionTypeOption[] => [ - { value: 'is', label: 'is' }, - { value: 'is_not', label: 'is_not' }, -]; - -export const getNumberCampatators = (): IConditionTypeOption[] => [ - { value: 'equals', label: 'equals' }, - { value: 'not_equal', label: 'not_equal' }, - { value: 'bigger_than', label: 'bigger_than' }, - { value: 'bigger_or_equals', label: 'bigger_or_equals' }, - { value: 'smaller_than', label: 'smaller_than' }, - { value: 'smaller_or_equals', label: 'smaller_or_equals' }, -]; - -export const getConditionTypeCompatators = ( - dataType: string, -): IConditionTypeOption[] => { - return [ - ...(dataType === 'options' - ? [...getOptionsCompatators()] - : dataType === 'date' - ? [...getDateCompatators()] - : dataType === 'boolean' - ? [...getBooleanCompatators()] - : dataType === 'number' - ? [...getNumberCampatators()] - : [...getTextCompatators()]), - ]; -}; - -export const getConditionDefaultCompatator = ( - dataType: string, -): IConditionTypeOption => { - const compatators = getConditionTypeCompatators(dataType); - return compatators[0]; -}; - -export const transformFieldsToOptions = (fields: IResourceField[]) => - fields.map((field) => ({ - value: field.key, - label: field.name, - })); - -/** - * Filtered conditions that don't contain atleast on required fields or - * fileds keys that not exists. - * @param {IFilterRole[]} conditions - * @returns - */ -export const filterConditionRoles = ( - conditions: IFilterRole[], -): IFilterRole[] => { - const requiredProps = ['fieldKey', 'condition', 'comparator', 'value']; - - const filteredConditions = conditions.filter( - (condition: IFilterRole) => - !checkRequiredProperties(condition, requiredProps), - ); - return uniqueMultiProps(filteredConditions, requiredProps); -}; diff --git a/client/src/components/Dashboard/DashboardFilterButton.js b/client/src/components/Dashboard/DashboardFilterButton.js new file mode 100644 index 000000000..973431d08 --- /dev/null +++ b/client/src/components/Dashboard/DashboardFilterButton.js @@ -0,0 +1,26 @@ +import React from 'react'; +import classNames from 'classnames'; +import intl from "react-intl-universal"; +import { Classes, Button } from '@blueprintjs/core'; +import { T, Icon } from 'components'; + +/** + * Dashboard advanced filter button. + */ +export function DashboardFilterButton({ conditionsCount }) { + return ( + - - - ); -} diff --git a/client/src/components/ListSelect.js b/client/src/components/ListSelect.js index 1035d184f..dbfb4d7ab 100644 --- a/client/src/components/ListSelect.js +++ b/client/src/components/ListSelect.js @@ -1,3 +1,4 @@ + import React, { useState, useMemo, useEffect } from 'react'; import { Button, MenuItem } from '@blueprintjs/core'; import { Select } from '@blueprintjs/select'; @@ -66,10 +67,23 @@ export default function ListSelect({ onItemSelect && onItemSelect(_item); }; + // Filters accounts types items. + const filterItems = (query, item, _index, exactMatch) => { + const normalizedTitle = item[textProp].toLowerCase(); + const normalizedQuery = query.toLowerCase(); + + if (exactMatch) { + return normalizedTitle === normalizedQuery; + } else { + return normalizedTitle.indexOf(normalizedQuery) >= 0; + } + }; + return ( ); diff --git a/client/src/components/index.js b/client/src/components/index.js index b6aa9dd50..d0d5904ce 100644 --- a/client/src/components/index.js +++ b/client/src/components/index.js @@ -62,6 +62,10 @@ import Card from './Card'; import { ItemsMultiSelect } from './Items'; export * from './Menu'; +export * from './AdvancedFilter/AdvancedFilterDropdown'; +export * from './AdvancedFilter/AdvancedFilterPopover'; +export * from './Dashboard/DashboardFilterButton'; +export * from './Dashboard/DashboardRowsHeightButton'; const Hint = FieldHint; diff --git a/client/src/containers/Accounting/JournalsLanding/ManualJournalActionsBar.js b/client/src/containers/Accounting/JournalsLanding/ManualJournalActionsBar.js index 1491775e8..023be03b9 100644 --- a/client/src/containers/Accounting/JournalsLanding/ManualJournalActionsBar.js +++ b/client/src/containers/Accounting/JournalsLanding/ManualJournalActionsBar.js @@ -5,24 +5,26 @@ import { NavbarGroup, Classes, NavbarDivider, - Popover, - PopoverInteractionKind, - Position, Intent, Alignment, } from '@blueprintjs/core'; -import classNames from 'classnames'; import { useHistory } from 'react-router-dom'; -import { FormattedMessage as T } from 'components'; +import { + AdvancedFilterPopover, + DashboardFilterButton, + FormattedMessage as T, +} from 'components'; import { useRefreshJournals } from 'hooks/query/manualJournals'; import { useManualJournalsContext } from './ManualJournalsListProvider'; import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar'; + import withDialogActions from 'containers/Dialog/withDialogActions'; +import withManualJournalsActions from './withManualJournalsActions'; +import withManualJournals from './withManualJournals'; import { If, DashboardActionViewsList } from 'components'; -import withManualJournalsActions from './withManualJournalsActions'; import { compose } from 'utils'; /** @@ -31,12 +33,15 @@ import { compose } from 'utils'; function ManualJournalActionsBar({ // #withManualJournalsActions setManualJournalsTableState, + + // #withManualJournals + manualJournalsFilterConditions, }) { // History context. const history = useHistory(); // Manual journals context. - const { journalsViews } = useManualJournalsContext(); + const { journalsViews, fields } = useManualJournalsContext(); // Manual journals refresh action. const { refresh } = useRefreshJournals(); @@ -45,7 +50,6 @@ function ManualJournalActionsBar({ const onClickNewManualJournal = () => { history.push('/make-journal-entry'); }; - // Handle delete button click. const handleBulkDelete = () => {}; @@ -53,11 +57,10 @@ function ManualJournalActionsBar({ const handleTabChange = (customView) => { setManualJournalsTableState({ customViewId: customView.id || null }); }; - // Handle click a refresh Journals - const handleRefreshBtnClick = () => { - refresh(); - }; + const handleRefreshBtnClick = () => { refresh(); }; + + console.log(manualJournalsFilterConditions, fields, 'XXX'); return ( @@ -75,20 +78,20 @@ function ManualJournalActionsBar({ text={} onClick={onClickNewManualJournal} /> - { + setManualJournalsTableState({ filterRoles: filterConditions }); + }, + }} > -