insomnia/app/ui/components/wrapper.js

579 lines
22 KiB
JavaScript
Raw Normal View History

import React, {PropTypes, PureComponent} from 'react';
import autobind from 'autobind-decorator';
import classnames from 'classnames';
import {registerModal, showModal} from './modals/index';
import AlertModal from './modals/alert-modal';
import ChangelogModal from './modals/changelog-modal';
import CookiesModal from './modals/cookies-modal';
import EnvironmentEditModal from './modals/environment-edit-modal';
import GenerateCodeModal from './modals/generate-code-modal';
import LoginModal from './modals/login-modal';
import PaymentNotificationModal from './modals/payment-notification-modal';
import NunjucksModal from './modals/nunjucks-modal';
import PromptModal from './modals/prompt-modal';
import RequestCreateModal from './modals/request-create-modal';
import RequestPane from './request-pane';
import RequestSwitcherModal from './modals/request-switcher-modal';
import SetupSyncModal from './modals/setup-sync-modal';
import SettingsModal from './modals/settings-modal';
import FilterHelpModal from './modals/filter-help-modal';
import ResponsePane from './response-pane';
import RequestSettingsModal from './modals/request-settings-modal';
import RequestRenderErrorModal from './modals/request-render-error-modal';
import Sidebar from './sidebar/sidebar';
import WorkspaceEnvironmentsEditModal from './modals/workspace-environments-edit-modal';
import WorkspaceSettingsModal from './modals/workspace-settings-modal';
import WorkspaceShareSettingsModal from './modals/workspace-share-settings-modal';
import CodePromptModal from './modals/code-prompt-modal';
import * as models from '../../models/index';
import {updateMimeType} from '../../models/request';
2016-11-26 00:37:59 +00:00
import {trackEvent} from '../../analytics/index';
import * as importers from 'insomnia-importers';
2016-11-26 00:37:59 +00:00
const rUpdate = models.request.update;
const sUpdate = models.settings.update;
@autobind
class Wrapper extends PureComponent {
constructor (props) {
super(props);
this.state = {
forceRefreshKey: Date.now()
};
}
2016-11-26 00:37:59 +00:00
// Request updaters
async _handleForceUpdateRequest (patch) {
const newRequest = await rUpdate(this.props.activeRequest, patch);
// Give it a second for the app to render first. If we don't wait, it will refresh
// on the old request and won't catch the newest one.
window.setTimeout(this._forceRequestPaneRefresh, 100);
return newRequest;
}
_handleUpdateRequestBody (body) {
rUpdate(this.props.activeRequest, {body});
}
2016-11-28 07:12:17 +00:00
_handleUpdateRequestMethod (method) {
rUpdate(this.props.activeRequest, {method});
}
_handleUpdateRequestParameters (parameters) {
rUpdate(this.props.activeRequest, {parameters});
}
_handleUpdateRequestAuthentication (authentication) {
rUpdate(this.props.activeRequest, {authentication});
}
_handleUpdateRequestHeaders (headers) {
rUpdate(this.props.activeRequest, {headers});
}
_handleUpdateRequestUrl (url) {
rUpdate(this.props.activeRequest, {url});
}
2016-11-26 00:37:59 +00:00
// Special request updaters
async _handleUpdateRequestMimeType (mimeType) {
await updateMimeType(this.props.activeRequest, mimeType);
// Force it to update, because other editor components (header editor)
// needs to change. Need to wait a delay so the next render can finish
setTimeout(this._forceRequestPaneRefresh, 300);
}
_handleStartDragSidebar (e) {
e.preventDefault();
this.props.handleStartDragSidebar();
}
async _handleImport (text) {
2016-11-26 00:37:59 +00:00
// Allow user to paste any import file into the url. If it results in
// only one item, it will overwrite the current request.
try {
const {data} = importers.convert(text);
const {resources} = data;
2016-11-26 00:37:59 +00:00
const r = resources[0];
if (r && r._type === 'request') {
trackEvent('Import', 'Url Bar');
2016-11-25 23:09:17 +00:00
2016-11-26 00:37:59 +00:00
// Only pull fields that we want to update
return this._handleForceUpdateRequest({
2016-11-26 00:37:59 +00:00
url: r.url,
method: r.method,
headers: r.headers,
body: r.body,
authentication: r.authentication,
parameters: r.parameters
2016-11-26 00:37:59 +00:00
});
}
} catch (e) {
// Import failed, that's alright
}
return null;
}
2016-11-26 00:37:59 +00:00
// Settings updaters
_handleUpdateSettingsShowPasswords (showPasswords) {
sUpdate(this.props.settings, {showPasswords});
}
_handleUpdateSettingsUseBulkHeaderEditor (useBulkHeaderEditor) {
sUpdate(this.props.settings, {useBulkHeaderEditor});
}
2016-11-26 00:37:59 +00:00
// Other Helpers
_handleImportFile () {
this.props.handleImportFileToWorkspace(this.props.activeWorkspace._id);
}
_handleImportUri (uri) {
this.props.handleImportUriToWorkspace(this.props.activeWorkspace._id, uri);
}
_handleExportWorkspaceToFile () {
this.props.handleExportFile(this.props.activeWorkspace._id);
}
_handleSetActiveResponse (responseId) {
this.props.handleSetActiveResponse(this.props.activeRequest._id, responseId);
}
2016-12-07 17:57:01 +00:00
_handleShowEnvironmentsModal () {
showModal(WorkspaceEnvironmentsEditModal, this.props.activeWorkspace);
}
2016-11-26 00:37:59 +00:00
_handleShowCookiesModal () {
showModal(CookiesModal, this.props.activeWorkspace);
}
_handleShowRequestSettingsModal () {
showModal(RequestSettingsModal, {request: this.props.activeRequest});
}
_handleDeleteResponses () {
models.response.removeForRequest(this.props.activeRequest._id);
this._handleSetActiveResponse(null);
}
2017-06-12 21:48:17 +00:00
async _handleDeleteResponse (responseId) {
let response;
if (responseId) {
response = await models.response.getById(responseId);
} else {
const {activeRequest} = this.props;
const requestId = activeRequest ? activeRequest._id : 'n/a';
response = await models.response.getLatestForRequestId(requestId);
}
if (response) {
await models.response.remove(response);
}
// Also unset active response it's the one we're deleting
if (this.props.activeResponseId === response._id) {
this._handleSetActiveResponse(null);
}
}
async _handleRemoveActiveWorkspace () {
const {workspaces, activeWorkspace} = this.props;
if (workspaces.length <= 1) {
showModal(AlertModal, {
title: 'Deleting Last Workspace',
message: 'Since you deleted your only workspace, a new one has been created for you.'
});
models.workspace.create({name: 'Insomnia'});
trackEvent('Workspace', 'Delete', 'Last');
} else {
trackEvent('Workspace', 'Delete');
}
models.workspace.remove(activeWorkspace);
}
async _handleDuplicateActiveWorkspace () {
const {activeWorkspace} = this.props;
trackEvent('Workspace', 'Duplicate');
const newWorkspace = await models.workspace.duplicate(activeWorkspace);
await this.props.handleSetActiveWorkspace(newWorkspace._id);
}
_handleSendRequestWithActiveEnvironment () {
2016-11-26 00:37:59 +00:00
const {activeRequest, activeEnvironment, handleSendRequestWithEnvironment} = this.props;
const activeRequestId = activeRequest ? activeRequest._id : 'n/a';
const activeEnvironmentId = activeEnvironment ? activeEnvironment._id : 'n/a';
handleSendRequestWithEnvironment(activeRequestId, activeEnvironmentId);
}
2016-11-25 23:09:17 +00:00
_handleSendAndDownloadRequestWithActiveEnvironment (filename) {
const {activeRequest, activeEnvironment, handleSendAndDownloadRequestWithEnvironment} = this.props;
const activeRequestId = activeRequest ? activeRequest._id : 'n/a';
const activeEnvironmentId = activeEnvironment ? activeEnvironment._id : 'n/a';
handleSendAndDownloadRequestWithEnvironment(activeRequestId, activeEnvironmentId, filename);
}
_handleSetPreviewMode (previewMode) {
2016-11-25 23:09:17 +00:00
const activeRequest = this.props.activeRequest;
const activeRequestId = activeRequest ? activeRequest._id : 'n/a';
this.props.handleSetResponsePreviewMode(activeRequestId, previewMode);
}
2016-11-25 23:09:17 +00:00
_handleSetResponseFilter (filter) {
2016-11-25 23:09:17 +00:00
const activeRequest = this.props.activeRequest;
const activeRequestId = activeRequest ? activeRequest._id : 'n/a';
this.props.handleSetResponseFilter(activeRequestId, filter);
}
2016-11-25 23:09:17 +00:00
_forceRequestPaneRefresh () {
this.setState({forceRefreshKey: Date.now()});
}
2016-11-25 23:09:17 +00:00
render () {
const {
activeEnvironment,
activeRequest,
activeResponseId,
activeWorkspace,
2016-11-25 23:09:17 +00:00
environments,
handleActivateRequest,
2016-11-25 23:09:17 +00:00
handleCreateRequest,
handleCreateRequestForWorkspace,
handleCreateRequestGroup,
handleDuplicateRequest,
2016-11-28 07:12:17 +00:00
handleDuplicateRequestGroup,
2016-11-25 23:09:17 +00:00
handleExportFile,
2017-06-13 20:45:15 +00:00
handleMoveDoc,
handleResetDragPaneHorizontal,
handleResetDragPaneVertical,
handleResetDragSidebar,
handleSetActiveEnvironment,
handleSetActiveWorkspace,
handleSetRequestGroupCollapsed,
2016-11-25 23:09:17 +00:00
handleSetRequestPaneRef,
handleSetResponsePaneRef,
handleSetSidebarRef,
handleStartDragPaneHorizontal,
handleStartDragPaneVertical,
handleSetSidebarFilter,
handleToggleMenuBar,
2017-02-13 08:12:02 +00:00
handleRender,
handleGetRenderContext,
2017-06-07 00:07:09 +00:00
handleDuplicateWorkspace,
handleGenerateCodeForActiveRequest,
2016-11-28 07:12:17 +00:00
handleGenerateCode,
isLoading,
loadStartTime,
paneWidth,
paneHeight,
responseFilter,
responseFilterHistory,
responsePreviewMode,
oAuth2Token,
settings,
2016-11-25 23:09:17 +00:00
sidebarChildren,
sidebarFilter,
sidebarHidden,
sidebarWidth,
workspaceChildren,
workspaces
2016-11-25 23:09:17 +00:00
} = this.props;
const realSidebarWidth = sidebarHidden ? 0 : sidebarWidth;
const columns = `${realSidebarWidth}rem 0 minmax(0, ${paneWidth}fr) 0 minmax(0, ${1 - paneWidth}fr)`;
const rows = `minmax(0, ${paneHeight}fr) 0 minmax(0, ${1 - paneHeight}fr)`;
2016-11-25 23:09:17 +00:00
return (
<div id="wrapper"
className={classnames('wrapper', {'wrapper--vertical': settings.forceVerticalLayout})}
style={{gridTemplateColumns: columns, gridTemplateRows: rows}}>
2016-11-26 00:37:59 +00:00
2016-11-25 23:09:17 +00:00
<Sidebar
ref={handleSetSidebarRef}
2016-11-26 00:37:59 +00:00
showEnvironmentsModal={this._handleShowEnvironmentsModal}
showCookiesModal={this._handleShowCookiesModal}
2016-11-25 23:09:17 +00:00
handleActivateRequest={handleActivateRequest}
handleChangeFilter={handleSetSidebarFilter}
2016-11-25 23:09:17 +00:00
handleImportFile={this._handleImportFile}
handleExportFile={handleExportFile}
handleSetActiveWorkspace={handleSetActiveWorkspace}
handleDuplicateRequest={handleDuplicateRequest}
2016-11-28 07:12:17 +00:00
handleGenerateCode={handleGenerateCode}
handleDuplicateRequestGroup={handleDuplicateRequestGroup}
2016-11-25 23:09:17 +00:00
handleSetActiveEnvironment={handleSetActiveEnvironment}
2017-06-13 20:45:15 +00:00
moveDoc={handleMoveDoc}
2016-11-25 23:09:17 +00:00
handleSetRequestGroupCollapsed={handleSetRequestGroupCollapsed}
activeRequest={activeRequest}
activeEnvironment={activeEnvironment}
handleCreateRequest={handleCreateRequest}
handleCreateRequestGroup={handleCreateRequestGroup}
filter={sidebarFilter || ''}
hidden={sidebarHidden || false}
workspace={activeWorkspace}
childObjects={sidebarChildren}
2016-11-25 23:09:17 +00:00
width={sidebarWidth}
isLoading={isLoading}
workspaces={workspaces}
environments={environments}
/>
2016-11-25 23:09:17 +00:00
<div className="drag drag--sidebar">
<div onDoubleClick={handleResetDragSidebar} onMouseDown={this._handleStartDragSidebar}>
</div>
2016-11-25 23:09:17 +00:00
</div>
<RequestPane
ref={handleSetRequestPaneRef}
handleImportFile={this._handleImportFile}
request={activeRequest}
showPasswords={settings.showPasswords}
useBulkHeaderEditor={settings.useBulkHeaderEditor}
editorFontSize={settings.editorFontSize}
editorIndentSize={settings.editorIndentSize}
2017-01-24 22:18:11 +00:00
editorKeyMap={settings.editorKeyMap}
2016-11-25 23:09:17 +00:00
editorLineWrapping={settings.editorLineWrapping}
workspace={activeWorkspace}
oAuth2Token={oAuth2Token}
forceUpdateRequest={this._handleForceUpdateRequest}
2016-11-25 23:09:17 +00:00
handleCreateRequest={handleCreateRequestForWorkspace}
handleGenerateCode={handleGenerateCodeForActiveRequest}
handleImport={this._handleImport}
2017-02-13 08:12:02 +00:00
handleRender={handleRender}
handleGetRenderContext={handleGetRenderContext}
2016-11-26 00:37:59 +00:00
updateRequestBody={this._handleUpdateRequestBody}
updateRequestUrl={this._handleUpdateRequestUrl}
updateRequestMethod={this._handleUpdateRequestMethod}
updateRequestParameters={this._handleUpdateRequestParameters}
updateRequestAuthentication={this._handleUpdateRequestAuthentication}
updateRequestHeaders={this._handleUpdateRequestHeaders}
updateRequestMimeType={this._handleUpdateRequestMimeType}
updateSettingsShowPasswords={this._handleUpdateSettingsShowPasswords}
updateSettingsUseBulkHeaderEditor={this._handleUpdateSettingsUseBulkHeaderEditor}
forceRefreshCounter={this.state.forceRefreshKey}
2016-11-26 00:37:59 +00:00
handleSend={this._handleSendRequestWithActiveEnvironment}
handleSendAndDownload={this._handleSendAndDownloadRequestWithActiveEnvironment}
2016-11-25 23:09:17 +00:00
/>
<div className="drag drag--pane-horizontal">
<div
onMouseDown={handleStartDragPaneHorizontal}
onDoubleClick={handleResetDragPaneHorizontal}>
</div>
</div>
<div className="drag drag--pane-vertical">
<div
onMouseDown={handleStartDragPaneVertical}
onDoubleClick={handleResetDragPaneVertical}>
</div>
2016-11-25 23:09:17 +00:00
</div>
<ResponsePane
ref={handleSetResponsePaneRef}
request={activeRequest}
editorFontSize={settings.editorFontSize}
editorIndentSize={settings.editorIndentSize}
2017-01-24 22:18:11 +00:00
editorKeyMap={settings.editorKeyMap}
2016-11-25 23:09:17 +00:00
editorLineWrapping={settings.editorLineWrapping}
previewMode={responsePreviewMode}
activeResponseId={activeResponseId}
2016-11-25 23:09:17 +00:00
filter={responseFilter}
filterHistory={responseFilterHistory}
2016-11-25 23:09:17 +00:00
loadStartTime={loadStartTime}
showCookiesModal={this._handleShowCookiesModal}
handleShowRequestSettings={this._handleShowRequestSettingsModal}
handleSetActiveResponse={this._handleSetActiveResponse}
2016-11-25 23:09:17 +00:00
handleSetPreviewMode={this._handleSetPreviewMode}
handleDeleteResponses={this._handleDeleteResponses}
2017-06-12 21:48:17 +00:00
handleDeleteResponse={this._handleDeleteResponse}
2016-11-25 23:09:17 +00:00
handleSetFilter={this._handleSetResponseFilter}
/>
<div className="modals">
<AlertModal ref={registerModal}/>
<ChangelogModal ref={registerModal}/>
<LoginModal ref={registerModal}/>
<PromptModal ref={registerModal}/>
<RequestCreateModal ref={registerModal}/>
<PaymentNotificationModal ref={registerModal}/>
<FilterHelpModal ref={registerModal}/>
<RequestRenderErrorModal ref={registerModal}/>
<CodePromptModal
ref={registerModal}
handleRender={handleRender}
handleGetRenderContext={handleGetRenderContext}
editorFontSize={settings.editorFontSize}
editorIndentSize={settings.editorIndentSize}
editorKeyMap={settings.editorKeyMap}
editorLineWrapping={settings.editorLineWrapping}
/>
<RequestSettingsModal
ref={registerModal}
editorFontSize={settings.editorFontSize}
editorIndentSize={settings.editorIndentSize}
editorKeyMap={settings.editorKeyMap}
editorLineWrapping={settings.editorLineWrapping}
handleRender={handleRender}
handleGetRenderContext={handleGetRenderContext}
/>
<CookiesModal
ref={registerModal}
workspace={activeWorkspace}
/>
<NunjucksModal
uniqueKey={`key::${this.state.forceRefreshKey}`}
ref={registerModal}
handleRender={handleRender}
handleGetRenderContext={handleGetRenderContext}
workspace={activeWorkspace}
/>
<WorkspaceSettingsModal
ref={registerModal}
workspace={activeWorkspace}
editorFontSize={settings.editorFontSize}
editorIndentSize={settings.editorIndentSize}
editorKeyMap={settings.editorKeyMap}
editorLineWrapping={settings.editorLineWrapping}
handleRender={handleRender}
handleGetRenderContext={handleGetRenderContext}
handleRemoveWorkspace={this._handleRemoveActiveWorkspace}
2017-06-07 00:07:09 +00:00
handleDuplicateWorkspace={handleDuplicateWorkspace}
/>
<WorkspaceShareSettingsModal
ref={registerModal}
workspace={activeWorkspace}
/>
<GenerateCodeModal
ref={registerModal}
environmentId={activeEnvironment ? activeEnvironment._id : 'n/a'}
editorFontSize={settings.editorFontSize}
editorIndentSize={settings.editorIndentSize}
editorKeyMap={settings.editorKeyMap}
/>
<SettingsModal
ref={registerModal}
handleExportWorkspaceToFile={this._handleExportWorkspaceToFile}
handleExportAllToFile={handleExportFile}
handleImportFile={this._handleImportFile}
handleImportUri={this._handleImportUri}
handleToggleMenuBar={handleToggleMenuBar}
settings={settings}
/>
<RequestSwitcherModal
ref={registerModal}
workspaces={workspaces}
workspaceChildren={workspaceChildren}
workspaceId={activeWorkspace._id}
activeRequestParentId={activeRequest ? activeRequest.parentId : activeWorkspace._id}
activateRequest={handleActivateRequest}
handleSetActiveWorkspace={handleSetActiveWorkspace}
/>
<EnvironmentEditModal
ref={registerModal}
editorFontSize={settings.editorFontSize}
editorIndentSize={settings.editorIndentSize}
editorKeyMap={settings.editorKeyMap}
lineWrapping={settings.editorLineWrapping}
onChange={models.requestGroup.update}
render={handleRender}
getRenderContext={handleGetRenderContext}
/>
<SetupSyncModal
ref={registerModal}
workspace={activeWorkspace}
/>
<WorkspaceEnvironmentsEditModal
ref={registerModal}
onChange={models.workspace.update}
lineWrapping={settings.editorLineWrapping}
editorFontSize={settings.editorFontSize}
editorIndentSize={settings.editorIndentSize}
editorKeyMap={settings.editorKeyMap}
render={handleRender}
getRenderContext={handleGetRenderContext}
/>
</div>
2016-11-25 23:09:17 +00:00
</div>
);
2016-11-25 23:09:17 +00:00
}
}
Wrapper.propTypes = {
// Helper Functions
2016-11-25 23:09:17 +00:00
handleActivateRequest: PropTypes.func.isRequired,
handleSetSidebarFilter: PropTypes.func.isRequired,
handleToggleMenuBar: PropTypes.func.isRequired,
handleImportFileToWorkspace: PropTypes.func.isRequired,
handleImportUriToWorkspace: PropTypes.func.isRequired,
handleExportFile: PropTypes.func.isRequired,
handleSetActiveWorkspace: PropTypes.func.isRequired,
handleSetActiveEnvironment: PropTypes.func.isRequired,
2017-06-13 20:45:15 +00:00
handleMoveDoc: PropTypes.func.isRequired,
handleCreateRequest: PropTypes.func.isRequired,
handleDuplicateRequest: PropTypes.func.isRequired,
2016-11-28 07:12:17 +00:00
handleDuplicateRequestGroup: PropTypes.func.isRequired,
2017-06-07 00:07:09 +00:00
handleDuplicateWorkspace: PropTypes.func.isRequired,
handleCreateRequestGroup: PropTypes.func.isRequired,
handleGenerateCodeForActiveRequest: PropTypes.func.isRequired,
2016-11-28 07:12:17 +00:00
handleGenerateCode: PropTypes.func.isRequired,
2016-11-25 23:09:17 +00:00
handleCreateRequestForWorkspace: PropTypes.func.isRequired,
handleSetRequestPaneRef: PropTypes.func.isRequired,
handleSetResponsePaneRef: PropTypes.func.isRequired,
handleSetResponsePreviewMode: PropTypes.func.isRequired,
2017-02-13 08:12:02 +00:00
handleRender: PropTypes.func.isRequired,
handleGetRenderContext: PropTypes.func.isRequired,
handleSetResponseFilter: PropTypes.func.isRequired,
handleSetActiveResponse: PropTypes.func.isRequired,
handleSetSidebarRef: PropTypes.func.isRequired,
handleStartDragSidebar: PropTypes.func.isRequired,
handleResetDragSidebar: PropTypes.func.isRequired,
handleStartDragPaneHorizontal: PropTypes.func.isRequired,
handleStartDragPaneVertical: PropTypes.func.isRequired,
handleResetDragPaneHorizontal: PropTypes.func.isRequired,
handleResetDragPaneVertical: PropTypes.func.isRequired,
handleSetRequestGroupCollapsed: PropTypes.func.isRequired,
handleSendRequestWithEnvironment: PropTypes.func.isRequired,
handleSendAndDownloadRequestWithEnvironment: PropTypes.func.isRequired,
// Properties
loadStartTime: PropTypes.number.isRequired,
isLoading: PropTypes.bool.isRequired,
paneWidth: PropTypes.number.isRequired,
paneHeight: PropTypes.number.isRequired,
responsePreviewMode: PropTypes.string.isRequired,
responseFilter: PropTypes.string.isRequired,
responseFilterHistory: PropTypes.arrayOf(PropTypes.string.isRequired).isRequired,
activeResponseId: PropTypes.string.isRequired,
sidebarWidth: PropTypes.number.isRequired,
sidebarHidden: PropTypes.bool.isRequired,
sidebarFilter: PropTypes.string.isRequired,
sidebarChildren: PropTypes.arrayOf(PropTypes.object).isRequired,
settings: PropTypes.object.isRequired,
workspaces: PropTypes.arrayOf(PropTypes.object).isRequired,
2016-11-26 07:33:55 +00:00
workspaceChildren: PropTypes.arrayOf(PropTypes.object).isRequired,
environments: PropTypes.arrayOf(PropTypes.object).isRequired,
activeWorkspace: PropTypes.shape({
_id: PropTypes.string.isRequired
}).isRequired,
// Optional
oAuth2Token: PropTypes.object,
activeRequest: PropTypes.object,
activeEnvironment: PropTypes.object
};
export default Wrapper;