Skip to content

Commit caed0b4

Browse files
authored
Migrate DetailsCard from ClassBased to Function based component (jaegertracing#2670)
## Which problem is this PR solving? - (jaegertracing#2610) ## Description of the changes - This PR migrates Details Card from a class based to a function based component. ## Checklist - [x] I have read https://github.com/jaegertracing/jaeger/blob/master/CONTRIBUTING_GUIDELINES.md - [x] I have signed all commits - [x] I have added unit tests for the new functionality - [ ] I have run lint and test steps successfully - for `jaeger`: `make lint test` - for `jaeger-ui`: `npm run lint` and `npm run test` Signed-off-by: yaten2302 <[email protected]>
1 parent b8986b3 commit caed0b4

File tree

2 files changed

+36
-53
lines changed

2 files changed

+36
-53
lines changed

packages/jaeger-ui/src/components/common/DetailsCard/index.test.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,20 @@ describe('DetailsCard', () => {
5959
});
6060

6161
it('renders as collapsible', () => {
62-
expect(shallow(<DetailsCard header={header} />).state('collapsed')).toBe(false);
62+
expect(
63+
shallow(<DetailsCard header={header} />)
64+
.find('.DetailsCard--DetailsWrapper')
65+
.hasClass('is-collapsed')
66+
).toBe(false);
6367

6468
const wrapper = shallow(<DetailsCard collapsible header={header} />);
65-
expect(wrapper.state('collapsed')).toBe(true);
69+
expect(wrapper.find('.DetailsCard--DetailsWrapper').hasClass('is-collapsed')).toBe(true);
6670
expect(wrapper).toMatchSnapshot();
6771

6872
wrapper.find('button').simulate('click');
69-
expect(wrapper.state('collapsed')).toBe(false);
73+
expect(wrapper.find('.DetailsCard--DetailsWrapper').hasClass('is-collapsed')).toBe(false);
7074

7175
wrapper.find('button').simulate('click');
72-
expect(wrapper.state('collapsed')).toBe(true);
76+
expect(wrapper.find('.DetailsCard--DetailsWrapper').hasClass('is-collapsed')).toBe(true);
7377
});
7478
});

packages/jaeger-ui/src/components/common/DetailsCard/index.tsx

+28-49
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ import cx from 'classnames';
1717
import { IoChevronDown } from 'react-icons/io5';
1818

1919
import { TColumnDefs, TDetails, TRow } from './types';
20-
import DetailTable from './DetailTable';
2120
import DetailList from './DetailList';
21+
import DetailTable from './DetailTable';
2222

2323
import './index.css';
2424

@@ -31,67 +31,46 @@ type TProps = {
3131
header: string;
3232
};
3333

34-
type TState = {
35-
collapsed: boolean;
36-
};
37-
3834
function isList(arr: string[] | TRow[]): arr is string[] {
3935
return typeof arr[0] === 'string';
4036
}
4137

42-
export default class DetailsCard extends React.PureComponent<TProps> {
43-
state: TState;
44-
45-
constructor(props: TProps) {
46-
super(props);
47-
48-
this.state = { collapsed: Boolean(props.collapsible) };
49-
}
50-
51-
renderDetails() {
52-
const { columnDefs, details } = this.props;
38+
function DetailsCard({ className, collapsible = false, description, header, columnDefs, details }: TProps) {
39+
const [isCollapsed, setIsCollapsed] = React.useState(Boolean(collapsible));
5340

41+
const renderDetails = () => {
5442
if (Array.isArray(details)) {
5543
if (details.length === 0) return null;
56-
5744
if (isList(details)) return <DetailList details={details} />;
5845
return <DetailTable columnDefs={columnDefs} details={details} />;
5946
}
60-
6147
return <span>{details}</span>;
62-
}
63-
64-
toggleCollapse = () => {
65-
this.setState((prevState: TState) => ({
66-
collapsed: !prevState.collapsed,
67-
}));
6848
};
6949

70-
render() {
71-
const { collapsed } = this.state;
72-
const { className, collapsible, description, header } = this.props;
73-
74-
return (
75-
<div className={cx('DetailsCard', className)}>
76-
<div className="DetailsCard--ButtonHeaderWrapper">
77-
{collapsible && (
78-
<button
79-
onClick={this.toggleCollapse}
80-
type="button"
81-
className={cx('DetailsCard--Collapser', { 'is-collapsed': collapsed })}
82-
>
83-
<IoChevronDown />
84-
</button>
85-
)}
86-
<div className="DetailsCard--HeaderWrapper">
87-
<span className="DetailsCard--Header">{header}</span>
88-
{description && <p className="DetailsCard--Description">{description}</p>}
89-
</div>
90-
</div>
91-
<div className={cx('DetailsCard--DetailsWrapper', { 'is-collapsed': collapsed })}>
92-
{this.renderDetails()}
50+
const toggleCollapsed = React.useCallback(() => setIsCollapsed(!isCollapsed), [isCollapsed]);
51+
52+
return (
53+
<div className={cx('DetailsCard', className)}>
54+
<div className="DetailsCard--ButtonHeaderWrapper">
55+
{collapsible && (
56+
<button
57+
onClick={toggleCollapsed}
58+
type="button"
59+
className={cx('DetailsCard--Collapser', { 'is-collapsed': isCollapsed })}
60+
>
61+
<IoChevronDown />
62+
</button>
63+
)}
64+
<div className="DetailsCard--HeaderWrapper">
65+
<span className="DetailsCard--Header">{header}</span>
66+
{description && <p className="DetailsCard--Description">{description}</p>}
9367
</div>
9468
</div>
95-
);
96-
}
69+
<div className={cx('DetailsCard--DetailsWrapper', { 'is-collapsed': isCollapsed })}>
70+
{renderDetails()}
71+
</div>
72+
</div>
73+
);
9774
}
75+
76+
export default DetailsCard;

0 commit comments

Comments
 (0)