Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 46 additions & 4 deletions src/components/Badge.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
import React from 'react';
import PropTypes from 'prop-types';
import {omit} from 'ramda';
import {Badge as RSBadge} from 'reactstrap';
import Link from '../private/Link';

const Badge = props => {
const {children, loading_state, ...otherProps} = props;
const {children, href, loading_state, setProps, ...otherProps} = props;

const incrementClicks = () => {
if (setProps) {
setProps({
n_clicks: props.n_clicks + 1,
n_clicks_timestamp: Date.now()
});
}
};

otherProps[href ? 'preOnClick' : 'onClick'] = incrementClicks;

return (
<RSBadge
{...omit(['setProps'], otherProps)}
tag={href && Link}
href={href}
{...otherProps}
data-dash-is-loading={
(loading_state && loading_state.is_loading) || undefined
}
Expand All @@ -17,6 +31,11 @@ const Badge = props => {
);
};

Badge.defaultProps = {
n_clicks: 0,
n_clicks_timestamp: -1
};

Badge.propTypes = {
/**
* The ID of this component, used to identify dash components
Expand Down Expand Up @@ -84,7 +103,30 @@ Badge.propTypes = {
* Holds the name of the component that is loading
*/
component_name: PropTypes.string
})
}),

/**
* If true, the browser will treat this as an external link,
* forcing a page refresh at the new location. If false,
* this just changes the location without triggering a page
* refresh. Use this if you are observing dcc.Location, for
* instance. Defaults to true for absolute URLs and false
* otherwise.
*/
external_link: PropTypes.bool,

/**
* An integer that represents the number of times
* that this element has been clicked on.
*/
n_clicks: PropTypes.number,

/**
* An integer that represents the time (in ms since 1970)
* at which n_clicks changed. This can be used to tell
* which button was changed most recently.
*/
n_clicks_timestamp: PropTypes.number
};

export default Badge;
25 changes: 25 additions & 0 deletions src/components/__tests__/Badge.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';
import {mount, shallow} from 'enzyme';

import Badge from '../Badge';

describe('Badge', () => {
it('should track clicks', () => {
const mockSetProps = jest.fn();
const wrapper = shallow(<Badge setProps={mockSetProps}>Badge</Badge>);
wrapper.simulate('click');
expect(mockSetProps.mock.calls).toHaveLength(1);
expect(mockSetProps.mock.calls[0][0].n_clicks).toBe(1);
expect(typeof mockSetProps.mock.calls[0][0].n_clicks_timestamp).toBe(
'number'
);
});

it('should render as link when href is set', () => {
const href = '#href';
const wrapper = mount(<Badge href={href}>Badge</Badge>);
const linkComponent = wrapper.find('a');
expect(linkComponent.exists()).toBe(true);
expect(linkComponent.prop('href')).toEqual(href);
});
});