mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 05:40:31 +00:00
feat: remove SET_DASHBOARD_REQUEST_LOADING reducer.
feat: fix dropdown filter. feat: fix fetch resource data.
This commit is contained in:
@@ -1,13 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Dialog, Spinner, Classes} from '@blueprintjs/core';
|
||||
|
||||
export default function DialogComponent(props) {
|
||||
const loadingContent = (
|
||||
<div className={Classes.DIALOG_BODY}><Spinner size={30} /></div>
|
||||
);
|
||||
return (
|
||||
<Dialog {...props}>
|
||||
{props.isLoading ? loadingContent : props.children}
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
22
client/src/components/Dialog/Dialog.js
Normal file
22
client/src/components/Dialog/Dialog.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import React from 'react';
|
||||
import { Dialog } from '@blueprintjs/core';
|
||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||
import { compose } from 'utils';
|
||||
|
||||
function DialogComponent(props) {
|
||||
const { name, children, closeDialog, onClose } = props;
|
||||
|
||||
const handleClose = (event) => {
|
||||
closeDialog(name)
|
||||
onClose && onClose(event);
|
||||
};
|
||||
return (
|
||||
<Dialog {...props} onClose={handleClose}>
|
||||
{ children }
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withDialogActions,
|
||||
)(DialogComponent);
|
||||
15
client/src/components/Dialog/DialogContent.js
Normal file
15
client/src/components/Dialog/DialogContent.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import React from 'react';
|
||||
import { Spinner, Classes } from '@blueprintjs/core';
|
||||
|
||||
export default function DialogContent(props) {
|
||||
const { isLoading, children } = props;
|
||||
|
||||
const loadingContent = (
|
||||
<div className={Classes.DIALOG_BODY}><Spinner size={30} /></div>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
{isLoading ? loadingContent : children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
18
client/src/components/Dialog/DialogSuspense.js
Normal file
18
client/src/components/Dialog/DialogSuspense.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import React, { Suspense } from 'react';
|
||||
import { Classes, Spinner } from '@blueprintjs/core';
|
||||
|
||||
function LoadingContent() {
|
||||
return (<div className={Classes.DIALOG_BODY}><Spinner size={30} /></div>);
|
||||
}
|
||||
|
||||
export default function DialogSuspense({
|
||||
children
|
||||
}) {
|
||||
return (
|
||||
<Suspense fallback={<LoadingContent /> }>
|
||||
<div className={'dialog__suspense-wrapper'}>
|
||||
{ children }
|
||||
</div>
|
||||
</Suspense>
|
||||
);
|
||||
};
|
||||
@@ -1,17 +1,15 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
isDialogOpenFactory,
|
||||
getDialogPayloadFactory,
|
||||
} from 'store/dashboard/dashboard.selectors';
|
||||
|
||||
export default (mapState, dialogName) => {
|
||||
const isDialogOpen = isDialogOpenFactory(dialogName);
|
||||
const getDialogPayload = getDialogPayloadFactory(dialogName);
|
||||
export default (mapState) => {
|
||||
const isDialogOpen = isDialogOpenFactory();
|
||||
const getDialogPayload = getDialogPayloadFactory();
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
const mapped = {
|
||||
dialogName,
|
||||
isOpen: isDialogOpen(state, props),
|
||||
payload: getDialogPayload(state, props),
|
||||
};
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
import React from 'react';
|
||||
import React, { lazy } from 'react';
|
||||
|
||||
import AccountFormDialog from 'containers/Dialogs/AccountFormDialog';
|
||||
import UserFormDialog from 'containers/Dialogs/UserFormDialog';
|
||||
import ItemCategoryDialog from 'containers/Dialogs/ItemCategoryDialog';
|
||||
import CurrencyDialog from 'containers/Dialogs/CurrencyDialog';
|
||||
import InviteUserDialog from 'containers/Dialogs/InviteUserDialog';
|
||||
import ExchangeRateDialog from 'containers/Dialogs/ExchangeRateDialog';
|
||||
// import UserFormDialog from 'containers/Dialogs/UserFormDialog';
|
||||
// import ItemCategoryDialog from 'containers/Dialogs/ItemCategoryDialog';
|
||||
// import CurrencyDialog from 'containers/Dialogs/CurrencyDialog';
|
||||
// import InviteUserDialog from 'containers/Dialogs/InviteUserDialog';
|
||||
// import ExchangeRateDialog from 'containers/Dialogs/ExchangeRateDialog';
|
||||
|
||||
|
||||
export default function DialogsContainer() {
|
||||
return (
|
||||
<div>
|
||||
<ExchangeRateDialog />
|
||||
{/* <InviteUserDialog /> */}
|
||||
<CurrencyDialog />
|
||||
<ItemCategoryDialog />
|
||||
<AccountFormDialog />
|
||||
{/* <UserFormDialog /> */}
|
||||
<AccountFormDialog dialogName={'account-form'} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export const BooleanCompatators = [
|
||||
{ value: 'is', label_id: 'is' },
|
||||
{ value: 'is_not', label_id: 'is_not' },
|
||||
];
|
||||
|
||||
export const TextCompatators = [
|
||||
@@ -20,6 +21,15 @@ export const OptionsCompatators = [
|
||||
{ value: 'is_not', label_id: 'is_not' },
|
||||
];
|
||||
|
||||
export const NumberCampatators = [
|
||||
{ value: 'equals', label_id: 'equals' },
|
||||
{ value: 'not_equal', label_id: 'not_equal' },
|
||||
{ value: 'bigger_than', label_id: 'bigger_than' },
|
||||
{ value: 'bigger_or_equals', label_id: 'bigger_or_equals' },
|
||||
{ value: 'smaller_than', label_id: 'smaller_than' },
|
||||
{ value: 'smaller_or_equals', label_id: 'smaller_or_equals' },
|
||||
]
|
||||
|
||||
export const getConditionTypeCompatators = (dataType) => {
|
||||
return [
|
||||
...(dataType === 'options'
|
||||
@@ -27,7 +37,9 @@ export const getConditionTypeCompatators = (dataType) => {
|
||||
: dataType === 'date'
|
||||
? [...DateCompatators]
|
||||
: dataType === 'boolean'
|
||||
? [...BooleanCompatators]
|
||||
? [...BooleanCompatators]
|
||||
: dataType === 'number'
|
||||
? [...NumberCampatators]
|
||||
: [...TextCompatators]),
|
||||
];
|
||||
};
|
||||
|
||||
@@ -14,72 +14,80 @@ import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
import { debounce } from 'lodash';
|
||||
import moment from 'moment';
|
||||
|
||||
import { If, Choose, ListSelect, MODIFIER } from 'components';
|
||||
import { Choose, ListSelect, MODIFIER } from 'components';
|
||||
|
||||
import withResourceDetail from 'containers/Resources/withResourceDetails';
|
||||
import withResourceActions from 'containers/Resources/withResourcesActions';
|
||||
|
||||
import {
|
||||
getConditionTypeCompatators,
|
||||
getConditionDefaultCompatator,
|
||||
} from './DynamicFilterCompatators';
|
||||
|
||||
import { compose, momentFormatter } from 'utils';
|
||||
|
||||
/**
|
||||
* Dynamic filter fields.
|
||||
*/
|
||||
function DynamicFilterValueField({
|
||||
dataType,
|
||||
value,
|
||||
|
||||
initialValue,
|
||||
error,
|
||||
// fieldkey,
|
||||
// resourceKey,
|
||||
|
||||
// #withResourceDetail
|
||||
resourceName,
|
||||
resourceData,
|
||||
resourceData = [],
|
||||
|
||||
requestResourceData,
|
||||
|
||||
// #ownProps
|
||||
fieldType,
|
||||
fieldName,
|
||||
value,
|
||||
initialValue,
|
||||
error,
|
||||
optionsResource,
|
||||
optionsKey = 'key',
|
||||
optionsLabel = 'label',
|
||||
options,
|
||||
onChange,
|
||||
rosourceKey,
|
||||
|
||||
inputDebounceWait = 500,
|
||||
inputDebounceWait = 250,
|
||||
}) {
|
||||
const { formatMessage } = useIntl();
|
||||
const [localValue, setLocalValue] = useState();
|
||||
|
||||
const fetchResourceData = useQuery(
|
||||
['resource-data', resourceName && resourceName],
|
||||
(k, resName) => requestResourceData(resName),
|
||||
{ manual: true },
|
||||
);
|
||||
|
||||
// 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 <MenuItem text={item.name} key={item.id} onClick={handleClick} />;
|
||||
return (<MenuItem
|
||||
text={item[optionsLabel]}
|
||||
key={item[optionsKey]}
|
||||
onClick={handleClick}
|
||||
/>);
|
||||
};
|
||||
|
||||
// Handle list button click.
|
||||
const handleBtnClick = () => {
|
||||
fetchResourceData.refetch({});
|
||||
|
||||
};
|
||||
|
||||
const listOptions = useMemo(() => Object.values(resourceData), [
|
||||
resourceData,
|
||||
const listOptions = useMemo(() => [
|
||||
...(resourceData || []),
|
||||
...(options || []),
|
||||
], [
|
||||
resourceData, options,
|
||||
]);
|
||||
|
||||
// Filters accounts types items.
|
||||
const filterItems = (query, item, _index, exactMatch) => {
|
||||
const normalizedTitle = item.name.toLowerCase();
|
||||
const normalizedTitle = item.label.toLowerCase();
|
||||
const normalizedQuery = query.toLowerCase();
|
||||
|
||||
if (exactMatch) {
|
||||
@@ -89,16 +97,16 @@ function DynamicFilterValueField({
|
||||
}
|
||||
};
|
||||
|
||||
// Handle list item selected.
|
||||
const onItemSelect = (item) => {
|
||||
onChange && onChange(item);
|
||||
onChange && onChange(item[optionsKey]);
|
||||
};
|
||||
|
||||
const handleInputChangeThrottled = useRef(
|
||||
debounce((value) => {
|
||||
onChange && onChange(value);
|
||||
}, inputDebounceWait),
|
||||
debounce((value) => { onChange && onChange(value); }, inputDebounceWait),
|
||||
);
|
||||
|
||||
// Handle input change.
|
||||
const handleInputChange = (e) => {
|
||||
if (e.currentTarget.type === 'checkbox') {
|
||||
setLocalValue(e.currentTarget.checked);
|
||||
@@ -108,12 +116,14 @@ function DynamicFilterValueField({
|
||||
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);
|
||||
@@ -126,7 +136,7 @@ function DynamicFilterValueField({
|
||||
return (
|
||||
<FormGroup className={'form-group--value'}>
|
||||
<Choose>
|
||||
<Choose.When condition={dataType === 'options'}>
|
||||
<Choose.When condition={fieldType === 'options'}>
|
||||
<ListSelect
|
||||
className={classNames(
|
||||
'list-select--filter-dropdown',
|
||||
@@ -146,14 +156,16 @@ function DynamicFilterValueField({
|
||||
}}
|
||||
onItemSelect={onItemSelect}
|
||||
selectedItem={value}
|
||||
selectedItemProp={'id'}
|
||||
defaultText={<T id={'select_account_type'} />}
|
||||
labelProp={'name'}
|
||||
buttonProps={{ onClick: handleBtnClick }}
|
||||
selectedItemProp={optionsKey}
|
||||
defaultText={`Select an option`}
|
||||
labelProp={optionsLabel}
|
||||
buttonProps={{
|
||||
onClick: handleBtnClick
|
||||
}}
|
||||
/>
|
||||
</Choose.When>
|
||||
|
||||
<Choose.When condition={dataType === 'date'}>
|
||||
<Choose.When condition={fieldType === 'date'}>
|
||||
<DateInput
|
||||
{...momentFormatter('YYYY/MM/DD')}
|
||||
value={transformDateValue(localValue)}
|
||||
@@ -167,7 +179,7 @@ function DynamicFilterValueField({
|
||||
/>
|
||||
</Choose.When>
|
||||
|
||||
<Choose.When condition={dataType === 'boolean'}>
|
||||
<Choose.When condition={fieldType === 'checkbox'}>
|
||||
<Checkbox value={localValue} onChange={handleCheckboxChange} />
|
||||
</Choose.When>
|
||||
|
||||
@@ -184,7 +196,7 @@ function DynamicFilterValueField({
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
resourceName: props.dataResource,
|
||||
resourceName: props.optionsResource,
|
||||
});
|
||||
|
||||
const withResourceFilterValueField = connect(mapStateToProps);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @flow
|
||||
import React, { useEffect, useMemo, useCallback, useRef } from 'react';
|
||||
// @flow
|
||||
import React, { useEffect, useMemo, useCallback, useState } from 'react';
|
||||
import {
|
||||
FormGroup,
|
||||
Classes,
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
import { useFormik } from 'formik';
|
||||
import { isEqual, last } from 'lodash';
|
||||
import { usePrevious } from 'react-use';
|
||||
import { debounce } from 'lodash';
|
||||
import Icon from 'components/Icon';
|
||||
import { checkRequiredProperties, uniqueMultiProps } from 'utils';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
@@ -22,7 +21,7 @@ import Toaster from 'components/AppToaster';
|
||||
import moment from 'moment';
|
||||
import {
|
||||
getConditionTypeCompatators,
|
||||
getConditionDefaultCompatator
|
||||
getConditionDefaultCompatator,
|
||||
} from './DynamicFilter/DynamicFilterCompatators';
|
||||
|
||||
let limitToast;
|
||||
@@ -39,224 +38,238 @@ type InitialCondition = {
|
||||
export default function FilterDropdown({
|
||||
fields,
|
||||
onFilterChange,
|
||||
refetchDebounceWait = 10,
|
||||
initialCondition,
|
||||
initialConditions,
|
||||
}) {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
// Fields key -> metadata table.
|
||||
const fieldsKeyMapped = useMemo(() =>
|
||||
new Map(fields.map((field) => [field.key, field])),
|
||||
[fields]
|
||||
);
|
||||
// Conditions options.
|
||||
const conditionalsOptions = useMemo(
|
||||
() => [
|
||||
{ value: '&&', label: formatMessage({ id: 'and' }) },
|
||||
{ value: '||', label: formatMessage({ id: 'or' }) },
|
||||
],
|
||||
[formatMessage],
|
||||
);
|
||||
// Resources fileds options for fields options.
|
||||
const resourceFieldsOptions = useMemo(
|
||||
() => [
|
||||
...fields.map((field) => ({
|
||||
value: field.key,
|
||||
label: field.label,
|
||||
})),
|
||||
],
|
||||
[fields],
|
||||
);
|
||||
// Default filter conition.
|
||||
const defaultFilterCondition = useMemo(
|
||||
() => ({
|
||||
condition: '&&',
|
||||
fieldKey: initialCondition.fieldKey,
|
||||
comparator: initialCondition.comparator,
|
||||
value: initialCondition.value,
|
||||
}),
|
||||
[initialCondition],
|
||||
);
|
||||
// Formik for validation purposes.
|
||||
const { setFieldValue, getFieldProps, values } = useFormik({
|
||||
initialValues: {
|
||||
conditions: [
|
||||
...((initialConditions && initialConditions.length) ?
|
||||
[...initialConditions] : [defaultFilterCondition]),
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
// Handle click a new filter row.
|
||||
const onClickNewFilter = useCallback(() => {
|
||||
if (values.conditions.length >= 12) {
|
||||
limitToast = Toaster.show(
|
||||
{
|
||||
message: formatMessage({ id: 'you_reached_conditions_limit' }),
|
||||
intent: Intent.WARNING,
|
||||
},
|
||||
limitToast,
|
||||
);
|
||||
} else {
|
||||
setFieldValue('conditions', [
|
||||
...values.conditions,
|
||||
defaultFilterCondition
|
||||
]);
|
||||
}
|
||||
}, [values, setFieldValue, formatMessage, defaultFilterCondition]);
|
||||
|
||||
// Filtered conditions that filters conditions that don't contain atleast
|
||||
// on required fields or fileds keys that not exists.
|
||||
const filteredFilterConditions = useMemo(() => {
|
||||
const requiredProps = ['fieldKey', 'condition', 'comparator', 'value'];
|
||||
|
||||
const conditions = values.conditions
|
||||
.filter(
|
||||
(condition) => !checkRequiredProperties(condition, requiredProps),
|
||||
)
|
||||
.filter(
|
||||
(condition) => !!fieldsKeyMapped.get(condition.fieldKey),
|
||||
);
|
||||
return uniqueMultiProps(conditions, requiredProps);
|
||||
}, [values.conditions, fieldsKeyMapped]);
|
||||
|
||||
// Previous filtered conditions.
|
||||
const prevConditions = usePrevious(filteredFilterConditions);
|
||||
|
||||
useEffect(() => {
|
||||
// Campare the current conditions with previous conditions, if they were equal
|
||||
// there is no need to execute `onFilterChange` function.
|
||||
if (!isEqual(prevConditions, filteredFilterConditions) && prevConditions) {
|
||||
onFilterChange && onFilterChange(filteredFilterConditions);
|
||||
}
|
||||
}, [filteredFilterConditions, prevConditions, onFilterChange]);
|
||||
|
||||
// Handle click remove condition.
|
||||
const onClickRemoveCondition = (index) => () => {
|
||||
if (values.conditions.length === 1) {
|
||||
setFieldValue('conditions', [defaultFilterCondition]);
|
||||
return;
|
||||
}
|
||||
const conditions = [...values.conditions];
|
||||
conditions.splice(index, 1);
|
||||
setFieldValue('conditions', [...conditions]);
|
||||
};
|
||||
|
||||
// Transform dynamic value field.
|
||||
const transformValueField = (value) => {
|
||||
if (value instanceof Date) {
|
||||
return moment(value).format('YYYY-MM-DD');
|
||||
} else if (typeof value === 'object') {
|
||||
return value.id;
|
||||
}
|
||||
return value;
|
||||
};
|
||||
// Override getFieldProps for conditions fields.
|
||||
const fieldProps = (name, index) => {
|
||||
const override = {
|
||||
...getFieldProps(`conditions[${index}].${name}`),
|
||||
};
|
||||
return {
|
||||
...override,
|
||||
onChange: (e) => {
|
||||
if (name === 'fieldKey') {
|
||||
const currentField = fieldsKeyMapped.get(
|
||||
values.conditions[index].fieldKey,
|
||||
);
|
||||
const nextField = fieldsKeyMapped.get(e.currentTarget.value);
|
||||
|
||||
if (currentField.field_type !== nextField.field_type) {
|
||||
setFieldValue(`conditions[${index}].value`, '');
|
||||
}
|
||||
const comparatorsObs = getConditionTypeCompatators(
|
||||
nextField.field_type,
|
||||
);
|
||||
const currentCompatator = values.conditions[index].comparator;
|
||||
|
||||
if (
|
||||
!currentCompatator ||
|
||||
comparatorsObs.map((c) => c.value).indexOf(currentCompatator) === -1
|
||||
) {
|
||||
const defaultCompatator = getConditionDefaultCompatator(
|
||||
nextField.field_type,
|
||||
);
|
||||
setFieldValue(
|
||||
`conditions[${index}].comparator`,
|
||||
defaultCompatator.value,
|
||||
);
|
||||
}
|
||||
}
|
||||
override.onChange(e);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// Compatator field props.
|
||||
const comparatorFieldProps = (name, index) => {
|
||||
const condition = values.conditions[index];
|
||||
const field = fieldsKeyMapped.get(condition.fieldKey);
|
||||
|
||||
return {
|
||||
...fieldProps(name, index),
|
||||
dataType: field.field_type,
|
||||
};
|
||||
};
|
||||
|
||||
// Value field props.
|
||||
const valueFieldProps = (name, index) => {
|
||||
const condition = values.conditions[index];
|
||||
const field = fieldsKeyMapped.get(condition.fieldKey);
|
||||
|
||||
return {
|
||||
...fieldProps(name, index),
|
||||
fieldName: field.label,
|
||||
fieldType: field.field_type,
|
||||
options: field.options,
|
||||
optionsResource: field.options_resource,
|
||||
onChange: (value) => {
|
||||
const transformedValue = transformValueField(value);
|
||||
setFieldValue(`conditions[${index}].${name}`, transformedValue);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
return (
|
||||
<div class="filter-dropdown">
|
||||
<div class="filter-dropdown__body">
|
||||
{values.conditions.map((condition, index) => (
|
||||
<div class="filter-dropdown__condition">
|
||||
<FormGroup className={'form-group--condition'}>
|
||||
<HTMLSelect
|
||||
options={conditionalsOptions}
|
||||
className={Classes.FILL}
|
||||
disabled={index > 1}
|
||||
{...fieldProps('condition', index)}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup className={'form-group--field'}>
|
||||
<HTMLSelect
|
||||
options={resourceFieldsOptions}
|
||||
value={1}
|
||||
className={Classes.FILL}
|
||||
{...fieldProps('fieldKey', index)}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup className={'form-group--comparator'}>
|
||||
<DynamicFilterCompatatorField
|
||||
className={Classes.FILL}
|
||||
{...comparatorFieldProps('comparator', index)}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<DynamicFilterValueField
|
||||
{...valueFieldProps('value', index)} />
|
||||
|
||||
<Button
|
||||
icon={<Icon icon="times" iconSize={14} />}
|
||||
minimal={true}
|
||||
onClick={onClickRemoveCondition(index)}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div class="filter-dropdown__footer">
|
||||
<Button
|
||||
minimal={true}
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={onClickNewFilter}
|
||||
>
|
||||
<T id={'new_conditional'} />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
// const { formatMessage } = useIntl();
|
||||
// const fieldsKeyMapped = new Map(fields.map((field) => [field.key, field]));
|
||||
|
||||
// const conditionalsItems = useMemo(
|
||||
// () => [
|
||||
// { value: 'and', label: formatMessage({ id: 'and' }) },
|
||||
// { value: 'or', label: formatMessage({ id: 'or' }) },
|
||||
// ],
|
||||
// [formatMessage],
|
||||
// );
|
||||
|
||||
// const resourceFields = useMemo(
|
||||
// () => [
|
||||
// ...fields.map((field) => ({
|
||||
// value: field.key,
|
||||
// label: field.label_name,
|
||||
// })),
|
||||
// ],
|
||||
// [fields],
|
||||
// );
|
||||
|
||||
// const defaultFilterCondition = useMemo(
|
||||
// () => ({
|
||||
// condition: 'and',
|
||||
// field_key: initialCondition.fieldKey,
|
||||
// comparator: initialCondition.comparator,
|
||||
// value: initialCondition.value,
|
||||
// }),
|
||||
// [fields],
|
||||
// );
|
||||
|
||||
// const { setFieldValue, getFieldProps, values } = useFormik({
|
||||
// enableReinitialize: true,
|
||||
// initialValues: {
|
||||
// conditions: [defaultFilterCondition],
|
||||
// },
|
||||
// });
|
||||
|
||||
// const onClickNewFilter = useCallback(() => {
|
||||
// if (values.conditions.length >= 12) {
|
||||
// limitToast = Toaster.show(
|
||||
// {
|
||||
// message: formatMessage({ id: 'you_reached_conditions_limit' }),
|
||||
// intent: Intent.WARNING,
|
||||
// },
|
||||
// limitToast,
|
||||
// );
|
||||
// } else {
|
||||
// setFieldValue('conditions', [
|
||||
// ...values.conditions,
|
||||
// last(values.conditions),
|
||||
// ]);
|
||||
// }
|
||||
// }, [values, defaultFilterCondition, setFieldValue]);
|
||||
|
||||
// const filteredFilterConditions = useMemo(() => {
|
||||
// const requiredProps = ['field_key', 'condition', 'comparator', 'value'];
|
||||
// const conditions = values.conditions.filter(
|
||||
// (condition) => !checkRequiredProperties(condition, requiredProps),
|
||||
// );
|
||||
// return uniqueMultiProps(conditions, requiredProps);
|
||||
// }, [values.conditions]);
|
||||
|
||||
// const prevConditions = usePrevious(filteredFilterConditions);
|
||||
|
||||
// const onFilterChangeThrottled = useRef(
|
||||
// debounce((conditions) => {
|
||||
// onFilterChange && onFilterChange(conditions);
|
||||
// }, refetchDebounceWait),
|
||||
// );
|
||||
|
||||
// useEffect(() => {
|
||||
// if (!isEqual(prevConditions, filteredFilterConditions) && prevConditions) {
|
||||
// onFilterChange && onFilterChange(filteredFilterConditions);
|
||||
// }
|
||||
// }, [filteredFilterConditions, prevConditions]);
|
||||
|
||||
// // Handle click remove condition.
|
||||
// const onClickRemoveCondition = (index) => () => {
|
||||
// if (values.conditions.length === 1) {
|
||||
// setFieldValue('conditions', [defaultFilterCondition]);
|
||||
// return;
|
||||
// }
|
||||
// const conditions = [...values.conditions];
|
||||
// conditions.splice(index, 1);
|
||||
// setFieldValue('conditions', [...conditions]);
|
||||
// };
|
||||
|
||||
// // Transform dynamic value field.
|
||||
// const transformValueField = (value) => {
|
||||
// if (value instanceof Date) {
|
||||
// return moment(value).format('YYYY-MM-DD');
|
||||
// } else if (typeof value === 'object') {
|
||||
// return value.id;
|
||||
// }
|
||||
// return value;
|
||||
// };
|
||||
// // Override getFieldProps for conditions fields.
|
||||
// const fieldProps = (name, index) => {
|
||||
// const override = {
|
||||
// ...getFieldProps(`conditions[${index}].${name}`),
|
||||
// };
|
||||
// return {
|
||||
// ...override,
|
||||
// onChange: (e) => {
|
||||
// if (name === 'field_key') {
|
||||
// const currentField = fieldsKeyMapped.get(
|
||||
// values.conditions[index].field_key,
|
||||
// );
|
||||
// const nextField = fieldsKeyMapped.get(e.currentTarget.value);
|
||||
|
||||
// if (currentField.data_type !== nextField.data_type) {
|
||||
// setFieldValue(`conditions[${index}].value`, '');
|
||||
// }
|
||||
// const comparatorsObs = getConditionTypeCompatators(nextField.data_type);
|
||||
// const currentCompatator = values.conditions[index].comparator;
|
||||
|
||||
// if (!currentCompatator || comparatorsObs.map(c => c.value).indexOf(currentCompatator) === -1) {
|
||||
// const defaultCompatator = getConditionDefaultCompatator(nextField.data_type);
|
||||
// setFieldValue(`conditions[${index}].comparator`, defaultCompatator.value);
|
||||
// }
|
||||
// }
|
||||
// override.onChange(e);
|
||||
// },
|
||||
// };
|
||||
// };
|
||||
|
||||
// // Compatator field props.
|
||||
// const comparatorFieldProps = (name, index) => {
|
||||
// const condition = values.conditions[index];
|
||||
// const field = fieldsKeyMapped.get(condition.field_key);
|
||||
|
||||
// return {
|
||||
// ...fieldProps(name, index),
|
||||
// dataType: field.data_type,
|
||||
// };
|
||||
// };
|
||||
|
||||
// // Value field props.
|
||||
// const valueFieldProps = (name, index) => {
|
||||
// const condition = values.conditions[index];
|
||||
// const field = fieldsKeyMapped.get(condition.field_key);
|
||||
|
||||
// return {
|
||||
// ...fieldProps(name, index),
|
||||
// dataType: field.data_type,
|
||||
// resourceKey: field.resource_key,
|
||||
// options: field.options,
|
||||
// dataResource: field.data_resource,
|
||||
// onChange: (value) => {
|
||||
// const transformedValue = transformValueField(value);
|
||||
// setFieldValue(`conditions[${index}].${name}`, transformedValue);
|
||||
// },
|
||||
// };
|
||||
// };
|
||||
|
||||
// return (
|
||||
// <div class="filter-dropdown">
|
||||
// <div class="filter-dropdown__body">
|
||||
// {values.conditions.map((condition, index) => (
|
||||
// <div class="filter-dropdown__condition">
|
||||
// <FormGroup className={'form-group--condition'}>
|
||||
// <HTMLSelect
|
||||
// options={conditionalsItems}
|
||||
// className={Classes.FILL}
|
||||
// disabled={index > 1}
|
||||
// {...fieldProps('condition', index)}
|
||||
// />
|
||||
// </FormGroup>
|
||||
|
||||
// <FormGroup className={'form-group--field'}>
|
||||
// <HTMLSelect
|
||||
// options={resourceFields}
|
||||
// value={1}
|
||||
// className={Classes.FILL}
|
||||
// {...fieldProps('field_key', index)}
|
||||
// />
|
||||
// </FormGroup>
|
||||
|
||||
// <FormGroup className={'form-group--comparator'}>
|
||||
// <DynamicFilterCompatatorField
|
||||
// className={Classes.FILL}
|
||||
// {...comparatorFieldProps('comparator', index)}
|
||||
// />
|
||||
// </FormGroup>
|
||||
|
||||
// <DynamicFilterValueField {...valueFieldProps('value', index)} />
|
||||
|
||||
// <Button
|
||||
// icon={<Icon icon="times" iconSize={14} />}
|
||||
// minimal={true}
|
||||
// onClick={onClickRemoveCondition(index)}
|
||||
// />
|
||||
// </div>
|
||||
// ))}
|
||||
// </div>
|
||||
|
||||
// <div class="filter-dropdown__footer">
|
||||
// <Button
|
||||
// minimal={true}
|
||||
// intent={Intent.PRIMARY}
|
||||
// onClick={onClickNewFilter}
|
||||
// >
|
||||
// <T id={'new_conditional'} />
|
||||
// </Button>
|
||||
// </div>
|
||||
// </div>
|
||||
// );
|
||||
}
|
||||
|
||||
9
client/src/components/Forms/InputPrepend.js
Normal file
9
client/src/components/Forms/InputPrepend.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
|
||||
export default function InputPrepend({ children }) {
|
||||
return (
|
||||
<div class="input-prepend">
|
||||
{ children }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
0
client/src/components/Forms/InputPrependOptions.js
Normal file
0
client/src/components/Forms/InputPrependOptions.js
Normal file
@@ -5,7 +5,7 @@ const Bar = ({ progress, animationDuration }) => (
|
||||
<div
|
||||
style={{
|
||||
background: '#79b8ff',
|
||||
height: 3,
|
||||
height: 4,
|
||||
left: 0,
|
||||
marginLeft: `${(-1 + progress) * 100}%`,
|
||||
position: 'fixed',
|
||||
|
||||
@@ -15,13 +15,15 @@ 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';
|
||||
import AccountsSelectList from './AccountsSelectList';
|
||||
import AccountsTypesSelect from './AccountsTypesSelect';
|
||||
import LoadingIndicator from './LoadingIndicator';
|
||||
import DashboardActionViewsList from './Dashboard/DashboardActionViewsList';
|
||||
import Dialog from './Dialog/Dialog';
|
||||
import DialogContent from './Dialog/DialogContent';
|
||||
import DialogSuspense from './Dialog/DialogSuspense';
|
||||
const Hint = FieldHint;
|
||||
|
||||
export {
|
||||
@@ -43,11 +45,13 @@ export {
|
||||
DashboardViewsTabs,
|
||||
CurrenciesSelectList,
|
||||
FieldRequiredHint,
|
||||
Dialog,
|
||||
AppToaster,
|
||||
DataTable,
|
||||
AccountsSelectList,
|
||||
AccountsTypesSelect,
|
||||
LoadingIndicator,
|
||||
DashboardActionViewsList,
|
||||
AppToaster,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogSuspense
|
||||
};
|
||||
Reference in New Issue
Block a user