response pane class->fc (#4982)

* first pass

* remove old

* remove delete drill prop

* remove two more drills

* two more drills

* remove one drill

* constify

* two more drills

* remove preview mode get/set drills

* undrill exportAsHAR

* undrill debug response download

* undrill prettify option

* save ipc for next pass

* fix delete response

* make delete function uniform

* address feedback comments
This commit is contained in:
Jack Kavanagh 2022-07-22 11:52:00 +02:00 committed by GitHub
parent 4d82d4ddb7
commit ac166158c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 263 additions and 388 deletions

View File

@ -1,6 +1,12 @@
import fs from 'fs';
import React, { FC, useCallback } from 'react';
import { useSelector } from 'react-redux';
import { getPreviewModeName, PREVIEW_MODES, PreviewMode } from '../../../common/constants';
import { exportHarCurrentRequest } from '../../../common/har';
import * as models from '../../../models';
import { isRequest } from '../../../models/request';
import { selectActiveRequest, selectActiveResponse, selectResponsePreviewMode } from '../../redux/selectors';
import { Dropdown } from '../base/dropdown/dropdown';
import { DropdownButton } from '../base/dropdown/dropdown-button';
import { DropdownDivider } from '../base/dropdown/dropdown-divider';
@ -8,39 +14,85 @@ import { DropdownItem } from '../base/dropdown/dropdown-item';
interface Props {
download: (pretty: boolean) => any;
fullDownload: (pretty: boolean) => any;
exportAsHAR: () => void;
copyToClipboard: () => any;
updatePreviewMode: Function;
previewMode: PreviewMode;
showPrettifyOption?: boolean;
}
export const PreviewModeDropdown: FC<Props> = ({
fullDownload,
previewMode,
showPrettifyOption,
download,
copyToClipboard,
exportAsHAR,
updatePreviewMode,
}) => {
const request = useSelector(selectActiveRequest);
const previewMode = useSelector(selectResponsePreviewMode);
const response = useSelector(selectActiveResponse);
const handleClick = async (previewMode: string) => {
await updatePreviewMode(previewMode);
const handleClick = async (previewMode: PreviewMode) => {
if (!request || !isRequest(request)) {
return;
}
return models.requestMeta.updateOrCreateByParentId(request._id, { previewMode });
};
const handleDownloadPrettify = useCallback(() => {
download(true);
}, [download]);
const handleDownloadPrettify = useCallback(() => download(true), [download]);
const handleDownloadNormal = useCallback(() => {
download(false);
}, [download]);
const handleDownloadNormal = useCallback(() => download(false), [download]);
const handleCopyRawResponse = useCallback(() => {
copyToClipboard();
}, [copyToClipboard]);
const exportAsHAR = useCallback(async () => {
if (!response || !request || !isRequest(request)) {
console.warn('Nothing to download');
return;
}
const data = await exportHarCurrentRequest(request, response);
const har = JSON.stringify(data, null, '\t');
const { filePath } = await window.dialog.showSaveDialog({
title: 'Export As HAR',
buttonLabel: 'Save',
defaultPath: `${request.name.replace(/ +/g, '_')}-${Date.now()}.har`,
});
if (!filePath) {
return;
}
const to = fs.createWriteStream(filePath);
to.on('error', err => {
console.warn('Failed to export har', err);
});
to.end(har);
}, [request, response]);
const exportDebugFile = useCallback(async () => {
if (!response || !request) {
console.warn('Nothing to download');
return;
}
const timeline = models.response.getTimeline(response);
const headers = timeline
.filter(v => v.name === 'HeaderIn')
.map(v => v.value)
.join('');
const { canceled, filePath } = await window.dialog.showSaveDialog({
title: 'Save Full Response',
buttonLabel: 'Save',
defaultPath: `${request.name.replace(/ +/g, '_')}-${Date.now()}.txt`,
});
if (canceled) {
return;
}
const readStream = models.response.getBodyStream(response);
if (readStream && filePath) {
const to = fs.createWriteStream(filePath);
to.write(headers);
readStream.pipe(to);
to.on('error', err => {
console.warn('Failed to save full response', err);
});
}
}, [request, response]);
const shouldPrettifyOption = response.contentType.includes('json');
return <Dropdown beside>
<DropdownButton className="tall">
{getPreviewModeName(previewMode)}
@ -52,7 +104,7 @@ export const PreviewModeDropdown: FC<Props> = ({
{getPreviewModeName(mode, true)}
</DropdownItem>)}
<DropdownDivider>Actions</DropdownDivider>
<DropdownItem onClick={handleCopyRawResponse}>
<DropdownItem onClick={copyToClipboard}>
<i className="fa fa-copy" />
Copy raw response
</DropdownItem>
@ -60,11 +112,11 @@ export const PreviewModeDropdown: FC<Props> = ({
<i className="fa fa-save" />
Export raw response
</DropdownItem>
{showPrettifyOption && <DropdownItem onClick={handleDownloadPrettify}>
{shouldPrettifyOption && <DropdownItem onClick={handleDownloadPrettify}>
<i className="fa fa-save" />
Export prettified response
</DropdownItem>}
<DropdownItem onClick={fullDownload}>
<DropdownItem onClick={exportDebugFile}>
<i className="fa fa-bug" />
Export HTTP debug
</DropdownItem>

View File

@ -1,12 +1,13 @@
import { differenceInHours, differenceInMinutes, isThisWeek, isToday } from 'date-fns';
import React, { FC, Fragment, useCallback, useRef } from 'react';
import { useSelector } from 'react-redux';
import { hotKeyRefs } from '../../../common/hotkeys';
import { executeHotKey } from '../../../common/hotkeys-listener';
import { decompressObject } from '../../../common/misc';
import type { Environment } from '../../../models/environment';
import type { RequestVersion } from '../../../models/request-version';
import * as models from '../../../models/index';
import type { Response } from '../../../models/response';
import { selectActiveEnvironment, selectActiveRequest, selectActiveRequestResponses, selectRequestVersions } from '../../redux/selectors';
import { type DropdownHandle, Dropdown } from '../base/dropdown/dropdown';
import { DropdownButton } from '../base/dropdown/dropdown-button';
import { DropdownDivider } from '../base/dropdown/dropdown-divider';
@ -20,30 +21,23 @@ import { URLTag } from '../tags/url-tag';
import { TimeFromNow } from '../time-from-now';
interface Props {
activeEnvironment?: Environment | null;
activeResponse: Response;
className?: string;
handleDeleteResponse: Function;
handleDeleteResponses: Function;
handleSetActiveResponse: Function;
requestId: string;
requestVersions: RequestVersion[];
responses: Response[];
}
export const ResponseHistoryDropdown: FC<Props> = ({
activeEnvironment,
activeResponse,
className,
handleDeleteResponse,
handleDeleteResponses,
handleSetActiveResponse,
requestId,
requestVersions,
responses,
}) => {
const dropdownRef = useRef<DropdownHandle>(null);
const activeEnvironment = useSelector(selectActiveEnvironment);
const responses = useSelector(selectActiveRequestResponses);
const activeRequest = useSelector(selectActiveRequest);
const requestVersions = useSelector(selectRequestVersions);
const now = new Date();
const categories: Record<string, Response[]> = {
minutes: [],
@ -53,6 +47,22 @@ export const ResponseHistoryDropdown: FC<Props> = ({
other: [],
};
const handleDeleteResponses = useCallback(async () => {
const environmentId = activeEnvironment ? activeEnvironment._id : null;
await models.response.removeForRequest(requestId, environmentId);
if (activeRequest && activeRequest._id === requestId) {
await handleSetActiveResponse(requestId, null);
}
}, [activeEnvironment, activeRequest, handleSetActiveResponse, requestId]);
const handleDeleteResponse = useCallback(async () => {
if (activeResponse) {
await models.response.remove(activeResponse);
}
handleSetActiveResponse(null);
}, [activeResponse, handleSetActiveResponse]);
responses.forEach(response => {
const responseTime = new Date(response.created);
@ -148,7 +158,7 @@ export const ResponseHistoryDropdown: FC<Props> = ({
<i className="fa fa-trash-o" />
Delete Current Response
</DropdownItem>
<DropdownItem buttonClass={PromptButton} addIcon onClick={() => handleDeleteResponses(requestId, activeEnvironment ? activeEnvironment._id : null)}>
<DropdownItem buttonClass={PromptButton} addIcon onClick={handleDeleteResponses}>
<i className="fa fa-trash-o" />
Clear History
</DropdownItem>

View File

@ -1,25 +1,18 @@
import { autoBindMethodsForReact } from 'class-autobind-decorator';
import classnames from 'classnames';
import { clipboard } from 'electron';
import fs from 'fs';
import { json as jsonPrettify } from 'insomnia-prettify';
import { extension as mimeExtension } from 'mime-types';
import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import React, { FC, useCallback, useRef } from 'react';
import { useSelector } from 'react-redux';
import { Tab, TabList, TabPanel, Tabs } from 'react-tabs';
import { AUTOBIND_CFG, PREVIEW_MODE_SOURCE, PreviewMode } from '../../../common/constants';
import { exportHarCurrentRequest } from '../../../common/har';
import { PREVIEW_MODE_SOURCE } from '../../../common/constants';
import { getSetCookieHeaders } from '../../../common/misc';
import * as models from '../../../models';
import type { Environment } from '../../../models/environment';
import type { Request } from '../../../models/request';
import type { RequestVersion } from '../../../models/request-version';
import type { Response } from '../../../models/response';
import type { UnitTestResult } from '../../../models/unit-test-result';
import { cancelRequestById } from '../../../network/network';
import { RootState } from '../../redux/modules';
import { selectHotKeyRegistry } from '../../redux/selectors';
import { selectActiveResponse, selectLoadStartTime, selectResponseFilter, selectResponseFilterHistory, selectResponsePreviewMode, selectSettings } from '../../redux/selectors';
import { Button } from '../base/button';
import { PreviewModeDropdown } from '../dropdowns/preview-mode-dropdown';
import { ResponseHistoryDropdown } from '../dropdowns/response-history-dropdown';
@ -32,63 +25,47 @@ import { TimeTag } from '../tags/time-tag';
import { ResponseCookiesViewer } from '../viewers/response-cookies-viewer';
import { ResponseHeadersViewer } from '../viewers/response-headers-viewer';
import { ResponseTimelineViewer } from '../viewers/response-timeline-viewer';
import { ResponseViewer } from '../viewers/response-viewer';
import { ResponseViewer } from '../viewers/response-viewer';
import { BlankPane } from './blank-pane';
import { Pane, paneBodyClasses, PaneHeader } from './pane';
import { PlaceholderResponsePane } from './placeholder-response-pane';
interface OwnProps {
handleSetFilter: (filter: string) => void;
handleSetPreviewMode: Function;
interface Props {
handleSetActiveResponse: Function;
handleDeleteResponses: Function;
handleDeleteResponse: Function;
handleSetFilter: (filter: string) => void;
handleShowRequestSettings: Function;
previewMode: PreviewMode;
filter: string;
filterHistory: string[];
disableHtmlPreviewJs: boolean;
editorFontSize: number;
loadStartTime: number;
responses: Response[];
disableResponsePreviewLinks: boolean;
requestVersions: RequestVersion[];
request?: Request | null;
response?: Response | null;
environment?: Environment | null;
unitTestResult?: UnitTestResult | null;
}
export const ResponsePane: FC<Props> = ({
handleSetActiveResponse,
handleSetFilter,
handleShowRequestSettings,
request,
}) => {
const response = useSelector(selectActiveResponse);
const filterHistory = useSelector(selectResponseFilterHistory);
const filter = useSelector(selectResponseFilter);
const settings = useSelector(selectSettings);
const loadStartTime = useSelector(selectLoadStartTime);
const previewMode = useSelector(selectResponsePreviewMode);
const mapStateToProps = (state: RootState) => ({
hotKeyRegistry: selectHotKeyRegistry(state),
});
type ReduxProps = ReturnType<typeof mapStateToProps>;
type Props = OwnProps & ReduxProps;
@autoBindMethodsForReact(AUTOBIND_CFG)
class UnconnectedResponsePane extends PureComponent<Props> {
_responseViewer: ResponseViewer | null = null;
_setResponseViewerRef(responseViewer: ResponseViewer) {
this._responseViewer = responseViewer;
}
_handleGetResponseBody(): Buffer | null {
if (!this.props.response) {
const responseViewerRef = useRef<ResponseViewer>(null);
const handleGetResponseBody = useCallback(() => {
if (!response) {
return null;
}
return models.response.getBodyBuffer(response);
}, [response]);
const handleCopyResponseToClipboard = useCallback(async () => {
const bodyBuffer = handleGetResponseBody();
if (bodyBuffer) {
clipboard.writeText(bodyBuffer.toString('utf8'));
}
}, [handleGetResponseBody]);
return models.response.getBodyBuffer(this.props.response);
}
async _handleDownloadResponseBody(prettify: boolean) {
const { response, request } = this.props;
const handleDownloadResponseBody = useCallback(async (prettify: boolean) => {
if (!response || !request) {
// Should never happen
console.warn('No response to download');
console.warn('Nothing to download');
return;
}
@ -107,12 +84,11 @@ class UnconnectedResponsePane extends PureComponent<Props> {
const readStream = models.response.getBodyStream(response);
const dataBuffers: any[] = [];
if (readStream) {
if (readStream && outputPath) {
readStream.on('data', data => {
dataBuffers.push(data);
});
readStream.on('end', () => {
// @ts-expect-error -- TSCONVERSION
const to = fs.createWriteStream(outputPath);
const finalBuffer = Buffer.concat(dataBuffers);
to.on('error', err => {
@ -132,256 +108,136 @@ class UnconnectedResponsePane extends PureComponent<Props> {
to.end();
});
}
}
}, [request, response]);
async _handleDownloadFullResponseBody() {
const { response, request } = this.props;
if (!response || !request) {
// Should never happen
console.warn('No response to download');
return;
}
const timeline = models.response.getTimeline(response);
const headers = timeline
.filter(v => v.name === 'HeaderIn')
.map(v => v.value)
.join('');
const { canceled, filePath } = await window.dialog.showSaveDialog({
title: 'Save Full Response',
buttonLabel: 'Save',
defaultPath: `${request.name.replace(/ +/g, '_')}-${Date.now()}.txt`,
});
if (canceled) {
return;
}
const readStream = models.response.getBodyStream(response);
if (readStream) {
// @ts-expect-error -- TSCONVERSION
const to = fs.createWriteStream(filePath);
to.write(headers);
readStream.pipe(to);
to.on('error', err => {
console.warn('Failed to save full response', err);
});
}
}
async _handleCopyResponseToClipboard() {
if (!this.props.response) {
return;
}
const bodyBuffer = models.response.getBodyBuffer(this.props.response);
if (bodyBuffer) {
clipboard.writeText(bodyBuffer.toString('utf8'));
}
}
async _handleExportAsHAR() {
const { response, request } = this.props;
if (!response) {
// Should never happen
console.warn('No response to download');
return;
}
if (!request) {
// Should never happen
console.warn('No request to download');
return;
}
const data = await exportHarCurrentRequest(request, response);
const har = JSON.stringify(data, null, '\t');
const { filePath } = await window.dialog.showSaveDialog({
title: 'Export As HAR',
buttonLabel: 'Save',
defaultPath: `${request.name.replace(/ +/g, '_')}-${Date.now()}.har`,
});
if (!filePath) {
return;
}
const to = fs.createWriteStream(filePath);
to.on('error', err => {
console.warn('Failed to export har', err);
});
to.end(har);
}
_handleTabSelect(index: number, lastIndex: number) {
if (this._responseViewer != null && index === 0 && index !== lastIndex) {
const handleTabSelect = (index: number, lastIndex: number) => {
if (responseViewerRef.current != null && index === 0 && index !== lastIndex) {
// Fix for CodeMirror editor not updating its content.
// Refresh must be called when the editor is visible,
// so use nextTick to give time for it to be visible.
process.nextTick(() => {
// @ts-expect-error -- TSCONVERSION
this._responseViewer.refresh();
responseViewerRef.current?.refresh();
});
}
};
if (!request) {
return <BlankPane type="response" />;
}
render() {
const {
disableHtmlPreviewJs,
editorFontSize,
environment,
filter,
disableResponsePreviewLinks,
filterHistory,
handleDeleteResponse,
handleDeleteResponses,
handleSetActiveResponse,
handleSetFilter,
handleSetPreviewMode,
handleShowRequestSettings,
loadStartTime,
previewMode,
request,
requestVersions,
response,
responses,
} = this.props;
if (!request) {
return <BlankPane type="response" />;
}
if (!response) {
return (
<PlaceholderResponsePane>
<ResponseTimer
handleCancel={() => cancelRequestById(request._id)}
loadStartTime={loadStartTime}
/>
</PlaceholderResponsePane>
);
}
const cookieHeaders = getSetCookieHeaders(response.headers);
if (!response) {
return (
<Pane type="response">
{!response ? null : (
<PaneHeader className="row-spaced">
<div className="no-wrap scrollable scrollable--no-bars pad-left">
<StatusTag statusCode={response.statusCode} statusMessage={response.statusMessage} />
<TimeTag milliseconds={response.elapsedTime} />
<SizeTag bytesRead={response.bytesRead} bytesContent={response.bytesContent} />
</div>
<ResponseHistoryDropdown
activeResponse={response}
activeEnvironment={environment}
responses={responses}
requestVersions={requestVersions}
requestId={request._id}
handleSetActiveResponse={handleSetActiveResponse}
handleDeleteResponses={handleDeleteResponses}
handleDeleteResponse={handleDeleteResponse}
className="tall pane__header__right"
/>
</PaneHeader>
)}
<Tabs
className={classnames(paneBodyClasses, 'react-tabs')}
onSelect={this._handleTabSelect}
forceRenderTabPanel
>
<TabList>
<Tab tabIndex="-1">
<PreviewModeDropdown
download={this._handleDownloadResponseBody}
fullDownload={this._handleDownloadFullResponseBody}
exportAsHAR={this._handleExportAsHAR}
previewMode={previewMode}
updatePreviewMode={handleSetPreviewMode}
showPrettifyOption={response.contentType.includes('json')}
copyToClipboard={this._handleCopyResponseToClipboard}
/>
</Tab>
<Tab tabIndex="-1">
<Button>
Header{' '}
{response.headers.length > 0 && (
<span className="bubble">{response.headers.length}</span>
)}
</Button>
</Tab>
<Tab tabIndex="-1">
<Button>
Cookie{' '}
{cookieHeaders.length ? (
<span className="bubble">{cookieHeaders.length}</span>
) : null}
</Button>
</Tab>
<Tab tabIndex="-1">
<Button>Timeline</Button>
</Tab>
</TabList>
<TabPanel className="react-tabs__tab-panel">
<ResponseViewer
ref={this._setResponseViewerRef}
bytes={Math.max(response.bytesContent, response.bytesRead)}
contentType={response.contentType || ''}
disableHtmlPreviewJs={disableHtmlPreviewJs}
disablePreviewLinks={disableResponsePreviewLinks}
download={this._handleDownloadResponseBody}
editorFontSize={editorFontSize}
error={response.error}
filter={filter}
filterHistory={filterHistory}
getBody={this._handleGetResponseBody}
previewMode={response.error ? PREVIEW_MODE_SOURCE : previewMode}
responseId={response._id}
updateFilter={response.error ? undefined : handleSetFilter}
url={response.url}
/>
</TabPanel>
<TabPanel className="react-tabs__tab-panel scrollable-container">
<div className="scrollable pad">
<ErrorBoundary key={response._id} errorClassName="font-error pad text-center">
<ResponseHeadersViewer headers={response.headers} />
</ErrorBoundary>
</div>
</TabPanel>
<TabPanel className="react-tabs__tab-panel scrollable-container">
<div className="scrollable pad">
<ErrorBoundary key={response._id} errorClassName="font-error pad text-center">
<ResponseCookiesViewer
handleShowRequestSettings={handleShowRequestSettings}
cookiesSent={response.settingSendCookies}
cookiesStored={response.settingStoreCookies}
headers={cookieHeaders}
/>
</ErrorBoundary>
</div>
</TabPanel>
<TabPanel className="react-tabs__tab-panel">
<ErrorBoundary key={response._id} errorClassName="font-error pad text-center">
<ResponseTimelineViewer
response={response}
/>
</ErrorBoundary>
</TabPanel>
</Tabs>
<ErrorBoundary errorClassName="font-error pad text-center">
<ResponseTimer
handleCancel={() => cancelRequestById(request._id)}
loadStartTime={loadStartTime}
/>
</ErrorBoundary>
</Pane>
<PlaceholderResponsePane>
<ResponseTimer
handleCancel={() => cancelRequestById(request._id)}
loadStartTime={loadStartTime}
/>
</PlaceholderResponsePane>
);
}
}
export const ResponsePane = connect(mapStateToProps)(UnconnectedResponsePane);
const cookieHeaders = getSetCookieHeaders(response.headers);
return (
<Pane type="response">
{!response ? null : (
<PaneHeader className="row-spaced">
<div className="no-wrap scrollable scrollable--no-bars pad-left">
<StatusTag statusCode={response.statusCode} statusMessage={response.statusMessage} />
<TimeTag milliseconds={response.elapsedTime} />
<SizeTag bytesRead={response.bytesRead} bytesContent={response.bytesContent} />
</div>
<ResponseHistoryDropdown
activeResponse={response}
requestId={request._id}
handleSetActiveResponse={handleSetActiveResponse}
className="tall pane__header__right"
/>
</PaneHeader>
)}
<Tabs
className={classnames(paneBodyClasses, 'react-tabs')}
onSelect={handleTabSelect}
forceRenderTabPanel
>
<TabList>
<Tab tabIndex="-1">
<PreviewModeDropdown
download={handleDownloadResponseBody}
copyToClipboard={handleCopyResponseToClipboard}
/>
</Tab>
<Tab tabIndex="-1">
<Button>
Header{' '}
{response.headers.length > 0 && (
<span className="bubble">{response.headers.length}</span>
)}
</Button>
</Tab>
<Tab tabIndex="-1">
<Button>
Cookie{' '}
{cookieHeaders.length ? (
<span className="bubble">{cookieHeaders.length}</span>
) : null}
</Button>
</Tab>
<Tab tabIndex="-1">
<Button>Timeline</Button>
</Tab>
</TabList>
<TabPanel className="react-tabs__tab-panel">
<ResponseViewer
ref={responseViewerRef}
bytes={Math.max(response.bytesContent, response.bytesRead)}
contentType={response.contentType || ''}
disableHtmlPreviewJs={settings.disableHtmlPreviewJs}
disablePreviewLinks={settings.disableResponsePreviewLinks}
download={handleDownloadResponseBody}
editorFontSize={settings.editorFontSize}
error={response.error}
filter={filter}
filterHistory={filterHistory}
getBody={handleGetResponseBody}
previewMode={response.error ? PREVIEW_MODE_SOURCE : previewMode}
responseId={response._id}
updateFilter={response.error ? undefined : handleSetFilter}
url={response.url}
/>
</TabPanel>
<TabPanel className="react-tabs__tab-panel scrollable-container">
<div className="scrollable pad">
<ErrorBoundary key={response._id} errorClassName="font-error pad text-center">
<ResponseHeadersViewer headers={response.headers} />
</ErrorBoundary>
</div>
</TabPanel>
<TabPanel className="react-tabs__tab-panel scrollable-container">
<div className="scrollable pad">
<ErrorBoundary key={response._id} errorClassName="font-error pad text-center">
<ResponseCookiesViewer
handleShowRequestSettings={handleShowRequestSettings}
cookiesSent={response.settingSendCookies}
cookiesStored={response.settingStoreCookies}
headers={cookieHeaders}
/>
</ErrorBoundary>
</div>
</TabPanel>
<TabPanel className="react-tabs__tab-panel">
<ErrorBoundary key={response._id} errorClassName="font-error pad text-center">
<ResponseTimelineViewer
response={response}
/>
</ErrorBoundary>
</TabPanel>
</Tabs>
<ErrorBoundary errorClassName="font-error pad text-center">
<ResponseTimer
handleCancel={() => cancelRequestById(request._id)}
loadStartTime={loadStartTime}
/>
</ErrorBoundary>
</Pane>
);
};

View File

@ -7,7 +7,14 @@ import { isRemoteProject } from '../../models/project';
import { Request, RequestAuthentication, RequestBody, RequestHeader, RequestParameter } from '../../models/request';
import { Settings } from '../../models/settings';
import { isCollection, isDesign } from '../../models/workspace';
import { selectActiveEnvironment, selectActiveRequest, selectActiveRequestResponses, selectActiveResponse, selectActiveUnitTestResult, selectActiveWorkspace, selectEnvironments, selectLoadStartTime, selectRequestVersions, selectResponseDownloadPath, selectResponseFilter, selectResponseFilterHistory, selectResponsePreviewMode, selectSettings } from '../redux/selectors';
import {
selectActiveEnvironment,
selectActiveRequest,
selectActiveWorkspace,
selectEnvironments,
selectResponseDownloadPath,
selectSettings,
} from '../redux/selectors';
import { selectSidebarChildren, selectSidebarFilter } from '../redux/sidebar-selectors';
import { EnvironmentsDropdown } from './dropdowns/environments-dropdown';
import { SyncDropdown } from './dropdowns/sync-dropdown';
@ -28,15 +35,12 @@ interface Props {
gitSyncDropdown: ReactNode;
handleActivityChange: HandleActivityChange;
handleChangeEnvironment: Function;
handleDeleteResponse: Function;
handleDeleteResponses: Function;
handleForceUpdateRequest: (r: Request, patch: Partial<Request>) => Promise<Request>;
handleForceUpdateRequestHeaders: (r: Request, headers: RequestHeader[]) => Promise<Request>;
handleImport: Function;
handleSendAndDownloadRequestWithActiveEnvironment: (filepath?: string) => Promise<void>;
handleSendRequestWithActiveEnvironment: () => void;
handleSetActiveResponse: Function;
handleSetPreviewMode: Function;
handleSetResponseFilter: (filter: string) => void;
handleShowRequestSettingsModal: Function;
handleSidebarSort: (sortOrder: SortOrder) => void;
@ -55,15 +59,12 @@ export const WrapperDebug: FC<Props> = ({
gitSyncDropdown,
handleActivityChange,
handleChangeEnvironment,
handleDeleteResponse,
handleDeleteResponses,
handleForceUpdateRequest,
handleForceUpdateRequestHeaders,
handleImport,
handleSendAndDownloadRequestWithActiveEnvironment,
handleSendRequestWithActiveEnvironment,
handleSetActiveResponse,
handleSetPreviewMode,
handleSetResponseFilter,
handleShowRequestSettingsModal,
handleSidebarSort,
@ -100,17 +101,11 @@ export const WrapperDebug: FC<Props> = ({
const activeEnvironment = useSelector(selectActiveEnvironment);
const activeRequest = useSelector(selectActiveRequest);
const activeRequestResponses = useSelector(selectActiveRequestResponses);
const activeResponse = useSelector(selectActiveResponse);
const activeUnitTestResult = useSelector(selectActiveUnitTestResult);
const activeWorkspace = useSelector(selectActiveWorkspace);
const environments = useSelector(selectEnvironments);
const loadStartTime = useSelector(selectLoadStartTime);
const requestVersions = useSelector(selectRequestVersions);
const responseDownloadPath = useSelector(selectResponseDownloadPath);
const responseFilter = useSelector(selectResponseFilter);
const responseFilterHistory = useSelector(selectResponseFilterHistory);
const responsePreviewMode = useSelector(selectResponsePreviewMode);
const settings = useSelector(selectSettings);
const sidebarChildren = useSelector(selectSidebarChildren);
const sidebarFilter = useSelector(selectSidebarFilter);
@ -215,25 +210,10 @@ export const WrapperDebug: FC<Props> = ({
/>
:
<ResponsePane
disableHtmlPreviewJs={settings.disableHtmlPreviewJs}
disableResponsePreviewLinks={settings.disableResponsePreviewLinks}
editorFontSize={settings.editorFontSize}
environment={activeEnvironment}
filter={responseFilter}
filterHistory={responseFilterHistory}
handleDeleteResponse={handleDeleteResponse}
handleDeleteResponses={handleDeleteResponses}
handleSetActiveResponse={handleSetActiveResponse}
handleSetFilter={handleSetResponseFilter}
handleSetPreviewMode={handleSetPreviewMode}
handleShowRequestSettings={handleShowRequestSettingsModal}
loadStartTime={loadStartTime}
previewMode={responsePreviewMode}
request={activeRequest}
requestVersions={requestVersions}
response={activeResponse}
responses={activeRequestResponses}
unitTestResult={activeUnitTestResult}
/>}
</ErrorBoundary>}
/>

View File

@ -27,7 +27,6 @@ import {
RequestParameter,
} from '../../models/request';
import { RequestGroup } from '../../models/request-group';
import type { Response } from '../../models/response';
import { GitVCS } from '../../sync/git/git-vcs';
import { VCS } from '../../sync/vcs/vcs';
import { CookieModifyModal } from '../components/modals/cookie-modify-modal';
@ -350,26 +349,6 @@ export class Wrapper extends PureComponent<WrapperProps, State> {
showModal(RequestSettingsModal, { request: this.props.activeRequest });
}
async _handleDeleteResponses(requestId: string, environmentId: string | null) {
const { handleSetActiveResponse, activeRequest } = this.props;
await models.response.removeForRequest(requestId, environmentId);
if (activeRequest && activeRequest._id === requestId) {
await handleSetActiveResponse(requestId, null);
}
}
async _handleDeleteResponse(response: Response) {
if (response) {
await models.response.remove(response);
}
// Also unset active response it's the one we're deleting
if (this.props.activeResponse?._id === response._id) {
this._handleSetActiveResponse(null);
}
}
async _handleRemoveActiveWorkspace() {
const { activeWorkspace, handleSetActiveActivity } = this.props;
@ -654,8 +633,6 @@ export class Wrapper extends PureComponent<WrapperProps, State> {
gitSyncDropdown={gitSyncDropdown}
handleActivityChange={this._handleWorkspaceActivityChange}
handleChangeEnvironment={this._handleChangeEnvironment}
handleDeleteResponse={this._handleDeleteResponse}
handleDeleteResponses={this._handleDeleteResponses}
handleForceUpdateRequest={this._handleForceUpdateRequest}
handleForceUpdateRequestHeaders={this._handleForceUpdateRequestHeaders}
handleImport={this._handleImport}