Some stuff (#83)

This commit is contained in:
Gregory Schier 2017-02-13 00:12:02 -08:00 committed by GitHub
parent f6f148185d
commit ab6d4e03d6
12 changed files with 261 additions and 185 deletions

View File

@ -122,20 +122,29 @@ export function recursiveRender (obj, context) {
return newObj; return newObj;
} }
export async function getRenderedRequest (request, environmentId) { export async function getRenderContext (request, environmentId, ancestors = null) {
const ancestors = await db.withAncestors(request); if (!ancestors) {
const workspace = ancestors.find(doc => doc.type === models.workspace.type); ancestors = await db.withAncestors(request);
}
const workspace = ancestors.find(doc => doc.type === models.workspace.type);
const rootEnvironment = await models.environment.getOrCreateForWorkspace(workspace); const rootEnvironment = await models.environment.getOrCreateForWorkspace(workspace);
const subEnvironment = await models.environment.getById(environmentId); const subEnvironment = await models.environment.getById(environmentId);
const cookieJar = await models.cookieJar.getOrCreateForWorkspace(workspace);
// Generate the context we need to render // Generate the context we need to render
const renderContext = buildRenderContext( return buildRenderContext(
ancestors, ancestors,
rootEnvironment, rootEnvironment,
subEnvironment subEnvironment
); );
}
export async function getRenderedRequest (request, environmentId) {
const ancestors = await db.withAncestors(request);
const workspace = ancestors.find(doc => doc.type === models.workspace.type);
const cookieJar = await models.cookieJar.getOrCreateForWorkspace(workspace);
const renderContext = await getRenderContext(request, environmentId, ancestors);
// Render all request properties // Render all request properties
const renderedRequest = recursiveRender(request, renderContext); const renderedRequest = recursiveRender(request, renderContext);

View File

@ -1,7 +1,7 @@
{ {
"private": true, "private": true,
"name": "insomnia", "name": "insomnia",
"version": "4.2.12", "version": "4.2.13",
"productName": "Insomnia", "productName": "Insomnia",
"longName": "Insomnia REST Client", "longName": "Insomnia REST Client",
"description": "A simple and beautiful REST API client", "description": "A simple and beautiful REST API client",

View File

@ -72,6 +72,7 @@ class RequestPane extends PureComponent {
editorLineWrapping, editorLineWrapping,
handleSend, handleSend,
handleSendAndDownload, handleSendAndDownload,
handleRender,
forceRefreshCounter, forceRefreshCounter,
useBulkHeaderEditor, useBulkHeaderEditor,
handleGenerateCode, handleGenerateCode,
@ -190,6 +191,7 @@ class RequestPane extends PureComponent {
<TabPanel className="editor-wrapper"> <TabPanel className="editor-wrapper">
<BodyEditor <BodyEditor
handleUpdateRequestMimeType={updateRequestMimeType} handleUpdateRequestMimeType={updateRequestMimeType}
handleRender={handleRender}
key={uniqueKey} key={uniqueKey}
request={request} request={request}
onChange={updateRequestBody} onChange={updateRequestBody}
@ -285,6 +287,7 @@ RequestPane.propTypes = {
handleSendAndDownload: PropTypes.func.isRequired, handleSendAndDownload: PropTypes.func.isRequired,
handleCreateRequest: PropTypes.func.isRequired, handleCreateRequest: PropTypes.func.isRequired,
handleGenerateCode: PropTypes.func.isRequired, handleGenerateCode: PropTypes.func.isRequired,
handleRender: PropTypes.func.isRequired,
updateRequestUrl: PropTypes.func.isRequired, updateRequestUrl: PropTypes.func.isRequired,
updateRequestMethod: PropTypes.func.isRequired, updateRequestMethod: PropTypes.func.isRequired,
updateRequestBody: PropTypes.func.isRequired, updateRequestBody: PropTypes.func.isRequired,

View File

@ -168,6 +168,7 @@ class Wrapper extends Component {
handleStartDragPane, handleStartDragPane,
handleStartDragSidebar, handleStartDragSidebar,
handleSetSidebarFilter, handleSetSidebarFilter,
handleRender,
handleGenerateCodeForActiveRequest, handleGenerateCodeForActiveRequest,
handleGenerateCode, handleGenerateCode,
isLoading, isLoading,
@ -244,6 +245,7 @@ class Wrapper extends Component {
handleCreateRequest={handleCreateRequestForWorkspace} handleCreateRequest={handleCreateRequestForWorkspace}
handleGenerateCode={handleGenerateCodeForActiveRequest} handleGenerateCode={handleGenerateCodeForActiveRequest}
handleImport={this._handleImport} handleImport={this._handleImport}
handleRender={handleRender}
updateRequestBody={this._handleUpdateRequestBody} updateRequestBody={this._handleUpdateRequestBody}
updateRequestUrl={this._handleUpdateRequestUrl} updateRequestUrl={this._handleUpdateRequestUrl}
updateRequestMethod={this._handleUpdateRequestMethod} updateRequestMethod={this._handleUpdateRequestMethod}
@ -353,6 +355,7 @@ Wrapper.propTypes = {
handleSetRequestPaneRef: PropTypes.func.isRequired, handleSetRequestPaneRef: PropTypes.func.isRequired,
handleSetResponsePaneRef: PropTypes.func.isRequired, handleSetResponsePaneRef: PropTypes.func.isRequired,
handleSetResponsePreviewMode: PropTypes.func.isRequired, handleSetResponsePreviewMode: PropTypes.func.isRequired,
handleRender: PropTypes.func.isRequired,
handleSetResponseFilter: PropTypes.func.isRequired, handleSetResponseFilter: PropTypes.func.isRequired,
handleSetActiveResponse: PropTypes.func.isRequired, handleSetActiveResponse: PropTypes.func.isRequired,
handleSetSidebarRef: PropTypes.func.isRequired, handleSetSidebarRef: PropTypes.func.isRequired,

View File

@ -132,23 +132,41 @@ class Editor extends Component {
const {value} = this.props; const {value} = this.props;
// Add overlay to editor to make all links clickable // Add overlay to editor to make all links clickable
CodeMirror.defineMode('clickable', (config, parserConfig) => { CodeMirror.defineMode('master', (config, parserConfig) => {
const baseMode = CodeMirror.getMode(config, parserConfig.baseMode || 'text/plain'); const baseMode = CodeMirror.getMode(config, parserConfig.baseMode || 'text/plain');
// Only add the click mode if we have links to click // Only add the click mode if we have links to click
if (!this.props.onClickLink) { const highlightLinks = !!this.props.onClickLink;
return baseMode; const highlightNunjucks = !this.props.readOnly;
}
const regexUrl = /^(https?:\/\/)?([\da-z.\-]+)\.([a-z.]{2,6})([\/\w .\-]*)*\/?/;
const regexVariable = /^{{[ |a-zA-Z0-9_\-+,'"\\()\[\]]+}}/;
const regexTag = /^{%[ |a-zA-Z0-9_\-+,'"\\()\[\]]+%}/;
const regexComment = /^{#[^#]+#}/;
const overlay = { const overlay = {
token: function (stream, state) { token: function (stream, state) {
// console.log('state', state); if (highlightLinks && stream.match(regexUrl, true)) {
if (stream.match(/^(https?:\/\/)?([\da-z.\-]+)\.([a-z.]{2,6})([\/\w .\-]*)*\/?/, true)) {
return 'clickable'; return 'clickable';
} }
while (stream.next() != null && !stream.match("http", false)) { if (highlightNunjucks && stream.match(regexVariable, true)) {
// Do nothing return 'variable-3';
}
if (highlightNunjucks && stream.match(regexTag, true)) {
return 'variable-3';
}
if (highlightNunjucks && stream.match(regexComment, true)) {
return 'comment';
}
while (stream.next() != null) {
if (stream.match(regexUrl, false)) break;
if (stream.match(regexVariable, false)) break;
if (stream.match(regexTag, false)) break;
if (stream.match(regexComment, false)) break;
} }
return null; return null;
@ -271,7 +289,7 @@ class Editor extends Component {
readOnly, readOnly,
placeholder: this.props.placeholder || '', placeholder: this.props.placeholder || '',
mode: { mode: {
name: 'clickable', name: 'master',
baseMode: normalizedMode, baseMode: normalizedMode,
}, },
lineWrapping: this.props.lineWrapping, lineWrapping: this.props.lineWrapping,
@ -424,16 +442,12 @@ class Editor extends Component {
} }
render () { render () {
const {readOnly, fontSize, lightTheme, mode, filter} = this.props; const {readOnly, fontSize, mode, filter} = this.props;
const classes = classnames( const classes = classnames(
'editor', 'editor',
this.props.className, this.props.className,
{ {'editor--readonly': readOnly}
'editor--readonly': readOnly,
'editor--light-theme': !!lightTheme,
'editor--dark-theme': !lightTheme
}
); );
const toolbarChildren = []; const toolbarChildren = [];
@ -500,6 +514,7 @@ Editor.propTypes = {
onChange: PropTypes.func, onChange: PropTypes.func,
onFocusChange: PropTypes.func, onFocusChange: PropTypes.func,
onClickLink: PropTypes.func, onClickLink: PropTypes.func,
render: PropTypes.func,
keyMap: PropTypes.string, keyMap: PropTypes.string,
mode: PropTypes.string, mode: PropTypes.string,
placeholder: PropTypes.string, placeholder: PropTypes.string,
@ -509,8 +524,8 @@ Editor.propTypes = {
autoPrettify: PropTypes.bool, autoPrettify: PropTypes.bool,
manualPrettify: PropTypes.bool, manualPrettify: PropTypes.bool,
className: PropTypes.any, className: PropTypes.any,
lightTheme: PropTypes.bool,
updateFilter: PropTypes.func, updateFilter: PropTypes.func,
readOnly: PropTypes.bool,
filter: PropTypes.string filter: PropTypes.string
}; };

View File

@ -7,7 +7,7 @@ import {getContentTypeFromHeaders, CONTENT_TYPE_FORM_URLENCODED, CONTENT_TYPE_FO
import {newBodyRaw, newBodyFormUrlEncoded, newBodyForm, newBodyFile} from '../../../../models/request'; import {newBodyRaw, newBodyFormUrlEncoded, newBodyForm, newBodyFile} from '../../../../models/request';
class BodyEditor extends PureComponent { class BodyEditor extends PureComponent {
_handleRawChange = (rawValue) => { _handleRawChange = rawValue => {
const {onChange, request} = this.props; const {onChange, request} = this.props;
const contentType = getContentTypeFromHeaders(request.headers); const contentType = getContentTypeFromHeaders(request.headers);
@ -16,26 +16,26 @@ class BodyEditor extends PureComponent {
onChange(newBody); onChange(newBody);
}; };
_handleFormUrlEncodedChange = (parameters) => { _handleFormUrlEncodedChange = parameters => {
const {onChange} = this.props; const {onChange} = this.props;
const newBody = newBodyFormUrlEncoded(parameters); const newBody = newBodyFormUrlEncoded(parameters);
onChange(newBody); onChange(newBody);
}; };
_handleFormChange = (parameters) => { _handleFormChange = parameters => {
const {onChange} = this.props; const {onChange} = this.props;
const newBody = newBodyForm(parameters); const newBody = newBodyForm(parameters);
onChange(newBody); onChange(newBody);
}; };
_handleFileChange = (path) => { _handleFileChange = path => {
const {onChange} = this.props; const {onChange} = this.props;
const newBody = newBodyFile(path); const newBody = newBodyFile(path);
onChange(newBody); onChange(newBody);
}; };
render () { render () {
const {keyMap, fontSize, lineWrapping, request} = this.props; const {keyMap, fontSize, lineWrapping, request, handleRender} = this.props;
const fileName = request.body.fileName; const fileName = request.body.fileName;
const mimeType = request.body.mimeType; const mimeType = request.body.mimeType;
const isBodyEmpty = typeof mimeType !== 'string' && !request.body.text; const isBodyEmpty = typeof mimeType !== 'string' && !request.body.text;
@ -74,6 +74,7 @@ class BodyEditor extends PureComponent {
lineWrapping={lineWrapping} lineWrapping={lineWrapping}
contentType={contentType || 'text/plain'} contentType={contentType || 'text/plain'}
content={request.body.text || ''} content={request.body.text || ''}
render={handleRender}
onChange={this._handleRawChange} onChange={this._handleRawChange}
/> />
) )
@ -81,7 +82,7 @@ class BodyEditor extends PureComponent {
return ( return (
<div className="editor pad valign-center text-center"> <div className="editor pad valign-center text-center">
<p className="pad super-faint text-sm text-center"> <p className="pad super-faint text-sm text-center">
<i className="fa fa-hand-peace-o" style={{fontSize: '8rem', opacity: 0.3}}></i> <i className="fa fa-hand-peace-o" style={{fontSize: '8rem', opacity: 0.3}}/>
<br/><br/> <br/><br/>
Select a body type from above Select a body type from above
</p> </p>
@ -95,6 +96,7 @@ BodyEditor.propTypes = {
// Required // Required
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
handleUpdateRequestMimeType: PropTypes.func.isRequired, handleUpdateRequestMimeType: PropTypes.func.isRequired,
handleRender: PropTypes.func.isRequired,
request: PropTypes.object.isRequired, request: PropTypes.object.isRequired,
// Optional // Optional

View File

@ -8,6 +8,7 @@ class RawEditor extends Component {
content, content,
fontSize, fontSize,
keyMap, keyMap,
render,
lineWrapping, lineWrapping,
onChange, onChange,
className className
@ -20,6 +21,7 @@ class RawEditor extends Component {
keyMap={keyMap} keyMap={keyMap}
value={content} value={content}
className={className} className={className}
render={render}
onChange={onChange} onChange={onChange}
mode={contentType} mode={contentType}
lineWrapping={lineWrapping} lineWrapping={lineWrapping}
@ -34,11 +36,12 @@ RawEditor.propTypes = {
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
content: PropTypes.string.isRequired, content: PropTypes.string.isRequired,
contentType: PropTypes.string.isRequired, contentType: PropTypes.string.isRequired,
fontSize: PropTypes.number.isRequired,
keyMap: PropTypes.string.isRequired,
lineWrapping: PropTypes.bool.isRequired,
// Optional // Optional
fontSize: PropTypes.number, render: PropTypes.func,
keyMap: PropTypes.string,
lineWrapping: PropTypes.bool
}; };
export default RawEditor; export default RawEditor;

View File

@ -2,6 +2,7 @@ import React, {Component, PropTypes} from 'react';
import {Tab, Tabs, TabList, TabPanel} from 'react-tabs'; import {Tab, Tabs, TabList, TabPanel} from 'react-tabs';
import {shell} from 'electron'; import {shell} from 'electron';
import Modal from '../base/Modal'; import Modal from '../base/Modal';
import Button from '../base/Button';
import ModalBody from '../base/ModalBody'; import ModalBody from '../base/ModalBody';
import ModalHeader from '../base/ModalHeader'; import ModalHeader from '../base/ModalHeader';
import SettingsShortcuts from '../settings/SettingsShortcuts'; import SettingsShortcuts from '../settings/SettingsShortcuts';
@ -23,6 +24,29 @@ class SettingsModal extends Component {
this.state = {} this.state = {}
} }
_setModalRef = m => this.modal = m;
_trackTab = name => trackEvent('Setting', `Tab ${name}`);
_handleTabSelect = currentTabIndex => this.setState({currentTabIndex});
_handleUpdateSetting = (key, value) => {
models.settings.update(this.props.settings, {[key]: value});
trackEvent('Setting', 'Change', key)
};
_handleExportAllToFile = () => {
this.props.handleExportAllToFile();
this.modal.hide()
};
_handleExportWorkspace = () => {
this.props.handleExportWorkspaceToFile();
this.modal.hide()
};
_handleImport = () => {
this.props.handleImportFile();
this.modal.hide()
};
_handleChangeTheme = (theme, track = true) => { _handleChangeTheme = (theme, track = true) => {
document.body.setAttribute('theme', theme); document.body.setAttribute('theme', theme);
models.settings.update(this.props.settings, {theme}); models.settings.update(this.props.settings, {theme});
@ -52,23 +76,13 @@ class SettingsModal extends Component {
this.modal.toggle(); this.modal.toggle();
} }
_handleTabSelect (currentTabIndex) {
this.setState({currentTabIndex});
}
render () { render () {
const { const {settings} = this.props;
settings,
handleExportAllToFile,
handleExportWorkspaceToFile,
handleImportFile,
} = this.props;
const {currentTabIndex} = this.state; const {currentTabIndex} = this.state;
const email = session.isLoggedIn() ? session.getEmail() : null; const email = session.isLoggedIn() ? session.getEmail() : null;
return ( return (
<Modal ref={m => this.modal = m} tall={true} {...this.props}> <Modal ref={this._setModalRef} tall={true} {...this.props}>
<ModalHeader> <ModalHeader>
{getAppName()} Preferences {getAppName()} Preferences
<span className="faint txt-sm"> <span className="faint txt-sm">
@ -78,57 +92,45 @@ class SettingsModal extends Component {
</span> </span>
</ModalHeader> </ModalHeader>
<ModalBody noScroll={true}> <ModalBody noScroll={true}>
<Tabs onSelect={i => this._handleTabSelect(i)} selectedIndex={currentTabIndex}> <Tabs onSelect={this._handleTabSelect} selectedIndex={currentTabIndex}>
<TabList> <TabList>
<Tab selected={this._currentTabIndex === 0}> <Tab selected={this._currentTabIndex === 0}>
<button onClick={e => trackEvent('Setting', 'Tab General')}> <Button value="General" onClick={this._trackTab}>
General General
</button> </Button>
</Tab> </Tab>
<Tab selected={this._currentTabIndex === 1}> <Tab selected={this._currentTabIndex === 1}>
<button onClick={e => trackEvent('Setting', 'Tab Import/Export')}> <Button value="Import/Export" onClick={this._trackTab}>
Import/Export Import/Export
</button> </Button>
</Tab> </Tab>
<Tab selected={this._currentTabIndex === 2}> <Tab selected={this._currentTabIndex === 2}>
<button onClick={e => trackEvent('Setting', 'Tab Themes')}> <Button value="Themes" onClick={this._trackTab}>
Themes Themes
</button> </Button>
</Tab> </Tab>
<Tab selected={this._currentTabIndex === 3}> <Tab selected={this._currentTabIndex === 3}>
<button onClick={e => trackEvent('Setting', 'Tab Shortcuts')}> <Button value="shortcuts" onClick={this._trackTab}>
Shortcuts Shortcuts
</button> </Button>
</Tab> </Tab>
<Tab selected={this._currentTabIndex === 5}> <Tab selected={this._currentTabIndex === 4}>
<button onClick={e => trackEvent('Setting', 'Tab About')}> <Button value="About" onClick={this._trackTab}>
About About
</button> </Button>
</Tab> </Tab>
</TabList> </TabList>
<TabPanel className="pad scrollable"> <TabPanel className="pad scrollable">
<SettingsGeneral <SettingsGeneral
settings={settings} settings={settings}
updateSetting={(key, value) => { updateSetting={this._handleUpdateSetting}
models.settings.update(settings, {[key]: value});
trackEvent('Setting', 'Change', key)
}}
/> />
</TabPanel> </TabPanel>
<TabPanel className="pad scrollable"> <TabPanel className="pad scrollable">
<SettingsImportExport <SettingsImportExport
handleExportAll={() => { handleExportAll={this._handleExportAllToFile}
handleExportAllToFile(); handleExportWorkspace={this._handleExportWorkspace}
this.modal.hide() handleImport={this._handleImport}
}}
handleExportWorkspace={() => {
handleExportWorkspaceToFile();
this.modal.hide()
}}
handleImport={() => {
handleImportFile();
this.modal.hide()
}}
/> />
</TabPanel> </TabPanel>
<TabPanel className="pad scrollable"> <TabPanel className="pad scrollable">

View File

@ -1,52 +1,71 @@
import React, {PropTypes} from 'react'; import React, {Component, PropTypes} from 'react';
const SettingsGeneral = ({settings, updateSetting}) => ( class SettingsGeneral extends Component {
_handleUpdateSetting = e => {
let value = e.target.type === 'checkbox' ? e.target.checked : e.target.value;
if (e.target.type === 'number') {
value = parseInt(value, 10);
}
this.props.updateSetting(e.target.name, value);
};
render () {
const {settings} = this.props;
return (
<div> <div>
<div className="form-control form-control--thin"> <div className="form-control form-control--thin">
<label className="inline-block">Follow redirects automatically <label className="inline-block">Follow redirects automatically
<input type="checkbox" <input type="checkbox"
name="followRedirects"
checked={settings.followRedirects} checked={settings.followRedirects}
onChange={e => updateSetting('followRedirects', e.target.checked)}/> onChange={this._handleUpdateSetting}/>
</label> </label>
</div> </div>
<div className="form-control form-control--thin"> <div className="form-control form-control--thin">
<label className="inline-block">Validate SSL Certificates <label className="inline-block">Validate SSL Certificates
<input type="checkbox" <input type="checkbox"
name="validateSSL"
checked={settings.validateSSL} checked={settings.validateSSL}
onChange={e => updateSetting('validateSSL', e.target.checked)}/> onChange={this._handleUpdateSetting}/>
</label> </label>
</div> </div>
<div className="form-control form-control--thin"> <div className="form-control form-control--thin">
<label className="inline-block">Show passwords in plain-text <label className="inline-block">Show passwords in plain-text
<input type="checkbox" <input type="checkbox"
name="showPasswords"
checked={settings.showPasswords} checked={settings.showPasswords}
onChange={e => updateSetting('showPasswords', e.target.checked)}/> onChange={this._handleUpdateSetting}/>
</label> </label>
</div> </div>
<div className="form-control form-control--thin"> <div className="form-control form-control--thin">
<label className="inline-block">Use bulk header editor by default <label className="inline-block">Use bulk header editor by default
<input type="checkbox" <input type="checkbox"
name="useBulkHeaderEditor"
checked={settings.useBulkHeaderEditor} checked={settings.useBulkHeaderEditor}
onChange={e => updateSetting('useBulkHeaderEditor', e.target.checked)}/> onChange={this._handleUpdateSetting}/>
</label> </label>
</div> </div>
<div className="form-control form-control--thin"> <div className="form-control form-control--thin">
<label className="inline-block">Always use vertical layout <label className="inline-block">Always use vertical layout
<input type="checkbox" <input type="checkbox"
name="forceVerticalLayout"
checked={settings.forceVerticalLayout} checked={settings.forceVerticalLayout}
onChange={e => updateSetting('forceVerticalLayout', e.target.checked)}/> onChange={this._handleUpdateSetting}/>
</label> </label>
</div> </div>
<div className="form-control form-control--thin"> <div className="form-control form-control--thin">
<label className="inline-block">Wrap Long Lines <label className="inline-block">Wrap Long Lines
<input type="checkbox" <input type="checkbox"
name="editorLineWrapping"
checked={settings.editorLineWrapping} checked={settings.editorLineWrapping}
onChange={e => updateSetting('editorLineWrapping', e.target.checked)}/> onChange={this._handleUpdateSetting}/>
</label> </label>
</div> </div>
@ -54,10 +73,11 @@ const SettingsGeneral = ({settings, updateSetting}) => (
<div className="form-control form-control--outlined pad-top-sm"> <div className="form-control form-control--outlined pad-top-sm">
<label>Text Editor Font Size (px) <label>Text Editor Font Size (px)
<input type="number" <input type="number"
name="editorFontSize"
min={8} min={8}
max={20} max={20}
defaultValue={settings.editorFontSize} defaultValue={settings.editorFontSize}
onChange={e => updateSetting('editorFontSize', parseInt(e.target.value, 10))}/> onChange={this._handleUpdateSetting}/>
</label> </label>
</div> </div>
@ -65,7 +85,8 @@ const SettingsGeneral = ({settings, updateSetting}) => (
<label> <label>
Text Editor Key Map Text Editor Key Map
<select defaultValue={settings.editorKeyMap} <select defaultValue={settings.editorKeyMap}
onChange={e => updateSetting('editorKeyMap', e.target.value)}> name="editorKeyMap"
onChange={this._handleUpdateSetting}>
<option value="default">Default</option> <option value="default">Default</option>
<option value="vim">Vim</option> <option value="vim">Vim</option>
<option value="emacs">Emacs</option> <option value="emacs">Emacs</option>
@ -78,32 +99,37 @@ const SettingsGeneral = ({settings, updateSetting}) => (
<div className="form-control form-control--outlined"> <div className="form-control form-control--outlined">
<label>Request Timeout (ms) (0 for no timeout) <label>Request Timeout (ms) (0 for no timeout)
<input type="number" <input type="number"
name="timeout"
min={0} min={0}
defaultValue={settings.timeout} defaultValue={settings.timeout}
onChange={e => updateSetting('timeout', parseInt(e.target.value, 10))}/> onChange={this._handleUpdateSetting}/>
</label> </label>
</div> </div>
<div className="form-row"> <div className="form-row">
<div className="form-control form-control--outlined"> <div className="form-control form-control--outlined">
<label>HTTP Proxy <label>HTTP Proxy
<input type="text" <input type="text"
name="httpProxy"
placeholder="localhost:8005" placeholder="localhost:8005"
defaultValue={settings.httpProxy} defaultValue={settings.httpProxy}
onChange={e => updateSetting('httpProxy', e.target.value)}/> onChange={this._handleUpdateSetting}/>
</label> </label>
</div> </div>
<div className="form-control form-control--outlined"> <div className="form-control form-control--outlined">
<label>HTTPS Proxy <label>HTTPS Proxy
<input placeholder="localhost:8005" <input placeholder="localhost:8005"
name="httpsProxy"
type="text" type="text"
defaultValue={settings.httpsProxy} defaultValue={settings.httpsProxy}
onChange={e => updateSetting('httpsProxy', e.target.value)}/> onChange={this._handleUpdateSetting}/>
</label> </label>
</div> </div>
</div> </div>
<br/> <br/>
</div> </div>
); )
}
}
SettingsGeneral.propTypes = { SettingsGeneral.propTypes = {
settings: PropTypes.object.isRequired, settings: PropTypes.object.isRequired,

View File

@ -28,6 +28,7 @@ import * as network from '../../common/network';
import {debounce} from '../../common/misc'; import {debounce} from '../../common/misc';
import * as mime from 'mime-types'; import * as mime from 'mime-types';
import * as path from 'path'; import * as path from 'path';
import * as render from '../../common/render';
const KEY_ENTER = 13; const KEY_ENTER = 13;
const KEY_COMMA = 188; const KEY_COMMA = 188;
@ -143,7 +144,7 @@ class App extends Component {
models.requestGroup.create({parentId, name}) models.requestGroup.create({parentId, name})
}; };
_requestCreate = async (parentId) => { _requestCreate = async parentId => {
const request = await showModal(RequestCreateModal, {parentId}); const request = await showModal(RequestCreateModal, {parentId});
this._handleSetActiveRequest(request._id) this._handleSetActiveRequest(request._id)
}; };
@ -158,7 +159,14 @@ class App extends Component {
} }
const newRequest = await models.request.duplicate(request); const newRequest = await models.request.duplicate(request);
this._handleSetActiveRequest(newRequest._id) await this._handleSetActiveRequest(newRequest._id)
};
_handleRenderText = async text => {
const {activeEnvironment, activeRequest} = this.props;
const environmentId = activeEnvironment ? activeEnvironment._id : null;
const context = await render.getRenderContext(activeRequest, environmentId);
return render.render(text, context);
}; };
_handleGenerateCodeForActiveRequest = () => { _handleGenerateCodeForActiveRequest = () => {
@ -206,12 +214,13 @@ class App extends Component {
this._savePaneWidth(paneWidth); this._savePaneWidth(paneWidth);
}; };
_handleSetActiveRequest = activeRequestId => { _handleSetActiveRequest = async activeRequestId => {
this._updateActiveWorkspaceMeta({activeRequestId}); await this._updateActiveWorkspaceMeta({activeRequestId});
}; };
_handleSetActiveEnvironment = activeEnvironmentId => { _handleSetActiveEnvironment = async activeEnvironmentId => {
this._updateActiveWorkspaceMeta({activeEnvironmentId}); await this._updateActiveWorkspaceMeta({activeEnvironmentId});
this._wrapper.forceRequestPaneRefresh();
}; };
_saveSidebarWidth = debounce(sidebarWidth => this._updateActiveWorkspaceMeta({sidebarWidth})); _saveSidebarWidth = debounce(sidebarWidth => this._updateActiveWorkspaceMeta({sidebarWidth}));
@ -220,12 +229,12 @@ class App extends Component {
this._saveSidebarWidth(sidebarWidth); this._saveSidebarWidth(sidebarWidth);
}; };
_handleSetSidebarHidden = sidebarHidden => { _handleSetSidebarHidden = async sidebarHidden => {
this._updateActiveWorkspaceMeta({sidebarHidden}); await this._updateActiveWorkspaceMeta({sidebarHidden});
}; };
_handleSetSidebarFilter = sidebarFilter => { _handleSetSidebarFilter = async sidebarFilter => {
this._updateActiveWorkspaceMeta({sidebarFilter}); await this._updateActiveWorkspaceMeta({sidebarFilter});
}; };
_handleSetRequestGroupCollapsed = (requestGroupId, collapsed) => { _handleSetRequestGroupCollapsed = (requestGroupId, collapsed) => {
@ -431,7 +440,7 @@ class App extends Component {
trackEvent('General', 'Launched', getAppVersion(), {nonInteraction: true}); trackEvent('General', 'Launched', getAppVersion(), {nonInteraction: true});
} }
db.onChange(changes => { db.onChange(async changes => {
for (const change of changes) { for (const change of changes) {
const [event, doc, fromSync] = change; const [event, doc, fromSync] = change;
const {activeRequest} = this.props; const {activeRequest} = this.props;
@ -499,6 +508,7 @@ class App extends Component {
handleStartDragPane={this._startDragPane} handleStartDragPane={this._startDragPane}
handleResetDragPane={this._resetDragPane} handleResetDragPane={this._resetDragPane}
handleCreateRequest={this._requestCreate} handleCreateRequest={this._requestCreate}
handleRender={this._handleRenderText}
handleDuplicateRequest={this._requestDuplicate} handleDuplicateRequest={this._requestDuplicate}
handleDuplicateRequestGroup={this._requestGroupDuplicate} handleDuplicateRequestGroup={this._requestGroupDuplicate}
handleCreateRequestGroup={this._requestGroupCreate} handleCreateRequestGroup={this._requestGroupCreate}

View File

@ -176,7 +176,6 @@
box-sizing: border-box; box-sizing: border-box;
} }
span.cm-comment,
span.cm-meta, span.cm-meta,
span.cm-qualifier { span.cm-qualifier {
color: var(--color-font); color: var(--color-font);
@ -215,7 +214,7 @@
} }
span.cm-variable-3 { span.cm-variable-3 {
color: var(--color-info); color: var(--color-surprise);
} }
span.cm-def { span.cm-def {
@ -238,6 +237,10 @@
color: var(--color-surprise); color: var(--color-surprise);
} }
span.cm-comment {
color: var(--hl);
}
span.cm-error { span.cm-error {
background: var(--color-danger); background: var(--color-danger);
color: var(--color-font-danger); color: var(--color-font-danger);

View File

@ -45,7 +45,7 @@ body {
--color-notice: #ead950; --color-notice: #ead950;
--color-warning: #ff9a1f; --color-warning: #ff9a1f;
--color-danger: #ff5d4b; --color-danger: #ff5d4b;
--color-surprise: #a590ff; --color-surprise: #a896ff;
--color-info: #22c2f0; --color-info: #22c2f0;
.tag { .tag {