// @flow import type {Request} from '../../models/request'; import type {Workspace} from '../../models/workspace'; import type {OAuth2Token} from '../../models/o-auth-2-token'; import React from 'react'; import autobind from 'autobind-decorator'; import {Tab, TabList, TabPanel, Tabs} from 'react-tabs'; import ContentTypeDropdown from './dropdowns/content-type-dropdown'; import AuthDropdown from './dropdowns/auth-dropdown'; import KeyValueEditor from './key-value-editor/editor'; import RequestHeadersEditor from './editors/request-headers-editor'; import RenderedQueryString from './rendered-query-string'; import BodyEditor from './editors/body/body-editor'; import AuthWrapper from './editors/auth/auth-wrapper'; import RequestUrlBar from './request-url-bar.js'; import {DEBOUNCE_MILLIS, getAuthTypeName, getContentTypeName} from '../../common/constants'; import {trackEvent} from '../../analytics/index'; import * as querystring from '../../common/querystring'; import * as db from '../../common/database'; import * as models from '../../models'; import Hotkey from './hotkey'; import {showModal} from './modals/index'; import RequestSettingsModal from './modals/request-settings-modal'; import MarkdownPreview from './markdown-preview'; import type {Settings} from '../../models/settings'; import * as hotkeys from '../../common/hotkeys'; @autobind class RequestPane extends React.PureComponent { props: { // Functions forceUpdateRequest: Function, handleSend: Function, handleSendAndDownload: Function, handleCreateRequest: Function, handleGenerateCode: Function, handleRender: Function, handleGetRenderContext: Function, updateRequestUrl: Function, updateRequestMethod: Function, updateRequestBody: Function, updateRequestParameters: Function, updateRequestAuthentication: Function, updateRequestHeaders: Function, updateRequestMimeType: Function, updateSettingsShowPasswords: Function, updateSettingsUseBulkHeaderEditor: Function, handleImport: Function, handleImportFile: Function, // Other useBulkHeaderEditor: boolean, showPasswords: boolean, editorFontSize: number, editorIndentSize: number, editorKeyMap: string, editorLineWrapping: boolean, workspace: Workspace, settings: Settings, environmentId: string, forceRefreshCounter: number, // Optional request: ?Request, oAuth2Token: ?OAuth2Token }; _handleUpdateRequestUrlTimeout: number; _handleEditDescriptionAdd () { this._handleEditDescription(true); } _handleEditDescription (addDescription: boolean) { showModal(RequestSettingsModal, { request: this.props.request, forceEditMode: addDescription }); } async _autocompleteUrls () { const docs = await db.withDescendants( this.props.workspace, models.request.type ); const requestId = this.props.request ? this.props.request._id : 'n/a'; const urls = docs.filter(d => ( d.type === models.request.type && // Only requests d._id !== requestId && // Not current request (d.url || '') // Only ones with non-empty URLs )).map(r => r.url || ''); return Array.from(new Set(urls)); } _handleUpdateSettingsUseBulkHeaderEditor () { const {useBulkHeaderEditor, updateSettingsUseBulkHeaderEditor} = this.props; updateSettingsUseBulkHeaderEditor(!useBulkHeaderEditor); trackEvent('Headers', 'Toggle Bulk', !useBulkHeaderEditor ? 'On' : 'Off'); } _handleImportFile () { this.props.handleImportFile(); trackEvent('Request Pane', 'CTA', 'Import'); } _handleCreateRequest () { this.props.handleCreateRequest(this.props.request); trackEvent('Request Pane', 'CTA', 'New Request'); } _handleUpdateRequestUrl (url: string) { clearTimeout(this._handleUpdateRequestUrlTimeout); this._handleUpdateRequestUrlTimeout = setTimeout(() => { this.props.updateRequestUrl(url); }, DEBOUNCE_MILLIS); } _handleImportQueryFromUrl () { const {request} = this.props; if (!request) { console.warn('Tried to import query when no request active'); return; } let query; try { query = querystring.extractFromUrl(request.url); } catch (e) { console.warn('Failed to parse url to import querystring'); return; } // Remove the search string (?foo=bar&...) from the Url const url = request.url.replace(query, ''); const parameters = [ ...request.parameters, ...querystring.deconstructToParams(query) ]; // Only update if url changed if (url !== request.url) { this.props.forceUpdateRequest({url, parameters}); } } _trackQueryToggle (pair: {disabled: boolean}) { trackEvent('Query', 'Toggle', pair.disabled ? 'Disable' : 'Enable'); } _trackQueryCreate () { trackEvent('Query', 'Create'); } _trackQueryDelete () { trackEvent('Query', 'Delete'); } render () { const { editorFontSize, editorIndentSize, editorKeyMap, editorLineWrapping, forceRefreshCounter, handleGenerateCode, handleGetRenderContext, handleImport, handleRender, handleSend, handleSendAndDownload, oAuth2Token, request, workspace, environmentId, settings, showPasswords, updateRequestAuthentication, updateRequestBody, updateRequestHeaders, updateRequestMethod, updateRequestMimeType, updateRequestParameters, updateSettingsShowPasswords, useBulkHeaderEditor } = this.props; if (!request) { return ( New Request Switch Requests Edit Environments Import from File New Request ); } let numBodyParams = 0; if (request.body && request.body.params) { numBodyParams = request.body.params.filter(p => !p.disabled).length; } const numParameters = request.parameters.filter(p => !p.disabled).length; const numHeaders = request.headers.filter(h => !h.disabled).length; const urlHasQueryParameters = request.url.indexOf('?') >= 0; const uniqueKey = `${forceRefreshCounter}::${request._id}`; return ( {typeof request.body.mimeType === 'string' ? getContentTypeName(request.body.mimeType) : 'Body'} {numBodyParams ? {numBodyParams} : null} {getAuthTypeName(request.authentication.type) || 'Auth'} Query {numParameters > 0 && {numParameters}} Header {numHeaders > 0 && {numHeaders}} Docs {request.description && ( )} Url Preview Import from Url {useBulkHeaderEditor ? 'Regular Edit' : 'Bulk Edit'} {request.description ? ( Edit ) : ( Add Description )} ); } } export default RequestPane;
Add Description