Introduce button to copy request / response body to clipboard
Summary: Changelog: [Network] Introduce a copy button for request / response bodies Reviewed By: passy Differential Revision: D28222152 fbshipit-source-id: db33c8e91cbbe733502b32df75de14290e6f3d95
This commit is contained in:
committed by
Facebook GitHub Bot
parent
72e34bbd0d
commit
9c5967caf9
@@ -28,6 +28,7 @@ export const Panel: React.FC<{
|
|||||||
collapsed?: boolean;
|
collapsed?: boolean;
|
||||||
pad?: Spacing;
|
pad?: Spacing;
|
||||||
gap?: Spacing;
|
gap?: Spacing;
|
||||||
|
extraActions?: React.ReactElement | null;
|
||||||
}> = (props) => {
|
}> = (props) => {
|
||||||
const [collapsed, setCollapsed] = useLocalStorageState(
|
const [collapsed, setCollapsed] = useLocalStorageState(
|
||||||
`panel:${props.title}:collapsed`,
|
`panel:${props.title}:collapsed`,
|
||||||
@@ -49,7 +50,16 @@ export const Panel: React.FC<{
|
|||||||
onChange={toggle}>
|
onChange={toggle}>
|
||||||
<Collapse.Panel
|
<Collapse.Panel
|
||||||
key={props.title}
|
key={props.title}
|
||||||
header={props.title}
|
header={
|
||||||
|
props.extraActions ? (
|
||||||
|
<Layout.Right center>
|
||||||
|
<span>{props.title}</span>
|
||||||
|
{props.extraActions}
|
||||||
|
</Layout.Right>
|
||||||
|
) : (
|
||||||
|
props.title
|
||||||
|
)
|
||||||
|
}
|
||||||
showArrow={props.collapsible !== false}>
|
showArrow={props.collapsible !== false}>
|
||||||
<Layout.Container pad={props.pad} gap={props.pad}>
|
<Layout.Container pad={props.pad} gap={props.pad}>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
|||||||
@@ -23,11 +23,18 @@ import {
|
|||||||
} from 'flipper-plugin';
|
} from 'flipper-plugin';
|
||||||
import {Select, Typography} from 'antd';
|
import {Select, Typography} from 'antd';
|
||||||
|
|
||||||
import {bodyAsBinary, bodyAsString, formatBytes, getHeaderValue} from './utils';
|
import {
|
||||||
|
bodyAsBinary,
|
||||||
|
bodyAsString,
|
||||||
|
formatBytes,
|
||||||
|
getHeaderValue,
|
||||||
|
isTextual,
|
||||||
|
} from './utils';
|
||||||
import {Request, Header, Insights, RetryInsights} from './types';
|
import {Request, Header, Insights, RetryInsights} from './types';
|
||||||
import {BodyOptions} from './index';
|
import {BodyOptions} from './index';
|
||||||
import {ProtobufDefinitionsRepository} from './ProtobufDefinitionsRepository';
|
import {ProtobufDefinitionsRepository} from './ProtobufDefinitionsRepository';
|
||||||
import {KeyValueItem, KeyValueTable} from './KeyValueTable';
|
import {KeyValueItem, KeyValueTable} from './KeyValueTable';
|
||||||
|
import {CopyOutlined} from '@ant-design/icons';
|
||||||
|
|
||||||
const {Text} = Typography;
|
const {Text} = Typography;
|
||||||
|
|
||||||
@@ -35,6 +42,7 @@ type RequestDetailsProps = {
|
|||||||
request: Request;
|
request: Request;
|
||||||
bodyFormat: string;
|
bodyFormat: string;
|
||||||
onSelectFormat: (bodyFormat: string) => void;
|
onSelectFormat: (bodyFormat: string) => void;
|
||||||
|
onCopyText(test: string): void;
|
||||||
};
|
};
|
||||||
export default class RequestDetails extends Component<RequestDetailsProps> {
|
export default class RequestDetails extends Component<RequestDetailsProps> {
|
||||||
urlColumns = (url: URL) => {
|
urlColumns = (url: URL) => {
|
||||||
@@ -59,7 +67,7 @@ export default class RequestDetails extends Component<RequestDetailsProps> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {request, bodyFormat, onSelectFormat} = this.props;
|
const {request, bodyFormat, onSelectFormat, onCopyText} = this.props;
|
||||||
const url = new URL(request.url);
|
const url = new URL(request.url);
|
||||||
|
|
||||||
const formattedText = bodyFormat == 'formatted';
|
const formattedText = bodyFormat == 'formatted';
|
||||||
@@ -83,7 +91,21 @@ export default class RequestDetails extends Component<RequestDetailsProps> {
|
|||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{request.requestData != null ? (
|
{request.requestData != null ? (
|
||||||
<Panel key="requestData" title={'Request Body'} pad>
|
<Panel
|
||||||
|
key="requestData"
|
||||||
|
title={'Request Body'}
|
||||||
|
extraActions={
|
||||||
|
isTextual(request.requestHeaders) ? (
|
||||||
|
<CopyOutlined
|
||||||
|
title="Copy request body"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
onCopyText(request.requestData as string);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
pad>
|
||||||
<RequestBodyInspector
|
<RequestBodyInspector
|
||||||
formattedText={formattedText}
|
formattedText={formattedText}
|
||||||
request={request}
|
request={request}
|
||||||
@@ -106,6 +128,17 @@ export default class RequestDetails extends Component<RequestDetailsProps> {
|
|||||||
title={`Response Body${
|
title={`Response Body${
|
||||||
request.responseIsMock ? ' (Mocked)' : ''
|
request.responseIsMock ? ' (Mocked)' : ''
|
||||||
}`}
|
}`}
|
||||||
|
extraActions={
|
||||||
|
isTextual(request.responseHeaders) && request.responseData ? (
|
||||||
|
<CopyOutlined
|
||||||
|
title="Copy response body"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
onCopyText(request.responseData as string);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
pad>
|
pad>
|
||||||
<ResponseBodyInspector
|
<ResponseBodyInspector
|
||||||
formattedText={formattedText}
|
formattedText={formattedText}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {createRef} from 'react';
|
import React, {createRef} from 'react';
|
||||||
import {Button, Menu, Modal, Typography} from 'antd';
|
import {Button, Menu, message, Modal, Typography} from 'antd';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Layout,
|
Layout,
|
||||||
@@ -308,6 +308,10 @@ export function plugin(client: PluginClient<Events, Methods>) {
|
|||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
onCopyText(text: string) {
|
||||||
|
client.writeTextToClipboard(text);
|
||||||
|
message.success('Text copied to clipboard');
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,6 +422,7 @@ function Sidebar() {
|
|||||||
request={request}
|
request={request}
|
||||||
bodyFormat={detailBodyFormat}
|
bodyFormat={detailBodyFormat}
|
||||||
onSelectFormat={instance.onSelectFormat}
|
onSelectFormat={instance.onSelectFormat}
|
||||||
|
onCopyText={instance.onCopyText}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user