mirror of
https://github.com/Kong/insomnia
synced 2024-11-07 22:30:15 +00:00
Started on new Sidebar tree stuff
This commit is contained in:
parent
775a623c80
commit
410a218573
@ -10,52 +10,26 @@ class Sidebar extends Component {
|
||||
this.props.changeFilter(value);
|
||||
}
|
||||
|
||||
renderRequestGroupRow (requestGroup = null) {
|
||||
renderRequestGroupRow (child, parent) {
|
||||
const {
|
||||
filter,
|
||||
activeRequestId,
|
||||
addRequestToRequestGroup,
|
||||
toggleRequestGroup,
|
||||
requests,
|
||||
workspaceId
|
||||
toggleRequestGroup
|
||||
} = this.props;
|
||||
|
||||
let filteredRequests = requests.filter(
|
||||
r => {
|
||||
// TODO: Move this to a lib file
|
||||
|
||||
if (!filter) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const requestGroupName = requestGroup ? requestGroup.name : '';
|
||||
const toMatch = `${requestGroupName}✌${r.method}✌${r.name}`.toLowerCase();
|
||||
const matchTokens = filter.toLowerCase().split(' ');
|
||||
for (let i = 0; i < matchTokens.length; i++) {
|
||||
let token = `${matchTokens[i]}`;
|
||||
if (toMatch.indexOf(token) === -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
const requestGroup = child.doc.type === 'RequestGroup' ? child.doc : null;
|
||||
|
||||
if (!requestGroup) {
|
||||
filteredRequests = filteredRequests.filter(r => r.parentId === workspaceId);
|
||||
return filteredRequests.map(request => this.renderRequestRow(request));
|
||||
return child.children.map(c => this._renderChild(c, child));
|
||||
}
|
||||
|
||||
// Grab all of the children for this request group
|
||||
filteredRequests = filteredRequests.filter(r => r.parentId === requestGroup._id);
|
||||
|
||||
// Don't show folder if it was not in the filter
|
||||
if (filter && !filteredRequests.length) {
|
||||
if (filter && !child.children.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const isActive = activeRequestId && filteredRequests.find(r => r._id == activeRequestId);
|
||||
const isActive = activeRequestId && child.children.find(c => c.doc._id == activeRequestId);
|
||||
|
||||
let folderIconClass = 'fa-folder';
|
||||
let expanded = !requestGroup.collapsed;
|
||||
@ -68,6 +42,8 @@ class Sidebar extends Component {
|
||||
{'sidebar__item--active': isActive}
|
||||
);
|
||||
|
||||
child.children.sort((a, b) => a.doc._id > b.doc._id ? -1 : 1);
|
||||
|
||||
return (
|
||||
<li key={requestGroup._id}>
|
||||
<div className={sidebarItemClassNames}>
|
||||
@ -88,20 +64,22 @@ class Sidebar extends Component {
|
||||
</div>
|
||||
</div>
|
||||
<ul>
|
||||
{expanded && !filteredRequests.length ? this.renderRequestRow() : null}
|
||||
{!expanded ? null : filteredRequests.map(request => this.renderRequestRow(request, requestGroup))}
|
||||
{expanded && !child.children.length ? this.renderRequestRow() : null}
|
||||
{!expanded ? null : child.children.map(c => this._renderChild(c, child))}
|
||||
</ul>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
renderRequestRow (request = null, requestGroup = null) {
|
||||
renderRequestRow (child = null, parent = null) {
|
||||
const request = child ? child.doc : null;
|
||||
const requestGroup = parent ? parent.doc : null;
|
||||
const {activeRequestId, activateRequest} = this.props;
|
||||
const isActive = request && activeRequestId && request._id === activeRequestId;
|
||||
|
||||
const isActive = request && activeRequestId && request._id === activeRequestId || false;
|
||||
|
||||
return (
|
||||
<SidebarRequestRow
|
||||
key={request._id}
|
||||
key={request ? request._id : null}
|
||||
activateRequest={activateRequest}
|
||||
isActive={isActive}
|
||||
request={request}
|
||||
@ -110,9 +88,32 @@ class Sidebar extends Component {
|
||||
)
|
||||
}
|
||||
|
||||
_renderChild (child, parent = null) {
|
||||
const {filter} = this.props;
|
||||
|
||||
if (child.doc.type === 'Request') {
|
||||
const r = child.doc;
|
||||
const toMatch = `${r.method}❅${r.name}`.toLowerCase();
|
||||
const matchTokens = filter.toLowerCase().split(' ');
|
||||
for (let i = 0; i < matchTokens.length; i++) {
|
||||
let token = `${matchTokens[i]}`;
|
||||
if (toMatch.indexOf(token) === -1) {
|
||||
// Filter failed. Don't render children
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return this.renderRequestRow(child, parent)
|
||||
} else if (child.doc.type === 'RequestGroup') {
|
||||
return this.renderRequestGroupRow(child, parent);
|
||||
} else {
|
||||
console.error('Unknown child type', child.doc.type);
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const {filter, requestGroups} = this.props;
|
||||
|
||||
const {filter, children} = this.props;
|
||||
|
||||
return (
|
||||
<section className="sidebar bg-dark grid--v section section--bordered">
|
||||
<header className="header bg-brand section__header">
|
||||
@ -121,8 +122,7 @@ class Sidebar extends Component {
|
||||
<div className="grid--v grid--start grid__cell section__body">
|
||||
<ul
|
||||
className="grid--v grid--start grid__cell sidebar__scroll hover-scrollbars sidebar__request-list">
|
||||
{this.renderRequestGroupRow(null)}
|
||||
{requestGroups.map(requestGroup => this.renderRequestGroupRow(requestGroup))}
|
||||
{children.map(c => this._renderChild(c))}
|
||||
</ul>
|
||||
<div className="grid grid--center">
|
||||
<div className="grid__cell form-control form-control--underlined">
|
||||
@ -146,12 +146,11 @@ Sidebar.propTypes = {
|
||||
toggleRequestGroup: PropTypes.func.isRequired,
|
||||
addRequestToRequestGroup: PropTypes.func.isRequired,
|
||||
changeFilter: PropTypes.func.isRequired,
|
||||
|
||||
|
||||
// Other
|
||||
requests: PropTypes.array.isRequired,
|
||||
requestGroups: PropTypes.array.isRequired,
|
||||
children: PropTypes.array.isRequired,
|
||||
workspaceId: PropTypes.string.isRequired,
|
||||
|
||||
|
||||
// Optional
|
||||
filter: PropTypes.string,
|
||||
activeRequestId: PropTypes.string
|
||||
|
@ -37,11 +37,11 @@ SidebarRequestRow.propTypes = {
|
||||
activateRequest: PropTypes.func.isRequired,
|
||||
|
||||
// Other
|
||||
request: PropTypes.object.isRequired,
|
||||
isActive: PropTypes.bool.isRequired,
|
||||
|
||||
// Optional
|
||||
requestGroup: PropTypes.object
|
||||
requestGroup: PropTypes.object,
|
||||
request: PropTypes.object
|
||||
};
|
||||
|
||||
export default SidebarRequestRow;
|
||||
|
@ -24,24 +24,47 @@ class App extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const {actions, modals, workspaces, requestGroups, requests, responses} = this.props;
|
||||
_generateSidebarTree (parentId, entities) {
|
||||
const children = entities.filter(e => e.parentId === parentId);
|
||||
|
||||
if (children.length > 0) {
|
||||
return children.map(c => ({
|
||||
doc: c,
|
||||
children: this._generateSidebarTree(c._id, entities)
|
||||
}));
|
||||
} else {
|
||||
return children;
|
||||
}
|
||||
}
|
||||
|
||||
const activeRequest = requests.active;
|
||||
const activeResponse = activeRequest ? responses[activeRequest._id] : undefined;
|
||||
render () {
|
||||
const {actions, modals, workspaces, requests, entities} = this.props;
|
||||
|
||||
const activeRequestId = workspaces.active.activeRequestId;
|
||||
const activeRequest = activeRequestId ? entities.requests[activeRequestId] : null;
|
||||
|
||||
const responses = Object.keys(entities.responses).map(id => entities.responses[id]);
|
||||
const allRequests = Object.keys(entities.requests).map(id => entities.requests[id]);
|
||||
const allRequestGroups = Object.keys(entities.requestGroups).map(id => entities.requestGroups[id]);
|
||||
|
||||
const activeResponse = responses.find(r => r.parentId === activeRequestId);
|
||||
|
||||
const children = this._generateSidebarTree(
|
||||
workspaces.active._id,
|
||||
allRequests.concat(allRequestGroups)
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="grid bg-super-dark tall">
|
||||
<Sidebar
|
||||
workspaceId={workspaces.active._id}
|
||||
activateRequest={db.requestActivate}
|
||||
activateRequest={r => db.update(workspaces.active, {activeRequestId: r._id})}
|
||||
changeFilter={actions.requests.changeFilter}
|
||||
addRequestToRequestGroup={requestGroup => db.requestCreate({parentId: requestGroup._id})}
|
||||
toggleRequestGroup={requestGroup => db.update(requestGroup, {collapsed: !requestGroup.collapsed})}
|
||||
activeRequestId={activeRequest._id}
|
||||
activeRequestId={activeRequest ? activeRequest._id : null}
|
||||
filter={requests.filter}
|
||||
requestGroups={requestGroups.all.sort((a, b) => a._id > b._id ? -1 : 1)}
|
||||
requests={requests.all.sort((a, b) => a._id > b._id ? -1 : 1)}
|
||||
children={children}
|
||||
/>
|
||||
<div className="grid wide grid--collapse">
|
||||
<RequestPane
|
||||
@ -96,13 +119,8 @@ App.propTypes = {
|
||||
workspaces: PropTypes.shape({
|
||||
active: PropTypes.object
|
||||
}).isRequired,
|
||||
responses: PropTypes.object.isRequired,
|
||||
requestGroups: PropTypes.shape({
|
||||
all: PropTypes.array.isRequired
|
||||
}).isRequired,
|
||||
requests: PropTypes.shape({
|
||||
all: PropTypes.array.isRequired,
|
||||
active: PropTypes.object
|
||||
filter: PropTypes.string.isRequired
|
||||
}).isRequired,
|
||||
modals: PropTypes.array.isRequired
|
||||
};
|
||||
@ -111,9 +129,8 @@ function mapStateToProps (state) {
|
||||
return {
|
||||
actions: state.actions,
|
||||
workspaces: state.workspaces,
|
||||
requestGroups: state.requestGroups,
|
||||
requests: state.requests,
|
||||
responses: state.responses,
|
||||
entities: state.entities,
|
||||
modals: state.modals
|
||||
};
|
||||
}
|
||||
|
@ -3,8 +3,6 @@ import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
|
||||
import * as ModalActions from '../redux/modules/modals'
|
||||
import * as RequestGroupActions from '../redux/modules/requestGroups'
|
||||
import * as RequestActions from '../redux/modules/requests'
|
||||
import PromptModal from '../components/base/PromptModal'
|
||||
|
||||
import * as db from '../database'
|
||||
@ -65,12 +63,6 @@ Prompts.propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
modals: PropTypes.shape({
|
||||
hide: PropTypes.func.isRequired
|
||||
}),
|
||||
requestGroups: PropTypes.shape({
|
||||
update: PropTypes.func.isRequired
|
||||
}),
|
||||
requests: PropTypes.shape({
|
||||
update: PropTypes.func.isRequired
|
||||
})
|
||||
}),
|
||||
modals: PropTypes.array.isRequired
|
||||
@ -86,9 +78,7 @@ function mapStateToProps (state) {
|
||||
function mapDispatchToProps (dispatch) {
|
||||
return {
|
||||
actions: {
|
||||
requests: bindActionCreators(RequestActions, dispatch),
|
||||
modals: bindActionCreators(ModalActions, dispatch),
|
||||
requestGroups: bindActionCreators(RequestGroupActions, dispatch)
|
||||
modals: bindActionCreators(ModalActions, dispatch)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ export const TYPE_RESPONSE = 'Response';
|
||||
let db = new PouchDB('insomnia.db', {adapter: 'websql'});
|
||||
|
||||
// For browser console debugging
|
||||
// global.db = db;
|
||||
global.db = db;
|
||||
|
||||
let changeListeners = {};
|
||||
|
||||
@ -145,10 +145,6 @@ export function requestCopy (request) {
|
||||
return requestCreate(Object.assign({}, request, {name}));
|
||||
}
|
||||
|
||||
export function requestActivate (request) {
|
||||
return update(request, {activated: Date.now()});
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~ //
|
||||
// REQUEST GROUP //
|
||||
|
@ -3,9 +3,9 @@ import {combineReducers} from 'redux'
|
||||
import {TYPE_WORKSPACE, TYPE_REQUEST_GROUP, TYPE_REQUEST, TYPE_RESPONSE} from '../../database/index'
|
||||
import * as workspaceFns from './workspaces'
|
||||
import * as requestGroupFns from './requestGroups'
|
||||
import * as requestFns from './requests'
|
||||
import * as responseFns from './responses'
|
||||
|
||||
const ENTITY_UPDATE = 'entities/update';
|
||||
const ENTITY_REMOVE = 'entities/remove';
|
||||
|
||||
// ~~~~~~~~ //
|
||||
// REDUCERS //
|
||||
@ -30,6 +30,30 @@ function generateEntityReducer (referenceName, updateAction, deleteAction) {
|
||||
}
|
||||
}
|
||||
|
||||
function genericEntityReducer (referenceName) {
|
||||
return function (state = {}, action) {
|
||||
const doc = action[referenceName];
|
||||
|
||||
if (!doc) {
|
||||
return state;
|
||||
}
|
||||
|
||||
switch (action.type) {
|
||||
|
||||
case ENTITY_UPDATE:
|
||||
return {...state, [doc._id]: doc};
|
||||
|
||||
case ENTITY_REMOVE:
|
||||
const newState = Object.assign({}, state);
|
||||
delete newState[action[referenceName]._id];
|
||||
return newState;
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const workspaces = generateEntityReducer(
|
||||
'workspace',
|
||||
workspaceFns.WORKSPACE_UPDATE,
|
||||
@ -37,28 +61,16 @@ const workspaces = generateEntityReducer(
|
||||
);
|
||||
|
||||
const requestGroups = generateEntityReducer(
|
||||
'requestGroup',
|
||||
'requestGroup',
|
||||
requestGroupFns.REQUEST_GROUP_UPDATE,
|
||||
requestGroupFns.REQUEST_GROUP_DELETE
|
||||
);
|
||||
|
||||
const requests = generateEntityReducer(
|
||||
'request',
|
||||
requestFns.REQUEST_UPDATE,
|
||||
requestFns.REQUEST_DELETE
|
||||
);
|
||||
|
||||
const responses = generateEntityReducer(
|
||||
'response',
|
||||
responseFns.RESPONSE_UPDATE,
|
||||
responseFns.RESPONSE_DELETE
|
||||
);
|
||||
|
||||
export default combineReducers({
|
||||
workspaces,
|
||||
requestGroups,
|
||||
requests,
|
||||
responses
|
||||
requests: genericEntityReducer('request'),
|
||||
responses: genericEntityReducer('response')
|
||||
})
|
||||
|
||||
|
||||
@ -69,33 +81,21 @@ export default combineReducers({
|
||||
const updateFns = {
|
||||
[TYPE_WORKSPACE]: workspaceFns.update,
|
||||
[TYPE_REQUEST_GROUP]: requestGroupFns.update,
|
||||
[TYPE_REQUEST]: requestFns.update,
|
||||
[TYPE_RESPONSE]: responseFns.update
|
||||
[TYPE_RESPONSE]: response => ({type: ENTITY_UPDATE, response}),
|
||||
[TYPE_REQUEST]: request => ({type: ENTITY_UPDATE, request})
|
||||
};
|
||||
|
||||
const removeFns = {
|
||||
[TYPE_WORKSPACE]: workspaceFns.remove,
|
||||
[TYPE_REQUEST_GROUP]: requestGroupFns.remove,
|
||||
[TYPE_REQUEST]: requestFns.remove
|
||||
// Response doesn't have a remove function (yet...)
|
||||
[TYPE_RESPONSE]: response => ({type: ENTITY_UPDATE, response}),
|
||||
[TYPE_REQUEST]: request => ({type: ENTITY_REMOVE, request})
|
||||
};
|
||||
|
||||
export function update (doc) {
|
||||
// Using dispatch here because Redux gets mad if we don't return anything
|
||||
// in a normal action creator
|
||||
return dispatch => {
|
||||
if (updateFns.hasOwnProperty(doc.type)) {
|
||||
dispatch(updateFns[doc.type](doc));
|
||||
}
|
||||
}
|
||||
return updateFns[doc.type](doc);
|
||||
}
|
||||
|
||||
export function remove (doc) {
|
||||
// Using dispatch here because Redux gets mad if we don't return anything
|
||||
// in a normal action creator
|
||||
return dispatch => {
|
||||
if (removeFns.hasOwnProperty(doc.type)) {
|
||||
dispatch(removeFns[doc.type](doc));
|
||||
}
|
||||
}
|
||||
return removeFns[doc.type](doc);
|
||||
}
|
||||
|
@ -1,93 +1,35 @@
|
||||
import {combineReducers} from 'redux'
|
||||
|
||||
import * as network from '../../lib/network'
|
||||
import {loadStart, loadStop} from './global'
|
||||
import {show} from './modals'
|
||||
import {MODAL_REQUEST_RENAME} from '../../lib/constants'
|
||||
|
||||
export const REQUEST_UPDATE = 'requests/update';
|
||||
export const REQUEST_DELETE = 'requests/delete';
|
||||
export const REQUEST_CHANGE_FILTER = 'requests/filter';
|
||||
|
||||
const initialState = {
|
||||
filter: ''
|
||||
};
|
||||
|
||||
// ~~~~~~~~ //
|
||||
// REDUCERS //
|
||||
// ~~~~~~~~ //
|
||||
|
||||
function allReducer (state = [], action) {
|
||||
switch (action.type) {
|
||||
|
||||
case REQUEST_DELETE:
|
||||
return state.filter(r => r._id !== action.request._id);
|
||||
|
||||
case REQUEST_UPDATE:
|
||||
const i = state.findIndex(r => r._id === action.request._id);
|
||||
|
||||
if (i === -1) {
|
||||
return [action.request, ...state];
|
||||
} else {
|
||||
return [...state.slice(0, i), action.request, ...state.slice(i + 1)]
|
||||
}
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function filterReducer (state = '', action) {
|
||||
export default function (state = initialState, action) {
|
||||
switch (action.type) {
|
||||
|
||||
case REQUEST_CHANGE_FILTER:
|
||||
return action.filter;
|
||||
const filter = action.filter;
|
||||
return Object.assign({}, state, {filter});
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function activeReducer (state = null, action) {
|
||||
switch (action.type) {
|
||||
|
||||
case REQUEST_UPDATE:
|
||||
if (state && state._id === action.request._id) {
|
||||
// Update the currently active request
|
||||
return action.request;
|
||||
} else if (state) {
|
||||
// Activate a new request
|
||||
return action.request.activated > state.activated ? action.request : state;
|
||||
} else if (action.request.activated > 0) {
|
||||
// Activate request if there isn't one
|
||||
return action.request;
|
||||
} else {
|
||||
return state;
|
||||
}
|
||||
|
||||
case REQUEST_DELETE:
|
||||
return state && state._id === action.request._id ? null : state;
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default combineReducers({
|
||||
all: allReducer,
|
||||
filter: filterReducer,
|
||||
active: activeReducer
|
||||
});
|
||||
|
||||
|
||||
// ~~~~~~~ //
|
||||
// ACTIONS //
|
||||
// ~~~~~~~ //
|
||||
|
||||
export function remove (request) {
|
||||
return {type: REQUEST_DELETE, request};
|
||||
}
|
||||
|
||||
export function update (request) {
|
||||
return {type: REQUEST_UPDATE, request};
|
||||
}
|
||||
|
||||
export function changeFilter (filter) {
|
||||
return {type: REQUEST_CHANGE_FILTER, filter};
|
||||
}
|
||||
|
@ -1,30 +1,12 @@
|
||||
export const RESPONSE_UPDATE = 'responses/update';
|
||||
export const RESPONSE_DELETE = 'responses/delete';
|
||||
|
||||
const initialState = {};
|
||||
|
||||
// ~~~~~~~~ //
|
||||
// REDUCERS //
|
||||
// ~~~~~~~~ //
|
||||
|
||||
export default function (state = initialState, action) {
|
||||
switch (action.type) {
|
||||
|
||||
case RESPONSE_UPDATE:
|
||||
return Object.assign({}, state, {
|
||||
[action.response.parentId]: action.response
|
||||
});
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
// None yet
|
||||
|
||||
|
||||
// ~~~~~~~ //
|
||||
// ACTIONS //
|
||||
// ~~~~~~~ //
|
||||
|
||||
export function update (response) {
|
||||
return {type: RESPONSE_UPDATE, response};
|
||||
}
|
||||
// None yet...
|
||||
|
Loading…
Reference in New Issue
Block a user