mirror of
https://github.com/Kong/insomnia
synced 2024-11-08 06:39:48 +00:00
Add workspace switching to quick switcher
This commit is contained in:
parent
0aec888c2e
commit
ccbbda274d
@ -36,14 +36,20 @@ class Dropdown extends Component {
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
ReactDOM.findDOMNode(this).addEventListener('keydown', e => {
|
||||
this._bodyKeydownHandler = e => {
|
||||
if (this.state.open && e.keyCode === 27) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
// Pressed escape
|
||||
this.hide();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
document.body.addEventListener('keydown', this._bodyKeydownHandler);
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
document.body.removeEventListener('keydown', this._bodyKeydownHandler);
|
||||
}
|
||||
|
||||
render () {
|
||||
@ -62,8 +68,7 @@ class Dropdown extends Component {
|
||||
return (
|
||||
<div className={classes}
|
||||
onClick={this._handleClick.bind(this)}
|
||||
onMouseDown={e => e.preventDefault()}
|
||||
ref={n => this._node = n}>
|
||||
onMouseDown={e => e.preventDefault()}>
|
||||
{this.props.children}
|
||||
<div className="dropdown__backdrop"></div>
|
||||
</div>
|
||||
|
@ -143,9 +143,7 @@ class CookiesModal extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
CookiesModal.propTypes = {
|
||||
onChange: PropTypes.func.isRequired
|
||||
};
|
||||
CookiesModal.propTypes = {};
|
||||
|
||||
// export CookiesModal;
|
||||
export default CookiesModal;
|
||||
|
@ -14,15 +14,17 @@ class RequestSwitcherModal extends Component {
|
||||
this.state = {
|
||||
searchString: '',
|
||||
matchedRequests: [],
|
||||
matchedWorkspaces: [],
|
||||
requestGroups: [],
|
||||
activeIndex: -1
|
||||
}
|
||||
}
|
||||
|
||||
_setActiveIndex (activeIndex) {
|
||||
const maxIndex = this.state.matchedRequests.length + this.state.matchedWorkspaces.length;
|
||||
if (activeIndex < 0) {
|
||||
activeIndex = this.state.matchedRequests.length - 1;
|
||||
} else if (activeIndex >= this.state.matchedRequests.length) {
|
||||
} else if (activeIndex >= maxIndex) {
|
||||
activeIndex = 0;
|
||||
}
|
||||
|
||||
@ -30,19 +32,49 @@ class RequestSwitcherModal extends Component {
|
||||
}
|
||||
|
||||
_activateCurrentIndex () {
|
||||
if (this.state.matchedRequests.length) {
|
||||
// Activate the request if there is one
|
||||
const request = this.state.matchedRequests[this.state.activeIndex];
|
||||
this._activateRequest(request);
|
||||
} else {
|
||||
// Create the request if nothing matched
|
||||
const name = this.state.searchString;
|
||||
const parentId = this.props.activeRequestParentId;
|
||||
const {
|
||||
activeIndex,
|
||||
matchedRequests,
|
||||
matchedWorkspaces
|
||||
} = this.state;
|
||||
|
||||
db.requestCreate({name, parentId}).then(request => {
|
||||
if (activeIndex < matchedRequests.length) {
|
||||
// Activate the request if there is one
|
||||
const request = matchedRequests[activeIndex];
|
||||
this._activateRequest(request);
|
||||
} else if (activeIndex < (matchedRequests.length + matchedWorkspaces.length)) {
|
||||
// Activate the workspace if there is one
|
||||
const index = activeIndex - matchedRequests.length;
|
||||
const workspace = matchedWorkspaces[index];
|
||||
this._activateWorkspace(workspace);
|
||||
} else {
|
||||
// Create request if no match
|
||||
this._createRequestFromSearch();
|
||||
}
|
||||
}
|
||||
|
||||
_createRequestFromSearch () {
|
||||
const {activeRequestParentId} = this.props;
|
||||
const {searchString} = this.state;
|
||||
|
||||
// Create the request if nothing matched
|
||||
const patch = {
|
||||
name: searchString,
|
||||
parentId: activeRequestParentId
|
||||
};
|
||||
|
||||
db.requestCreate(patch).then(request => {
|
||||
this._activateRequest(request);
|
||||
});
|
||||
}
|
||||
|
||||
_activateWorkspace (workspace) {
|
||||
if (!workspace) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.activateWorkspace(workspace);
|
||||
this.modal.hide();
|
||||
}
|
||||
|
||||
_activateRequest (request) {
|
||||
@ -59,10 +91,12 @@ class RequestSwitcherModal extends Component {
|
||||
|
||||
Promise.all([
|
||||
db.requestAll(),
|
||||
db.requestGroupAll()
|
||||
db.requestGroupAll(),
|
||||
db.workspaceAll()
|
||||
]).then(([
|
||||
allRequests,
|
||||
allRequestGroups
|
||||
allRequestGroups,
|
||||
allWorkspaces
|
||||
]) => {
|
||||
// TODO: Support nested RequestGroups
|
||||
// Filter out RequestGroups that don't belong to this Workspace
|
||||
@ -82,9 +116,14 @@ class RequestSwitcherModal extends Component {
|
||||
const parentId = this.props.activeRequestParentId;
|
||||
|
||||
// OPTIMIZATION: This only filters if we have a filter
|
||||
let matchedRequests = !searchString ? requests : requests.filter(
|
||||
r => r.name.toLowerCase().indexOf(searchString.toLowerCase()) !== -1
|
||||
);
|
||||
let matchedRequests = requests;
|
||||
if (searchString) {
|
||||
matchedRequests = matchedRequests.filter(r => {
|
||||
const name = r.name.toLowerCase();
|
||||
const toMatch = searchString.toLowerCase();
|
||||
return name.indexOf(toMatch) !== -1
|
||||
});
|
||||
}
|
||||
|
||||
// OPTIMIZATION: Apply sort after the filter so we have to sort less
|
||||
matchedRequests = matchedRequests.sort(
|
||||
@ -107,11 +146,24 @@ class RequestSwitcherModal extends Component {
|
||||
}
|
||||
);
|
||||
|
||||
let matchedWorkspaces = [];
|
||||
if (searchString) {
|
||||
// Only match workspaces if there is a search
|
||||
matchedWorkspaces = allWorkspaces
|
||||
.filter(w => w._id !== workspaceId)
|
||||
.filter(w => {
|
||||
const name = w.name.toLowerCase();
|
||||
const toMatch = searchString.toLowerCase();
|
||||
return name.indexOf(toMatch) !== -1
|
||||
});
|
||||
}
|
||||
|
||||
const activeIndex = searchString ? 0 : -1;
|
||||
|
||||
this.setState({
|
||||
activeIndex,
|
||||
matchedRequests,
|
||||
matchedWorkspaces,
|
||||
requestGroups,
|
||||
searchString
|
||||
});
|
||||
@ -152,6 +204,7 @@ class RequestSwitcherModal extends Component {
|
||||
render () {
|
||||
const {
|
||||
matchedRequests,
|
||||
matchedWorkspaces,
|
||||
requestGroups,
|
||||
searchString,
|
||||
activeIndex
|
||||
@ -170,7 +223,7 @@ class RequestSwitcherModal extends Component {
|
||||
|
||||
<span className="monospace">esc</span> to dismiss
|
||||
</p>
|
||||
<p>Jump To Request</p>
|
||||
<p>Quick Switch</p>
|
||||
</ModalHeader>
|
||||
<ModalBody className="pad request-switcher">
|
||||
<div className="form-control form-control--outlined no-margin">
|
||||
@ -208,9 +261,31 @@ class RequestSwitcherModal extends Component {
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
|
||||
{matchedRequests.length && matchedWorkspaces.length ? (
|
||||
<hr/>
|
||||
) : null}
|
||||
|
||||
{matchedWorkspaces.map((w, i) => {
|
||||
const buttonClasses = classnames(
|
||||
'btn btn--compact wide text-left',
|
||||
{focus: (activeIndex - matchedRequests.length) === i}
|
||||
);
|
||||
|
||||
return (
|
||||
<li key={w._id}>
|
||||
<button onClick={e => this._activateRequest(w)}
|
||||
className={buttonClasses}>
|
||||
<i className="fa fa-random"></i> Switch to
|
||||
{" "}
|
||||
<strong>{w.name}</strong>
|
||||
</button>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
|
||||
{matchedRequests.length === 0 ? (
|
||||
{!matchedRequests.length && !matchedWorkspaces.length ? (
|
||||
<div className="text-center">
|
||||
<p>
|
||||
No matches found for <strong>{searchString}</strong>
|
||||
@ -229,6 +304,7 @@ class RequestSwitcherModal extends Component {
|
||||
|
||||
RequestSwitcherModal.propTypes = {
|
||||
activateRequest: PropTypes.func.isRequired,
|
||||
activateWorkspace: PropTypes.func.isRequired,
|
||||
workspaceId: PropTypes.string.isRequired,
|
||||
activeRequestParentId: PropTypes.string.isRequired
|
||||
};
|
||||
|
@ -5,9 +5,7 @@ import {connect} from 'react-redux';
|
||||
import {bindActionCreators} from 'redux';
|
||||
import HTML5Backend from 'react-dnd-html5-backend';
|
||||
import {DragDropContext} from 'react-dnd';
|
||||
|
||||
import Mousetrap from '../lib/mousetrap';
|
||||
|
||||
import {addModal} from '../components/modals';
|
||||
import WorkspaceEnvironmentsEditModal from '../components/modals/WorkspaceEnvironmentsEditModal';
|
||||
import CookiesModal from '../components/modals/CookiesModal';
|
||||
@ -23,21 +21,21 @@ import ResponsePane from '../components/ResponsePane';
|
||||
import Sidebar from '../components/sidebar/Sidebar';
|
||||
import {PREVIEW_MODE_FRIENDLY} from '../lib/previewModes';
|
||||
import {
|
||||
MAX_PANE_WIDTH, MIN_PANE_WIDTH,
|
||||
MAX_PANE_WIDTH,
|
||||
MIN_PANE_WIDTH,
|
||||
DEFAULT_PANE_WIDTH,
|
||||
MAX_SIDEBAR_REMS,
|
||||
MIN_SIDEBAR_REMS,
|
||||
DEFAULT_SIDEBAR_WIDTH
|
||||
} from '../lib/constants'
|
||||
|
||||
DEFAULT_SIDEBAR_WIDTH,
|
||||
CHECK_FOR_UPDATES_INTERVAL
|
||||
} from '../lib/constants';
|
||||
import * as GlobalActions from '../redux/modules/global';
|
||||
import * as RequestActions from '../redux/modules/requests';
|
||||
|
||||
import * as WorkspaceActions from '../redux/modules/workspaces';
|
||||
import * as db from '../database';
|
||||
import {importCurl} from '../lib/export/curl';
|
||||
import {trackEvent} from '../lib/analytics';
|
||||
import {getAppVersion} from '../lib/appInfo';
|
||||
import {CHECK_FOR_UPDATES_INTERVAL} from '../lib/constants';
|
||||
import {getModal} from '../components/modals/index';
|
||||
|
||||
|
||||
@ -473,7 +471,8 @@ class App extends Component {
|
||||
const gridTemplateColumns = `${sidebarWidth}rem 0 ${paneWidth}fr 0 ${1 - paneWidth}fr`;
|
||||
|
||||
return (
|
||||
<div id="wrapper" className="wrapper" style={{gridTemplateColumns: gridTemplateColumns}}>
|
||||
<div id="wrapper" className="wrapper"
|
||||
style={{gridTemplateColumns: gridTemplateColumns}}>
|
||||
<Sidebar
|
||||
ref={n => this._sidebar = n}
|
||||
showEnvironmentsModal={() => getModal(WorkspaceEnvironmentsEditModal).show(workspace)}
|
||||
@ -494,7 +493,10 @@ class App extends Component {
|
||||
/>
|
||||
|
||||
<div className="drag drag--sidebar">
|
||||
<div onMouseDown={e => {e.preventDefault(); this._startDragSidebar()}}
|
||||
<div onMouseDown={e => {
|
||||
e.preventDefault();
|
||||
this._startDragSidebar()
|
||||
}}
|
||||
onDoubleClick={() => this._resetDragSidebar()}>
|
||||
</div>
|
||||
</div>
|
||||
@ -548,6 +550,7 @@ class App extends Component {
|
||||
workspaceId={workspace._id}
|
||||
activeRequestParentId={activeRequest ? activeRequest.parentId : workspace._id}
|
||||
activateRequest={r => db.workspaceUpdate(workspace, {metaActiveRequestId: r._id})}
|
||||
activateWorkspace={w => actions.workspaces.activate(w)}
|
||||
/>
|
||||
<EnvironmentEditModal
|
||||
ref={m => addModal(m)}
|
||||
@ -555,9 +558,7 @@ class App extends Component {
|
||||
<WorkspaceEnvironmentsEditModal
|
||||
ref={m => addModal(m)}
|
||||
onChange={w => db.workspaceUpdate(w)}/>
|
||||
<CookiesModal
|
||||
ref={m => addModal(m)}
|
||||
onChange={() => console.log('TODO: COOKIES!!!')}/>
|
||||
<CookiesModal ref={m => addModal(m)}/>
|
||||
|
||||
{/*<div className="toast toast--show">*/}
|
||||
{/*<div className="toast__message">How's it going?</div>*/}
|
||||
@ -574,6 +575,9 @@ App.propTypes = {
|
||||
requests: PropTypes.shape({
|
||||
send: PropTypes.func.isRequired
|
||||
}).isRequired,
|
||||
workspaces: PropTypes.shape({
|
||||
activate: PropTypes.func.isRequired
|
||||
}).isRequired,
|
||||
global: PropTypes.shape({
|
||||
importFile: PropTypes.func.isRequired
|
||||
}).isRequired
|
||||
@ -604,7 +608,8 @@ function mapDispatchToProps (dispatch) {
|
||||
return {
|
||||
actions: {
|
||||
global: bindActionCreators(GlobalActions, dispatch),
|
||||
requests: bindActionCreators(RequestActions, dispatch)
|
||||
requests: bindActionCreators(RequestActions, dispatch),
|
||||
workspaces: bindActionCreators(WorkspaceActions, dispatch)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user