Unverified Commit 94330854 authored by Allison Suarez Miranda's avatar Allison Suarez Miranda Committed by GitHub

feat: making clickable badges (#519)

* setting up for clickable badge component

* logic for search first try on badges

* we now have some really wonky looking clickable badges, don't quite work the way I expected them to yet

* major style changes, work in progress

* updated test on badge list

* lots of changes, functioning cloick and search

* clean up clean up everybody everywhere

* clean up pt 2

* lint

* fix

* fix make sure no config names change

* reverting change to navbar style because not part of this PR

* cleaning up an oopsie

* changed badgelist test to count ClickableBadge rather than Flag

* fixed test to reflect where the _ are replaced now

* commented out test

* moved badge

* updated imports

* removed all style and added pointer cursor

* samll fix to test

* Updated comment to reflect new functionality

* lint issue

* deleted old Badges dir

* fixed test

* fixed import

* applies to all badge styles

* lint

* applied cursor hover to clickable-badge rathern than flag

* added tests for clickable badges

* too many });

* fixed lint issue

* updated tests
parent d065a92c
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
import * as React from 'react'; import * as React from 'react';
import { shallow } from 'enzyme'; import { shallow } from 'enzyme';
import Flag from 'components/common/Flag'; import ClickableBadge from 'components/common/Badges';
import { BadgeStyle } from 'config/config-types'; import { BadgeStyle } from 'config/config-types';
import * as ConfigUtils from 'config/config-utils'; import * as ConfigUtils from 'config/config-utils';
import { Badge, TagType } from 'interfaces/Tags'; import { Badge, TagType } from 'interfaces/Tags';
...@@ -38,17 +38,17 @@ describe('BadgeList', () => { ...@@ -38,17 +38,17 @@ describe('BadgeList', () => {
expect(container.exists()).toBe(true); expect(container.exists()).toBe(true);
}); });
it('renders a <Flag> for each badge in the input', () => { it('renders a <ClickableBadge> for each badge in the input', () => {
expect(badgeList.find(Flag).length).toEqual(badges.length); expect(badgeList.find(ClickableBadge).length).toEqual(badges.length);
}); });
it('passes the correct props to the flag', () => { it('passes the correct props to the Clickable Badge', () => {
badges.forEach((badge, index) => { badges.forEach((badge, index) => {
const flag = badgeList.childAt(index); const clickableBadge = badgeList.childAt(index);
const flagProps = flag.props(); const clickableBadgeProps = clickableBadge.props();
const badgeConfig = ConfigUtils.getBadgeConfig(badge.tag_name); const badgeConfig = ConfigUtils.getBadgeConfig(badge.tag_name);
expect(flagProps.text).toEqual(badgeConfig.displayName); expect(clickableBadgeProps.text).toEqual(badgeConfig.displayName);
expect(flagProps.labelStyle).toEqual(badgeConfig.style); expect(clickableBadgeProps.labelStyle).toEqual(badgeConfig.style);
}); });
}); });
}); });
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
import * as React from 'react'; import * as React from 'react';
import Flag from 'components/common/Flag'; import ClickableBadge from 'components/common/Badges';
import { getBadgeConfig } from 'config/config-utils'; import { getBadgeConfig } from 'config/config-utils';
import { Badge } from 'interfaces/Tags'; import { Badge } from 'interfaces/Tags';
...@@ -18,7 +18,7 @@ const BadgeList: React.SFC<BadgeListProps> = ({ badges }: BadgeListProps) => { ...@@ -18,7 +18,7 @@ const BadgeList: React.SFC<BadgeListProps> = ({ badges }: BadgeListProps) => {
const badgeConfig = getBadgeConfig(badge.tag_name); const badgeConfig = getBadgeConfig(badge.tag_name);
return ( return (
<Flag <ClickableBadge
text={badgeConfig.displayName} text={badgeConfig.displayName}
labelStyle={badgeConfig.style} labelStyle={badgeConfig.style}
key={`badge-${index}`} key={`badge-${index}`}
......
import * as React from 'react';
import { shallow } from 'enzyme';
import Flag from 'components/common/Flag';
import { BadgeStyle } from 'config/config-types';
import { updateSearchState } from 'ducks/search/reducer';
import * as UtilMethods from 'ducks/utilMethods';
import { ClickableBadge, ClickableBadgeProps, mapDispatchToProps } from '.';
const logClickSpy = jest.spyOn(UtilMethods, 'logClick');
logClickSpy.mockImplementation(() => null);
jest.mock('ducks/search/reducer', () => ({
updateSearchState: jest.fn(),
}));
describe('ClickableBadge', () => {
const setup = (propOverrides?: Partial<ClickableBadgeProps>) => {
const props = {
text: 'test_badge',
labelStyle: BadgeStyle.PRIMARY,
searchBadge: jest.fn(),
...propOverrides,
};
const wrapper = shallow(<ClickableBadge {...props} />);
return { props, wrapper };
};
describe('onClick', () => {
let props;
let wrapper;
const mockEvent = {};
beforeAll(() => {
const setupResult = setup();
props = setupResult.props;
wrapper = setupResult.wrapper;
});
it('Calls the logClick utility function', () => {
logClickSpy.mockClear();
const expectedData = {
target_type: 'badge',
label: props.text,
};
wrapper.instance().onClick(mockEvent);
expect(logClickSpy).toHaveBeenCalledWith(mockEvent, expectedData);
});
it('it calls searchBadge', () => {
wrapper.instance().onClick(mockEvent);
expect(props.searchBadge).toHaveBeenCalledWith(props.text);
});
});
describe('render', () => {
let props;
let wrapper;
beforeAll(() => {
const setupResult = setup();
wrapper = setupResult.wrapper;
props = setupResult.props;
});
it('renders a <Flag> for the ClickableBadge', () => {
const flagPerBadge = 1;
expect(wrapper.find(Flag).length).toEqual(flagPerBadge);
});
it('renders with correct text', () => {
expect(wrapper.find(Flag).props().text).toEqual(props.text);
});
});
});
describe('mapDispatchToProps', () => {
let dispatch;
let result;
beforeAll(() => {
dispatch = jest.fn(() => Promise.resolve());
result = mapDispatchToProps(dispatch);
});
it('sets searchBadge on the props to trigger desired action', () => {
result.searchBadge();
expect(updateSearchState).toHaveBeenCalled();
});
});
// Copyright Contributors to the Amundsen project.
// SPDX-License-Identifier: Apache-2.0
import * as React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import Flag, { FlagProps } from 'components/common/Flag';
import { ResourceType } from 'interfaces';
import { updateSearchState } from 'ducks/search/reducer';
import { UpdateSearchStateRequest } from 'ducks/search/types';
import { logClick } from 'ducks/utilMethods';
import './styles.scss';
export interface DispatchFromProps {
searchBadge: (badgeText: string) => UpdateSearchStateRequest;
}
export type ClickableBadgeProps = FlagProps & DispatchFromProps;
export class ClickableBadge extends React.Component<ClickableBadgeProps> {
onClick = (e) => {
const badgeText = this.props.text;
logClick(e, {
target_type: 'badge',
label: badgeText,
});
this.props.searchBadge(badgeText);
};
render() {
return (
<span className="clickable-badge" onClick={this.onClick}>
<Flag
caseType={this.props.caseType}
text={this.props.text}
labelStyle={this.props.labelStyle}
/>
</span>
);
}
}
export const mapDispatchToProps = (dispatch: any) => {
return bindActionCreators(
{
searchBadge: (badgeText: string) =>
updateSearchState({
filters: {
[ResourceType.table]: { badges: badgeText },
},
submitSearch: true,
}),
},
dispatch
);
};
export default connect<null, DispatchFromProps, FlagProps>(
null,
mapDispatchToProps
)(ClickableBadge);
// Copyright Contributors to the Amundsen project.
// SPDX-License-Identifier: Apache-2.0
@import 'variables';
.clickable-badge {
&:hover {
cursor: pointer;
}
}
...@@ -77,14 +77,14 @@ export function getFilterConfigByResource( ...@@ -77,14 +77,14 @@ export function getFilterConfigByResource(
/* /*
* Given a badge name, this will return a badge style and a display name. * Given a badge name, this will return a badge style and a display name.
* If these are not specified by config, it will default to some simple rules: * If these are not specified by config, it will default to some simple rules:
* use BadgeStyle.DEFAULT and replace '-' and '_' with spaces for display name. * use BadgeStyle.DEFAULT and badge name as display name.
*/ */
export function getBadgeConfig(badgeName: string): BadgeStyleConfig { export function getBadgeConfig(badgeName: string): BadgeStyleConfig {
const config = AppConfig.badges[badgeName] || {}; const config = AppConfig.badges[badgeName] || {};
return { return {
style: BadgeStyle.DEFAULT, style: BadgeStyle.DEFAULT,
displayName: badgeName.replace(/[-_]/g, ' '), displayName: badgeName,
...config, ...config,
}; };
} }
......
...@@ -101,7 +101,7 @@ describe('getBadgeConfig', () => { ...@@ -101,7 +101,7 @@ describe('getBadgeConfig', () => {
const badgeName = 'not_configured_badge'; const badgeName = 'not_configured_badge';
const badgeConfig = ConfigUtils.getBadgeConfig(badgeName); const badgeConfig = ConfigUtils.getBadgeConfig(badgeName);
expect(badgeConfig.style).toEqual(BadgeStyle.DEFAULT); expect(badgeConfig.style).toEqual(BadgeStyle.DEFAULT);
expect(badgeConfig.displayName).toEqual('not configured badge'); expect(badgeConfig.displayName).toEqual(badgeName);
}); });
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment