Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add searchable prop in CategoryWidget to optionally use the search functionality #338

Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Add groupByDate tests [#346](https://github.com/CartoDB/carto-react/pull/346)
- Refactor PieWidgetUI [#341](https://github.com/CartoDB/carto-react/pull/341)
- Add searchable prop in CategoryWidget to optionally use the search functionality [#338](https://github.com/CartoDB/carto-react/pull/338)
- Implement stringSearch filter [#331](https://github.com/CartoDB/carto-react/pull/331)
- Add filters tests [#331](https://github.com/CartoDB/carto-react/pull/331)

Expand Down
6 changes: 6 additions & 0 deletions packages/react-ui/__tests__/widgets/CategoryWidgetUI.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,5 +161,11 @@ describe('CategoryWidgetUI', () => {
fireEvent.click(screen.getByText(/Search in 4 elements/));
fireEvent.click(screen.getByText(/Cancel/));
});

test('searchable prop', () => {
render(<CategoryWidgetUI data={DATA} maxItems={1} searchable={false} />);
expect(screen.queryByText('Search in 4 elements')).not.toBeInTheDocument();
expect(screen.getByText('Others (4)')).toBeInTheDocument();
});
});
});
23 changes: 13 additions & 10 deletions packages/react-ui/src/widgets/CategoryWidgetUI.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ function CategoryWidgetUI(props) {
order,
selectedCategories,
animation,
filterable
filterable,
searchable
} = props;
const [sortedData, setSortedData] = useState([]);
const [maxValue, setMaxValue] = useState(1);
Expand Down Expand Up @@ -283,15 +284,20 @@ function CategoryWidgetUI(props) {
[blockedCategories, labels, maxItems, searchValue, showAll]
);

const getCategoriesCount = useCallback(() => {
const blocked = blockedCategories.length;
return blocked ? data.length - blocked : data.length - maxItems;
}, [data, maxItems, blockedCategories]);

const getCategoryLabel = useCallback(
(name) => {
if (name === REST_CATEGORY) {
return 'Others';
return `Others ${searchable ? '' : `(${getCategoriesCount()})`}`;
} else {
return labels[name] || name;
}
},
[labels]
[getCategoriesCount, labels, searchable]
);

const getProgressbarLength = useCallback(
Expand Down Expand Up @@ -363,11 +369,6 @@ function CategoryWidgetUI(props) {
}
}, [animation, sortedData]);

const getCategoriesCount = useCallback(() => {
const blocked = blockedCategories.length;
return blocked ? data.length - blocked : data.length - maxItems;
}, [data, maxItems, blockedCategories]);

// Separated to simplify the widget layout but inside the main component to avoid passing all dependencies
const CategoryItem = (props) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any refactor here, moving 'internal' components to different files would be really appreciated

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, I'll add it to my backlog 👌

const { data, onCategoryClick } = props;
Expand Down Expand Up @@ -569,7 +570,7 @@ function CategoryWidgetUI(props) {
</>
)}
</Grid>
{data.length > maxItems ? (
{data.length > maxItems && searchable ? (
showAll ? (
<Button size='small' color='primary' onClick={handleCancelClicked}>
Cancel
Expand Down Expand Up @@ -606,7 +607,8 @@ CategoryWidgetUI.defaultProps = {
order: CategoryWidgetUI.ORDER_TYPES.RANKING,
selectedCategories: [],
animation: true,
filterable: true
filterable: true,
searchable: true
};

CategoryWidgetUI.propTypes = {
Expand All @@ -624,6 +626,7 @@ CategoryWidgetUI.propTypes = {
order: PropTypes.oneOf(Object.values(CategoryWidgetUI.ORDER_TYPES)),
animation: PropTypes.bool,
filterable: PropTypes.bool,
searchable: PropTypes.bool
};

export default CategoryWidgetUI;
5 changes: 5 additions & 0 deletions packages/react-widgets/src/widgets/CategoryWidget.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const EMPTY_ARRAY = [];
* @param {Object} [props.labels] - Overwrite category labels.
* @param {boolean} [props.animation] - Enable/disable widget animations on data updates. Enabled by default.
* @param {boolean} [props.filterable] - Enable/disable widget filtering capabilities. Enabled by default.
* @param {boolean} [props.searchable] - Enable/disable widget searching capabilities. Enabled by default.
* @param {Function} [props.onError] - Function to handle error messages from the widget.
* @param {Object} [props.wrapperProps] - Extra props to pass to [WrapperWidgetUI](https://storybook-react.carto.com/?path=/docs/widgets-wrapperwidgetui--default)
* @param {Object} [props.noDataAlertProps] - Extra props to pass to [NoDataAlert]()
Expand All @@ -40,6 +41,7 @@ function CategoryWidget(props) {
labels,
animation,
filterable,
searchable,
onError,
wrapperProps,
noDataAlertProps
Expand Down Expand Up @@ -128,6 +130,7 @@ function CategoryWidget(props) {
onSelectedCategoriesChange={handleSelectedCategoriesChange}
animation={animation}
filterable={filterable}
searchable={searchable}
/>
) : (
<NoDataAlert {...noDataAlertProps} />
Expand All @@ -147,6 +150,7 @@ CategoryWidget.propTypes = {
labels: PropTypes.object,
animation: PropTypes.bool,
filterable: PropTypes.bool,
searchable: PropTypes.bool,
onError: PropTypes.func,
wrapperProps: PropTypes.object,
noDataAlertProps: PropTypes.object
Expand All @@ -156,6 +160,7 @@ CategoryWidget.defaultProps = {
labels: {},
animation: true,
filterable: true,
searchable: true,
wrapperProps: {},
noDataAlertProps: {}
};
Expand Down