mirror of
https://github.com/Kong/insomnia.git
synced 2026-10-25 16:19:20 -04:00
Allow sidebar to show grpc requests (#2786)
This commit is contained in:
1 parent
d1e1da53e5
commit
5f1c1bb747
8 files changed
+185
-92
No files matched your search
@@ -14,7 +14,7 @@ import { Dropdown } from '../base/dropdown';
|
||||
import SidebarCreateDropdown from './sidebar-create-dropdown';
|
||||
|
||||
type Child = {
|
||||
doc: Request | RequestGroup,
|
||||
doc: Request | GrpcRequest | RequestGroup,
|
||||
children: Array<Child>,
|
||||
collapsed: boolean,
|
||||
hidden: boolean,
|
||||
@@ -103,7 +103,7 @@ class SidebarChildren extends React.PureComponent<Props> {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (child.doc.type === models.request.type) {
|
||||
if (child.doc.type === models.request.type || child.doc.type === models.grpcRequest.type) {
|
||||
return (
|
||||
<SidebarRequestRow
|
||||
key={child.doc._id}
|
||||
|
||||
@@ -13,6 +13,7 @@ import { showModal } from '../modals/index';
|
||||
import RequestSettingsModal from '../modals/request-settings-modal';
|
||||
import { CONTENT_TYPE_GRAPHQL } from '../../../common/constants';
|
||||
import { getMethodOverrideHeader } from '../../../common/misc';
|
||||
import GrpcTag from '../tags/grpc-tag';
|
||||
|
||||
@autobind
|
||||
class SidebarRequestRow extends PureComponent {
|
||||
@@ -174,6 +175,13 @@ class SidebarRequestRow extends PureComponent {
|
||||
</li>
|
||||
);
|
||||
} else {
|
||||
const methodTag =
|
||||
request.type === models.grpcRequest.type ? (
|
||||
<GrpcTag />
|
||||
) : (
|
||||
<MethodTag method={request.method} override={this._getMethodOverrideHeaderValue()} />
|
||||
);
|
||||
|
||||
node = (
|
||||
<li className={classes}>
|
||||
<div
|
||||
@@ -185,10 +193,7 @@ class SidebarRequestRow extends PureComponent {
|
||||
onClick={this._handleRequestActivate}
|
||||
onContextMenu={this._handleShowRequestActions}>
|
||||
<div className="sidebar__clickable">
|
||||
<MethodTag
|
||||
method={request.method}
|
||||
override={this._getMethodOverrideHeaderValue()}
|
||||
/>
|
||||
{methodTag}
|
||||
<Editable
|
||||
value={request.name}
|
||||
fallbackValue={this.state.renderedUrl}
|
||||
@@ -267,7 +272,7 @@ SidebarRequestRow.propTypes = {
|
||||
|
||||
// Optional
|
||||
requestGroup: PropTypes.object,
|
||||
request: PropTypes.object,
|
||||
request: PropTypes.object, // can be Request or GrpcRequest
|
||||
disableDragAndDrop: PropTypes.bool,
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import React from 'react';
|
||||
|
||||
const GrpcTag = () => (
|
||||
<div style={{ position: 'relative' }}>
|
||||
<div className="tag tag--no-bg tag--small method-grpc">
|
||||
<span className="tag__inner">gRPC</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default GrpcTag;
|
||||
@@ -52,11 +52,11 @@ import {
|
||||
selectActiveWorkspaceClientCertificates,
|
||||
selectActiveWorkspaceMeta,
|
||||
selectEntitiesLists,
|
||||
selectSidebarChildren,
|
||||
selectSyncItems,
|
||||
selectUnseenWorkspaces,
|
||||
selectWorkspaceRequestsAndRequestGroups,
|
||||
} from '../redux/selectors';
|
||||
import { selectSidebarChildren } from '../redux/sidebar-selectors';
|
||||
import RequestCreateModal from '../components/modals/request-create-modal';
|
||||
import GenerateCodeModal from '../components/modals/generate-code-modal';
|
||||
import WorkspaceSettingsModal from '../components/modals/workspace-settings-modal';
|
||||
|
||||
@@ -27,11 +27,14 @@
|
||||
}
|
||||
|
||||
.notice,
|
||||
.http-method-PATCH,
|
||||
.method-grpc {
|
||||
.http-method-PATCH {
|
||||
color: var(--color-notice) !important;
|
||||
}
|
||||
|
||||
.method-grpc {
|
||||
color: #ffbf2f !important;
|
||||
}
|
||||
|
||||
.warning,
|
||||
.http-method-PUT {
|
||||
color: var(--color-warning) !important;
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import * as models from '../../../models';
|
||||
import {
|
||||
shouldIgnoreChildrenOf,
|
||||
shouldShowInSidebar,
|
||||
sortByMetaKeyOrId,
|
||||
} from '../sidebar-selectors';
|
||||
import { difference } from 'lodash';
|
||||
|
||||
describe('shouldShowInSidebar', () => {
|
||||
const allTypes = models.types();
|
||||
const supported = [models.request.type, models.requestGroup.type, models.grpcRequest.type];
|
||||
const unsupported = difference(allTypes, supported);
|
||||
|
||||
it.each(supported)('should show %s in sidebar', type => {
|
||||
expect(shouldShowInSidebar({ type })).toBe(true);
|
||||
});
|
||||
|
||||
it.each(unsupported)('should not show %s in sidebar', type => {
|
||||
expect(shouldShowInSidebar({ type })).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('shouldIgnoreChildrenOf', () => {
|
||||
it.each([models.request.type, models.grpcRequest.type])('should ignore children of %s', type => {
|
||||
expect(shouldIgnoreChildrenOf({ type })).toBe(true);
|
||||
});
|
||||
|
||||
it.each([models.requestGroup.type])('should not ignore children of', type => {
|
||||
expect(shouldIgnoreChildrenOf({ type })).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sortByMetaKeyOrId', () => {
|
||||
it('sort by _id if meta keys are identical', () => {
|
||||
const a = { _id: 'a', metaSortKey: '1' };
|
||||
const b = { _id: 'b', metaSortKey: '1' };
|
||||
expect(sortByMetaKeyOrId(a, b)).toBe(1);
|
||||
expect(sortByMetaKeyOrId(b, a)).toBe(-1);
|
||||
});
|
||||
|
||||
it('sort by meta keys', () => {
|
||||
const a = { metaSortKey: '1' };
|
||||
const b = { metaSortKey: '2' };
|
||||
expect(sortByMetaKeyOrId(a, b)).toBe(-1);
|
||||
expect(sortByMetaKeyOrId(b, a)).toBe(1);
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,4 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import { fuzzyMatchAll } from '../../common/misc';
|
||||
import * as models from '../../models';
|
||||
|
||||
// ~~~~~~~~~ //
|
||||
@@ -139,98 +138,22 @@ export const selectActiveWorkspaceEntities = createSelector(
|
||||
export const selectPinnedRequests = createSelector(selectEntitiesLists, entities => {
|
||||
const pinned = {};
|
||||
|
||||
const requests = [...entities.requests, ...entities.grpcRequests];
|
||||
const requestMetas = [...entities.requestMetas, ...entities.grpcRequestMetas];
|
||||
|
||||
// Default all to unpinned
|
||||
for (const request of entities.requests) {
|
||||
for (const request of requests) {
|
||||
pinned[request._id] = false;
|
||||
}
|
||||
|
||||
// Update those that have metadata (not all do)
|
||||
for (const meta of entities.requestMetas) {
|
||||
for (const meta of requestMetas) {
|
||||
pinned[meta.parentId] = meta.pinned;
|
||||
}
|
||||
|
||||
return pinned;
|
||||
});
|
||||
|
||||
export const selectSidebarChildren = createSelector(
|
||||
selectCollapsedRequestGroups,
|
||||
selectPinnedRequests,
|
||||
selectActiveWorkspace,
|
||||
selectActiveWorkspaceMeta,
|
||||
selectEntitiesChildrenMap,
|
||||
(collapsed, pinned, activeWorkspace, activeWorkspaceMeta, childrenMap) => {
|
||||
const sidebarFilter = activeWorkspaceMeta ? activeWorkspaceMeta.sidebarFilter : '';
|
||||
|
||||
function next(parentId, pinnedChildren) {
|
||||
const children = (childrenMap[parentId] || [])
|
||||
.filter(doc => {
|
||||
return doc.type === models.request.type || doc.type === models.requestGroup.type;
|
||||
})
|
||||
.sort((a, b) => {
|
||||
if (a.metaSortKey === b.metaSortKey) {
|
||||
return a._id > b._id ? -1 : 1;
|
||||
} else {
|
||||
return a.metaSortKey < b.metaSortKey ? -1 : 1;
|
||||
}
|
||||
});
|
||||
|
||||
if (children.length > 0) {
|
||||
return children.map(c => {
|
||||
const child = {
|
||||
doc: c,
|
||||
hidden: false,
|
||||
collapsed: !!collapsed[c._id],
|
||||
pinned: !!pinned[c._id],
|
||||
};
|
||||
|
||||
if (child.pinned) {
|
||||
pinnedChildren.push(child);
|
||||
}
|
||||
|
||||
// Don't add children of requests
|
||||
child.children = c.type === models.request.type ? [] : next(c._id, pinnedChildren);
|
||||
|
||||
return child;
|
||||
});
|
||||
} else {
|
||||
return children;
|
||||
}
|
||||
}
|
||||
|
||||
function matchChildren(children, parentNames = []) {
|
||||
// Bail early if no filter defined
|
||||
if (!sidebarFilter) {
|
||||
return children;
|
||||
}
|
||||
|
||||
for (const child of children) {
|
||||
// Gather all parents so we can match them too
|
||||
matchChildren(child.children, [...parentNames, child.doc.name]);
|
||||
|
||||
const hasMatchedChildren = child.children.find(c => c.hidden === false);
|
||||
|
||||
// Try to match request attributes
|
||||
const { name, method } = child.doc;
|
||||
const match = fuzzyMatchAll(sidebarFilter, [name, method, ...parentNames], {
|
||||
splitSpace: true,
|
||||
});
|
||||
|
||||
// Update hidden state depending on whether it matched
|
||||
const matched = hasMatchedChildren || match;
|
||||
child.hidden = !matched;
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
const pinnedChildren = [];
|
||||
const childrenTree = next(activeWorkspace._id, pinnedChildren);
|
||||
const matchedChildren = matchChildren(childrenTree);
|
||||
|
||||
return { pinned: pinnedChildren, all: matchedChildren };
|
||||
},
|
||||
);
|
||||
|
||||
export const selectWorkspaceRequestsAndRequestGroups = createSelector(
|
||||
selectActiveWorkspaceEntities,
|
||||
entities => {
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
// @flow
|
||||
import * as models from '../../models';
|
||||
import type { BaseModel } from '../../models';
|
||||
import type { Request } from '../../models/request';
|
||||
import type { GrpcRequest } from '../../models/grpc-request';
|
||||
import type { RequestGroup } from '../../models/request-group';
|
||||
import { createSelector } from 'reselect';
|
||||
import { fuzzyMatchAll } from '../../common/misc';
|
||||
import {
|
||||
selectActiveWorkspace,
|
||||
selectActiveWorkspaceMeta,
|
||||
selectCollapsedRequestGroups,
|
||||
selectEntitiesChildrenMap,
|
||||
selectPinnedRequests,
|
||||
} from './selectors';
|
||||
|
||||
type SidebarModels = Request | GrpcRequest | RequestGroup;
|
||||
|
||||
export const shouldShowInSidebar = ({ type }: BaseModel): boolean =>
|
||||
type === models.request.type ||
|
||||
type === models.grpcRequest.type ||
|
||||
type === models.requestGroup.type;
|
||||
|
||||
export const shouldIgnoreChildrenOf = ({ type }: SidebarModels): boolean =>
|
||||
type === models.request.type || type === models.grpcRequest.type;
|
||||
|
||||
export const sortByMetaKeyOrId = (a: SidebarModels, b: SidebarModels): number => {
|
||||
if (a.metaSortKey === b.metaSortKey) {
|
||||
return a._id > b._id ? -1 : 1; // ascending
|
||||
} else {
|
||||
return a.metaSortKey < b.metaSortKey ? -1 : 1; // descending
|
||||
}
|
||||
};
|
||||
|
||||
export const selectSidebarChildren = createSelector(
|
||||
selectCollapsedRequestGroups,
|
||||
selectPinnedRequests,
|
||||
selectActiveWorkspace,
|
||||
selectActiveWorkspaceMeta,
|
||||
selectEntitiesChildrenMap,
|
||||
(collapsed, pinned, activeWorkspace, activeWorkspaceMeta, childrenMap) => {
|
||||
const sidebarFilter = activeWorkspaceMeta ? activeWorkspaceMeta.sidebarFilter : '';
|
||||
|
||||
function next(parentId, pinnedChildren) {
|
||||
const children: Array<SidebarModels> = (childrenMap[parentId] || [])
|
||||
.filter(shouldShowInSidebar)
|
||||
.sort(sortByMetaKeyOrId);
|
||||
|
||||
if (children.length > 0) {
|
||||
return children.map(c => {
|
||||
const child = {
|
||||
doc: c,
|
||||
hidden: false,
|
||||
collapsed: !!collapsed[c._id],
|
||||
pinned: !!pinned[c._id],
|
||||
};
|
||||
|
||||
if (child.pinned) {
|
||||
pinnedChildren.push(child);
|
||||
}
|
||||
|
||||
// Don't add children of requests
|
||||
child.children = shouldIgnoreChildrenOf(c) ? [] : next(c._id, pinnedChildren);
|
||||
|
||||
return child;
|
||||
});
|
||||
} else {
|
||||
return children;
|
||||
}
|
||||
}
|
||||
|
||||
function matchChildren(children, parentNames = []) {
|
||||
// Bail early if no filter defined
|
||||
if (!sidebarFilter) {
|
||||
return children;
|
||||
}
|
||||
|
||||
for (const child of children) {
|
||||
// Gather all parents so we can match them too
|
||||
matchChildren(child.children, [...parentNames, child.doc.name]);
|
||||
|
||||
const hasMatchedChildren = child.children.find(c => c.hidden === false);
|
||||
|
||||
// Try to match request attributes
|
||||
const { name, method } = child.doc;
|
||||
const match = fuzzyMatchAll(sidebarFilter, [name, method, ...parentNames], {
|
||||
splitSpace: true,
|
||||
});
|
||||
|
||||
// Update hidden state depending on whether it matched
|
||||
const matched = hasMatchedChildren || match;
|
||||
child.hidden = !matched;
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
const pinnedChildren = [];
|
||||
const childrenTree = next(activeWorkspace._id, pinnedChildren);
|
||||
const matchedChildren = matchChildren(childrenTree);
|
||||
|
||||
return { pinned: pinnedChildren, all: matchedChildren };
|
||||
},
|
||||
);
|
||||
Reference in new issue
Block a user