Traces: Fixed missing CopyButton on KeyValueTables and overlapping of panels (#49271)

* rewrote `CopyIcon` to an functional component

- fixed missing `CopyIcon` on `KeyValuesTable`

* added fixed height of `30px` to `KeyValuesTable` to fix overlapping

* removed unused CopyIcon snapshot

* KeyValuesTable: moved `30px` height from `tr` to `td` to fix vertical alignment
This commit is contained in:
svennergr
2022-05-20 20:24:33 +02:00
committed by GitHub
parent 426ca2999e
commit 2949ebc264
5 changed files with 29 additions and 77 deletions

View File

@@ -110,9 +110,6 @@ exports[`no enzyme tests`] = {
"packages/jaeger-ui-components/src/TraceTimelineViewer/index.test.js:381298544": [ "packages/jaeger-ui-components/src/TraceTimelineViewer/index.test.js:381298544": [
[14, 19, 13, "RegExp match", "2409514259"] [14, 19, 13, "RegExp match", "2409514259"]
], ],
"packages/jaeger-ui-components/src/common/CopyIcon.test.js:187212136": [
[15, 19, 13, "RegExp match", "2409514259"]
],
"packages/jaeger-ui-components/src/common/NewWindowIcon.test.js:1750458349": [ "packages/jaeger-ui-components/src/common/NewWindowIcon.test.js:1750458349": [
[14, 19, 13, "RegExp match", "2409514259"] [14, 19, 13, "RegExp match", "2409514259"]
], ],

View File

@@ -46,6 +46,7 @@ export const getStyles = (theme: GrafanaTheme2) => {
label: row; label: row;
& > td { & > td {
padding: 0rem 0.5rem; padding: 0rem 0.5rem;
height: 30px;
} }
&:nth-child(2n) > td { &:nth-child(2n) > td {
background: ${autoColor(theme, '#f5f5f5')}; background: ${autoColor(theme, '#f5f5f5')};

View File

@@ -12,12 +12,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { render, screen } from '@testing-library/react';
import * as copy from 'copy-to-clipboard'; import * as copy from 'copy-to-clipboard';
import { shallow } from 'enzyme';
import React from 'react'; import React from 'react';
import { Button, Tooltip } from '@grafana/ui';
import CopyIcon from './CopyIcon'; import CopyIcon from './CopyIcon';
jest.mock('copy-to-clipboard'); jest.mock('copy-to-clipboard');
@@ -29,7 +27,6 @@ describe('<CopyIcon />', () => {
tooltipTitle: 'tooltipTitleValue', tooltipTitle: 'tooltipTitleValue',
}; };
let copySpy; let copySpy;
let wrapper;
beforeAll(() => { beforeAll(() => {
copySpy = jest.spyOn(copy, 'default'); copySpy = jest.spyOn(copy, 'default');
@@ -37,24 +34,18 @@ describe('<CopyIcon />', () => {
beforeEach(() => { beforeEach(() => {
copySpy.mockReset(); copySpy.mockReset();
wrapper = shallow(<CopyIcon {...props} />);
}); });
it('renders as expected', () => { it('renders as expected', () => {
expect(wrapper).toMatchSnapshot(); expect(() => render(<CopyIcon {...props} />)).not.toThrow();
}); });
it('updates state and copies when clicked', () => { it('copies when clicked', () => {
expect(wrapper.state().hasCopied).toBe(false); render(<CopyIcon {...props} />);
expect(copySpy).not.toHaveBeenCalled();
const button = screen.getByRole('button');
button.click();
wrapper.find(Button).simulate('click');
expect(wrapper.state().hasCopied).toBe(true);
expect(copySpy).toHaveBeenCalledWith(props.copyText); expect(copySpy).toHaveBeenCalledWith(props.copyText);
}); });
it('persists state when tooltip opens', () => {
wrapper.setState({ hasCopied: true });
expect(wrapper.state().hasCopied).toBe(true);
});
}); });

View File

@@ -15,11 +15,11 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import cx from 'classnames'; import cx from 'classnames';
import copy from 'copy-to-clipboard'; import copy from 'copy-to-clipboard';
import * as React from 'react'; import React, { useState } from 'react';
import { Button, IconName, stylesFactory, Tooltip } from '@grafana/ui'; import { Button, IconName, Tooltip, useStyles2 } from '@grafana/ui';
const getStyles = stylesFactory(() => { const getStyles = () => {
return { return {
CopyIcon: css` CopyIcon: css`
background-color: transparent; background-color: transparent;
@@ -27,14 +27,13 @@ const getStyles = stylesFactory(() => {
color: inherit; color: inherit;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
padding: 0px;
&:focus { &:focus {
background-color: rgba(255, 255, 255, 0.25); background-color: rgba(255, 255, 255, 0.25);
color: inherit; color: inherit;
} }
`, `,
}; };
}); };
type PropsType = { type PropsType = {
className?: string; className?: string;
@@ -43,46 +42,24 @@ type PropsType = {
tooltipTitle: string; tooltipTitle: string;
}; };
type StateType = { export default function CopyIcon(props: PropsType) {
hasCopied: boolean; const styles = useStyles2(getStyles);
};
export default class CopyIcon extends React.PureComponent<PropsType, StateType> { const [hasCopied, setHasCopied] = useState(false);
static defaultProps: Partial<PropsType> = {
className: undefined, const handleClick = () => {
icon: 'copy', copy(props.copyText);
setHasCopied(true);
}; };
state = { return (
hasCopied: false, <Tooltip content={hasCopied ? 'Copied' : props.tooltipTitle}>
}; <Button className={cx(styles.CopyIcon)} type="button" icon={props.icon} onClick={handleClick} />
</Tooltip>
handleClick = () => { );
this.setState({
hasCopied: true,
});
copy(this.props.copyText);
};
handleTooltipVisibilityChange = (visible: boolean) => {
if (!visible && this.state.hasCopied) {
this.setState({
hasCopied: false,
});
}
};
render() {
const styles = getStyles();
return (
<Tooltip content={this.state.hasCopied ? 'Copied' : this.props.tooltipTitle}>
<Button
className={cx(styles.CopyIcon, this.props.className)}
type="button"
icon={this.props.icon}
onClick={this.handleClick}
/>
</Tooltip>
);
}
} }
CopyIcon.defaultProps = {
icon: 'copy',
className: undefined,
};

View File

@@ -1,14 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<CopyIcon /> renders as expected 1`] = `
<Tooltip
content="tooltipTitleValue"
>
<Button
className="css-oqwzau classNameValue"
icon="copy"
onClick={[Function]}
type="button"
/>
</Tooltip>
`;