openreplay/frontend/app/components/Session_/Fetch/FetchDetails.js
2021-05-01 15:12:01 +05:30

153 lines
No EOL
4 KiB
JavaScript

import { JSONTree, Label, Button, Tabs } from 'UI'
import cn from 'classnames';
import copy from 'copy-to-clipboard';
import stl from './fetchDetails.css';
import ResultTimings from '../../shared/ResultTimings/ResultTimings';
const REQUEST = 'REQUEST';
const RESPONSE = 'RESPONSE';
const TIMINGS = 'TIMINGS';
const TABS = [ REQUEST, RESPONSE, TIMINGS ].map(tab => ({ text: tab, key: tab }));
export default class FetchDetails extends React.PureComponent {
state = { activeTab: REQUEST, tabs: [] };
onTabClick = activeTab => this.setState({ activeTab })
componentDidMount() {
this.checkTabs();
}
renderActiveTab = tab => {
const { resource: { duration, timings }, isResult } = this.props;
switch(tab) {
case REQUEST:
const { resource: { payload } } = this.props;
let jsonPayload = undefined;
try {
jsonPayload = typeof payload === 'string' ? JSON.parse(payload) : payload
} catch (e) {}
return !!payload ? (
<div>
<div className="mt-6">
{/* <h5>{ 'Payload '}</h5> */}
{ jsonPayload === undefined
? <div className="ml-3 break-words my-3"> { payload } </div>
: <JSONTree src={ jsonPayload } collapsed={ false } enableClipboard />
}
</div>
<div className="divider"/>
</div>
) : ''
break;
case RESPONSE:
const { resource: { response = this.props.resource.body } } = this.props; // for IOS compat.
let jsonResponse = undefined;
try {
jsonResponse = JSON.parse(response);
} catch (e) {}
return !!response ? (
<div>
<div className="mt-6">
{/* <h5>{ 'Response '}</h5> */}
{ jsonResponse === undefined
? <div className="ml-3 break-words my-3"> { response } </div>
: <JSONTree src={ jsonResponse } collapsed={ false } enableClipboard />
}
</div>
<div className="divider"/>
</div>
// jsonResponse === undefined
// ? <div className="ml-3 break-words my-3"> { response } </div>
// : <JSONTree src={ jsonResponse } collapsed={ false } enableClipboard />
) : ''
break;
case TIMINGS:
return <ResultTimings duration={duration} timing={timings} />
}
}
componentDidUpdate(prevProps) {
if (prevProps.resource.index === this.props.resource.index) return;
this.checkTabs();
}
checkTabs() {
const { resource: { payload, response, body }, isResult } = this.props;
const _tabs = TABS.filter(t => {
if (t.key == REQUEST && !!payload) {
return true
}
if (t.key == RESPONSE && !!response) {
return true;
}
if (t.key == TIMINGS && isResult) {
return true;
}
return false;
})
this.setState({ tabs: _tabs, activeTab: _tabs.length > 0 ? _tabs[0].key : null })
}
render() {
const {
resource: {
method,
url,
duration
},
nextClick,
prevClick,
first = false,
last = false,
} = this.props;
const { activeTab, tabs } = this.state;
return (
<div className="px-4 pb-16">
<h5 className="mb-2">{ 'URL'}</h5>
<div className={ cn(stl.url, 'color-gray-darkest')}>{ url }</div>
<div className="flex items-center mt-4">
<div className="w-4/12">
<div className="font-medium mb-2">Method</div>
<div>{method}</div>
</div>
<div className="w-4/12">
<div className="font-medium mb-2">Duration</div>
<div>{parseInt(duration)} ms</div>
</div>
</div>
<div className="mt-6">
<div>
<Tabs
tabs={ tabs }
active={ activeTab }
onClick={ this.onTabClick }
border={ true }
/>
<div style={{ height: 'calc(100vh - 314px)', overflowY: 'auto' }}>
{ this.renderActiveTab(activeTab) }
</div>
</div>
<div className="flex justify-between absolute bottom-0 left-0 right-0 p-3 border-t bg-white">
<Button primary plain onClick={prevClick} disabled={first}>
Prev
</Button>
<Button primary plain onClick={nextClick} disabled={last}>
Next
</Button>
</div>
</div>
</div>
);
}
}