mirror of
https://github.com/microsoft/playwright.git
synced 2024-12-13 17:14:02 +03:00
feat(trace-viewer): add parameters copy to clip (#19662)
This commit is contained in:
parent
b363902e1b
commit
166a729386
@ -49,7 +49,7 @@
|
||||
|
||||
.call-line {
|
||||
padding: 4px 0 4px 6px;
|
||||
flex: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
@ -57,6 +57,25 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.call-line__copy-icon {
|
||||
visibility: hidden;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.call-line:hover .call-line__copy-icon {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.call-value {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.call-value::before {
|
||||
content: '\00a0';
|
||||
}
|
||||
|
||||
.call-line .datetime,
|
||||
.call-line .string {
|
||||
color: var(--orange);
|
||||
|
@ -20,6 +20,7 @@ import type { ActionTraceEvent } from '@trace/trace';
|
||||
import { msToString } from '@web/uiUtils';
|
||||
import * as React from 'react';
|
||||
import './callTab.css';
|
||||
import { CopyToClipboard } from './copyToClipboard';
|
||||
|
||||
export const CallTab: React.FunctionComponent<{
|
||||
action: ActionTraceEvent | undefined,
|
||||
@ -42,8 +43,8 @@ export const CallTab: React.FunctionComponent<{
|
||||
<div className='call-line'>{action.metadata.apiName}</div>
|
||||
{<>
|
||||
<div className='call-section'>Time</div>
|
||||
{action.metadata.wallTime && <div className='call-line'>wall time: <span className='datetime' title={wallTime}>{wallTime}</span></div>}
|
||||
<div className='call-line'>duration: <span className='datetime' title={duration}>{duration}</span></div>
|
||||
{action.metadata.wallTime && <div className='call-line'>wall time: <span className='call-value datetime' title={wallTime}>{wallTime}</span></div>}
|
||||
<div className='call-line'>duration: <span className='call-value datetime' title={duration}>{duration}</span></div>
|
||||
</>}
|
||||
{ !!paramKeys.length && <div className='call-section'>Parameters</div> }
|
||||
{
|
||||
@ -66,12 +67,29 @@ export const CallTab: React.FunctionComponent<{
|
||||
</div>;
|
||||
};
|
||||
|
||||
function shouldCopy(type: string): boolean {
|
||||
return !!({
|
||||
'string': true,
|
||||
'number': true,
|
||||
'object': true,
|
||||
}[type]);
|
||||
}
|
||||
|
||||
function renderLine(metadata: CallMetadata, name: string, value: any, key: string) {
|
||||
const { title, type } = toString(metadata, name, value);
|
||||
let text = title.replace(/\n/g, '↵');
|
||||
if (type === 'string')
|
||||
text = `"${text}"`;
|
||||
return <div key={key} className='call-line'>{name}: <span className={type} title={title}>{text}</span></div>;
|
||||
return (
|
||||
<div key={key} className='call-line'>
|
||||
{name}: <span className={`call-value ${type}`} title={title}>{text}</span>
|
||||
{ shouldCopy(type) && (
|
||||
<span className='call-line__copy-icon'>
|
||||
<CopyToClipboard value={title} />
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function toString(metadata: CallMetadata, name: string, value: any): { title: string, type: string } {
|
||||
|
7
packages/trace-viewer/src/ui/copyToClipboard.css
Normal file
7
packages/trace-viewer/src/ui/copyToClipboard.css
Normal file
@ -0,0 +1,7 @@
|
||||
.codicon-check {
|
||||
color: var(--green);
|
||||
}
|
||||
|
||||
.codicon-close {
|
||||
color: var(--red);
|
||||
}
|
43
packages/trace-viewer/src/ui/copyToClipboard.tsx
Normal file
43
packages/trace-viewer/src/ui/copyToClipboard.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
import './copyToClipboard.css';
|
||||
|
||||
const TIMEOUT = 3000;
|
||||
const DEFAULT_ICON = 'codicon-clippy';
|
||||
const COPIED_ICON = 'codicon-check';
|
||||
const FAILED_ICON = 'codicon-close';
|
||||
|
||||
export const CopyToClipboard: React.FunctionComponent<{
|
||||
value: string,
|
||||
}> = ({ value }) => {
|
||||
const [iconClassName, setIconClassName] = React.useState(DEFAULT_ICON);
|
||||
|
||||
const handleCopy = React.useCallback(() => {
|
||||
navigator.clipboard.writeText(value).then(() => {
|
||||
setIconClassName(COPIED_ICON);
|
||||
setTimeout(() => {
|
||||
setIconClassName(DEFAULT_ICON);
|
||||
}, TIMEOUT);
|
||||
}, () => {
|
||||
setIconClassName(FAILED_ICON);
|
||||
});
|
||||
|
||||
}, [value]);
|
||||
|
||||
return <span className={`codicon ${iconClassName}`} onClick={handleCopy}/>;
|
||||
};
|
Loading…
Reference in New Issue
Block a user