mirror of
https://github.com/Kong/insomnia.git
synced 2026-10-28 01:29:28 -04:00
Adds dropdown items for New Folder (and requisite work to accomplish this) (#4862)
Co-authored-by: Dimitri Mitropoulos <dimitropoulos@users.noreply.github.com> Co-authored-by: gatzjames <jamesgatzos@gmail.com>
This commit is contained in:
14 files changed
+578
-614
No files matched your search
Generated
+13
-12
@@ -73,6 +73,7 @@
|
||||
"@types/fs-extra": "^5.1.0",
|
||||
"@types/hapi__hawk": "^8.0.2",
|
||||
"@types/js-yaml": "^4.0.1",
|
||||
"@types/jshint": "^2.12.1",
|
||||
"@types/license-checker": "^25.0.1",
|
||||
"@types/marked": "^4.0.2",
|
||||
"@types/mime-types": "^2.1.1",
|
||||
@@ -4675,12 +4676,6 @@
|
||||
"integrity": "sha512-xdOvNmXmrZqqPy3kuCQ+fz6wA0xU5pji9cd1nDrflWaAWtYLLGk5ykW0H6yg5TVyehHP1pfmuuSaZkhP+kspVA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/jshint": {
|
||||
"version": "2.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/jshint/-/jshint-2.12.1.tgz",
|
||||
"integrity": "sha512-Sen/qexrVc74JFfqPfaRB5zF/aIuziEmENKFQgpUNU23Ebja/aAFXdnPpiB9qumE8QWLCHFinuVbx5THc5tWkw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/jsdom": {
|
||||
"version": "16.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-16.2.14.tgz",
|
||||
@@ -4692,6 +4687,12 @@
|
||||
"@types/tough-cookie": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jshint": {
|
||||
"version": "2.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/jshint/-/jshint-2.12.1.tgz",
|
||||
"integrity": "sha512-Sen/qexrVc74JFfqPfaRB5zF/aIuziEmENKFQgpUNU23Ebja/aAFXdnPpiB9qumE8QWLCHFinuVbx5THc5tWkw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
|
||||
@@ -24041,12 +24042,6 @@
|
||||
"integrity": "sha512-xdOvNmXmrZqqPy3kuCQ+fz6wA0xU5pji9cd1nDrflWaAWtYLLGk5ykW0H6yg5TVyehHP1pfmuuSaZkhP+kspVA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/jshint": {
|
||||
"version": "2.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/jshint/-/jshint-2.12.1.tgz",
|
||||
"integrity": "sha512-Sen/qexrVc74JFfqPfaRB5zF/aIuziEmENKFQgpUNU23Ebja/aAFXdnPpiB9qumE8QWLCHFinuVbx5THc5tWkw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/jsdom": {
|
||||
"version": "16.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-16.2.14.tgz",
|
||||
@@ -24058,6 +24053,12 @@
|
||||
"@types/tough-cookie": "*"
|
||||
}
|
||||
},
|
||||
"@types/jshint": {
|
||||
"version": "2.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/jshint/-/jshint-2.12.1.tgz",
|
||||
"integrity": "sha512-Sen/qexrVc74JFfqPfaRB5zF/aIuziEmENKFQgpUNU23Ebja/aAFXdnPpiB9qumE8QWLCHFinuVbx5THc5tWkw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/json-schema": {
|
||||
"version": "7.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
|
||||
|
||||
+146
-142
@@ -1,10 +1,8 @@
|
||||
import { autoBindMethodsForReact } from 'class-autobind-decorator';
|
||||
import classnames from 'classnames';
|
||||
import { HotKeyRegistry } from 'insomnia-common';
|
||||
import React, { PureComponent } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import React, { forwardRef, useCallback, useImperativeHandle, useRef, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { AUTOBIND_CFG } from '../../../common/constants';
|
||||
import { hotKeyRefs } from '../../../common/hotkeys';
|
||||
import { RENDER_PURPOSE_NO_RENDER } from '../../../common/render';
|
||||
import * as models from '../../../models';
|
||||
@@ -12,8 +10,8 @@ import type { RequestGroup } from '../../../models/request-group';
|
||||
import type { RequestGroupAction } from '../../../plugins';
|
||||
import { getRequestGroupActions } from '../../../plugins';
|
||||
import * as pluginContexts from '../../../plugins/context/index';
|
||||
import { RootState } from '../../redux/modules';
|
||||
import { selectActiveEnvironment, selectActiveProject } from '../../redux/selectors';
|
||||
import { createRequest, CreateRequestType } from '../../hooks/create-request';
|
||||
import { selectActiveEnvironment, selectActiveProject, selectActiveWorkspace } from '../../redux/selectors';
|
||||
import { Dropdown, DropdownProps } from '../base/dropdown/dropdown';
|
||||
import { DropdownButton } from '../base/dropdown/dropdown-button';
|
||||
import { DropdownDivider } from '../base/dropdown/dropdown-divider';
|
||||
@@ -23,154 +21,160 @@ import { PromptButton } from '../base/prompt-button';
|
||||
import { showError, showModal } from '../modals';
|
||||
import { EnvironmentEditModal } from '../modals/environment-edit-modal';
|
||||
|
||||
type ReduxProps = ReturnType<typeof mapStateToProps>;
|
||||
|
||||
const mapStateToProps = (state: RootState) => ({
|
||||
activeProject: selectActiveProject(state),
|
||||
activeEnvironment: selectActiveEnvironment(state),
|
||||
});
|
||||
|
||||
interface Props extends ReduxProps, Partial<DropdownProps> {
|
||||
interface Props extends Partial<DropdownProps> {
|
||||
requestGroup: RequestGroup;
|
||||
hotKeyRegistry: HotKeyRegistry;
|
||||
handleCreateRequest: (id: string) => any;
|
||||
handleDuplicateRequestGroup: (requestGroup: RequestGroup) => any;
|
||||
handleShowSettings: (requestGroup: RequestGroup) => any;
|
||||
handleCreateRequestGroup: (requestGroup: string) => any;
|
||||
}
|
||||
|
||||
interface State {
|
||||
actionPlugins: RequestGroupAction[];
|
||||
loadingActions: Record<string, boolean>;
|
||||
interface RequestGroupActionsDropdownHandle {
|
||||
show: () => void;
|
||||
}
|
||||
|
||||
@autoBindMethodsForReact(AUTOBIND_CFG)
|
||||
export class UnconnectedRequestGroupActionsDropdown extends PureComponent<Props, State> {
|
||||
_dropdown: Dropdown | null = null;
|
||||
state: State = {
|
||||
actionPlugins: [],
|
||||
loadingActions: {},
|
||||
};
|
||||
export const RequestGroupActionsDropdown = forwardRef<RequestGroupActionsDropdownHandle, Props>(({
|
||||
requestGroup,
|
||||
hotKeyRegistry,
|
||||
handleShowSettings,
|
||||
handleDuplicateRequestGroup,
|
||||
handleCreateRequestGroup,
|
||||
...other
|
||||
}, ref) => {
|
||||
const [actionPlugins, setActionPlugins] = useState<RequestGroupAction[]>([]);
|
||||
const [loadingActions, setLoadingActions] = useState< Record<string, boolean>>({});
|
||||
const dropdownRef = useRef<Dropdown | null>(null);
|
||||
|
||||
_setDropdownRef(dropdown: Dropdown) {
|
||||
this._dropdown = dropdown;
|
||||
}
|
||||
const activeProject = useSelector(selectActiveProject);
|
||||
const activeEnvironment = useSelector(selectActiveEnvironment);
|
||||
const activeWorkspace = useSelector(selectActiveWorkspace);
|
||||
const activeWorkspaceId = activeWorkspace?._id;
|
||||
|
||||
async _handleRequestCreate() {
|
||||
this.props.handleCreateRequest(this.props.requestGroup._id);
|
||||
}
|
||||
|
||||
_handleRequestGroupDuplicate() {
|
||||
this.props.handleDuplicateRequestGroup(this.props.requestGroup);
|
||||
}
|
||||
|
||||
async _handleRequestGroupCreate() {
|
||||
this.props.handleCreateRequestGroup(this.props.requestGroup._id);
|
||||
}
|
||||
|
||||
async _handleDeleteFolder() {
|
||||
await models.stats.incrementDeletedRequestsForDescendents(this.props.requestGroup);
|
||||
models.requestGroup.remove(this.props.requestGroup);
|
||||
}
|
||||
|
||||
_handleEditEnvironment() {
|
||||
showModal(EnvironmentEditModal, this.props.requestGroup);
|
||||
}
|
||||
|
||||
async onOpen() {
|
||||
const plugins = await getRequestGroupActions();
|
||||
this.setState({
|
||||
actionPlugins: plugins,
|
||||
});
|
||||
}
|
||||
|
||||
async show() {
|
||||
this._dropdown?.show();
|
||||
}
|
||||
|
||||
async _handlePluginClick(p: RequestGroupAction) {
|
||||
this.setState(state => ({
|
||||
loadingActions: { ...state.loadingActions, [p.label]: true },
|
||||
}));
|
||||
|
||||
try {
|
||||
const { activeEnvironment, requestGroup, activeProject } = this.props;
|
||||
const activeEnvironmentId = activeEnvironment ? activeEnvironment._id : null;
|
||||
const context = {
|
||||
...(pluginContexts.app.init(RENDER_PURPOSE_NO_RENDER) as Record<string, any>),
|
||||
...pluginContexts.data.init(activeProject._id),
|
||||
...(pluginContexts.store.init(p.plugin) as Record<string, any>),
|
||||
...(pluginContexts.network.init(activeEnvironmentId) as Record<string, any>),
|
||||
};
|
||||
const requests = await models.request.findByParentId(requestGroup._id);
|
||||
requests.sort((a, b) => a.metaSortKey - b.metaSortKey);
|
||||
await p.action(context, {
|
||||
requestGroup,
|
||||
requests,
|
||||
});
|
||||
} catch (err) {
|
||||
showError({
|
||||
title: 'Plugin Action Failed',
|
||||
error: err,
|
||||
});
|
||||
const create = useCallback((requestType: CreateRequestType) => {
|
||||
if (activeWorkspaceId) {
|
||||
createRequest({ parentId: requestGroup._id, requestType, workspaceId: activeWorkspaceId });
|
||||
}
|
||||
}, [activeWorkspaceId, requestGroup._id]);
|
||||
|
||||
this.setState(state => ({
|
||||
loadingActions: { ...state.loadingActions, [p.label]: false },
|
||||
}));
|
||||
this._dropdown?.hide();
|
||||
}
|
||||
useImperativeHandle(ref, () => ({
|
||||
show: () => {
|
||||
dropdownRef.current?.show();
|
||||
},
|
||||
}));
|
||||
|
||||
render() {
|
||||
const {
|
||||
// eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
requestGroup,
|
||||
// eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
hotKeyRegistry,
|
||||
...other
|
||||
} = this.props;
|
||||
const { actionPlugins, loadingActions } = this.state;
|
||||
return (
|
||||
<Dropdown ref={this._setDropdownRef} onOpen={this.onOpen} {...other}>
|
||||
<DropdownButton>
|
||||
<i className="fa fa-caret-down" />
|
||||
</DropdownButton>
|
||||
<DropdownItem onClick={() => this._handleRequestCreate()}>
|
||||
<i className="fa fa-plus-circle" /> New Request
|
||||
<DropdownHint keyBindings={hotKeyRegistry[hotKeyRefs.REQUEST_CREATE_HTTP.id]} />
|
||||
</DropdownItem>
|
||||
<DropdownItem onClick={this._handleRequestGroupCreate}>
|
||||
<i className="fa fa-folder" /> New Folder
|
||||
<DropdownHint keyBindings={hotKeyRegistry[hotKeyRefs.REQUEST_SHOW_CREATE_FOLDER.id]} />
|
||||
</DropdownItem>
|
||||
<DropdownDivider />
|
||||
<DropdownItem onClick={this._handleRequestGroupDuplicate}>
|
||||
<i className="fa fa-copy" /> Duplicate
|
||||
</DropdownItem>
|
||||
<DropdownItem onClick={this._handleEditEnvironment}>
|
||||
<i className="fa fa-code" /> Environment
|
||||
</DropdownItem>
|
||||
<DropdownItem buttonClass={PromptButton} addIcon onClick={this._handleDeleteFolder}>
|
||||
<i className="fa fa-trash-o" /> Delete
|
||||
</DropdownItem>
|
||||
{actionPlugins.length > 0 && <DropdownDivider>Plugins</DropdownDivider>}
|
||||
{actionPlugins.map((p: RequestGroupAction) => (
|
||||
<DropdownItem key={p.label} onClick={() => this._handlePluginClick(p)} stayOpenAfterClick>
|
||||
{loadingActions[p.label] ? (
|
||||
<i className="fa fa-refresh fa-spin" />
|
||||
) : (
|
||||
<i className={classnames('fa', p.icon || 'fa-code')} />
|
||||
)}
|
||||
{p.label}
|
||||
</DropdownItem>
|
||||
))}
|
||||
<DropdownDivider />
|
||||
<DropdownItem onClick={this.props.handleShowSettings}>
|
||||
<i className="fa fa-wrench" /> Settings
|
||||
</DropdownItem>
|
||||
</Dropdown>
|
||||
);
|
||||
}
|
||||
}
|
||||
const onOpen = useCallback(() => {
|
||||
getRequestGroupActions().then(actionPlugins => {
|
||||
setActionPlugins(actionPlugins);
|
||||
});
|
||||
}, []);
|
||||
|
||||
export const RequestGroupActionsDropdown = connect(mapStateToProps, null, null, { forwardRef: true })(UnconnectedRequestGroupActionsDropdown);
|
||||
const handleRequestGroupDuplicate = useCallback(() => {
|
||||
handleDuplicateRequestGroup(requestGroup);
|
||||
}, [requestGroup, handleDuplicateRequestGroup]);
|
||||
|
||||
const handleRequestGroupCreate = useCallback(() => {
|
||||
handleCreateRequestGroup(requestGroup._id);
|
||||
}, [handleCreateRequestGroup, requestGroup._id]);
|
||||
|
||||
const handleDeleteFolder = useCallback(() => {
|
||||
models.stats.incrementDeletedRequestsForDescendents(requestGroup).then(() => {
|
||||
models.requestGroup.remove(requestGroup);
|
||||
});
|
||||
}, [requestGroup]);
|
||||
|
||||
const handleEditEnvironment = useCallback(() => {
|
||||
showModal(EnvironmentEditModal, requestGroup);
|
||||
}, [requestGroup]);
|
||||
|
||||
const handlePluginClick = useCallback(({ label, plugin, action }: RequestGroupAction) => {
|
||||
const fn = async () => {
|
||||
setLoadingActions({ ...loadingActions, [label]: true });
|
||||
|
||||
try {
|
||||
const activeEnvironmentId = activeEnvironment ? activeEnvironment._id : null;
|
||||
const context = {
|
||||
...(pluginContexts.app.init(RENDER_PURPOSE_NO_RENDER) as Record<string, any>),
|
||||
...pluginContexts.data.init(activeProject._id),
|
||||
...(pluginContexts.store.init(plugin) as Record<string, any>),
|
||||
...(pluginContexts.network.init(activeEnvironmentId) as Record<string, any>),
|
||||
};
|
||||
const requests = await models.request.findByParentId(requestGroup._id);
|
||||
requests.sort((a, b) => a.metaSortKey - b.metaSortKey);
|
||||
await action(context, {
|
||||
requestGroup,
|
||||
requests,
|
||||
});
|
||||
} catch (err) {
|
||||
showError({
|
||||
title: 'Plugin Action Failed',
|
||||
error: err,
|
||||
});
|
||||
}
|
||||
|
||||
setLoadingActions({
|
||||
...loadingActions,
|
||||
[label]: false,
|
||||
});
|
||||
|
||||
dropdownRef.current?.hide();
|
||||
};
|
||||
fn();
|
||||
}, [dropdownRef, loadingActions, activeEnvironment, requestGroup, activeProject]);
|
||||
|
||||
return (
|
||||
<Dropdown ref={dropdownRef} onOpen={onOpen} {...other}>
|
||||
<DropdownButton>
|
||||
<i className="fa fa-caret-down" />
|
||||
</DropdownButton>
|
||||
|
||||
<DropdownItem value="HTTP" onClick={create}>
|
||||
<i className="fa fa-plus-circle" />New HTTP Request
|
||||
<DropdownHint keyBindings={hotKeyRegistry[hotKeyRefs.REQUEST_CREATE_HTTP.id]} />
|
||||
</DropdownItem>
|
||||
|
||||
<DropdownItem value="GraphQL" onClick={create}>
|
||||
<i className="fa fa-plus-circle" />New GraphQL Request
|
||||
</DropdownItem>
|
||||
|
||||
<DropdownItem value="gRPC" onClick={create}>
|
||||
<i className="fa fa-plus-circle" />New gRPC Request
|
||||
</DropdownItem>
|
||||
|
||||
<DropdownItem onClick={handleRequestGroupCreate}>
|
||||
<i className="fa fa-folder" /> New Folder
|
||||
<DropdownHint keyBindings={hotKeyRegistry[hotKeyRefs.REQUEST_SHOW_CREATE_FOLDER.id]} />
|
||||
</DropdownItem>
|
||||
|
||||
<DropdownDivider />
|
||||
|
||||
<DropdownItem onClick={handleRequestGroupDuplicate}>
|
||||
<i className="fa fa-copy" /> Duplicate
|
||||
</DropdownItem>
|
||||
|
||||
<DropdownItem onClick={handleEditEnvironment}>
|
||||
<i className="fa fa-code" /> Environment
|
||||
</DropdownItem>
|
||||
|
||||
<DropdownItem buttonClass={PromptButton} addIcon onClick={handleDeleteFolder}>
|
||||
<i className="fa fa-trash-o" /> Delete
|
||||
</DropdownItem>
|
||||
|
||||
{actionPlugins.length > 0 && <DropdownDivider>Plugins</DropdownDivider>}
|
||||
{actionPlugins.map((requestGroupAction: RequestGroupAction) => (
|
||||
<DropdownItem key={requestGroupAction.label} onClick={() => handlePluginClick(requestGroupAction)} stayOpenAfterClick>
|
||||
{loadingActions[requestGroupAction.label] ? (
|
||||
<i className="fa fa-refresh fa-spin" />
|
||||
) : (
|
||||
<i className={classnames('fa', requestGroupAction.icon || 'fa-code')} />
|
||||
)}
|
||||
{requestGroupAction.label}
|
||||
</DropdownItem>
|
||||
))}
|
||||
<DropdownDivider />
|
||||
<DropdownItem onClick={handleShowSettings}>
|
||||
<i className="fa fa-wrench" /> Settings
|
||||
</DropdownItem>
|
||||
</Dropdown>
|
||||
);
|
||||
});
|
||||
RequestGroupActionsDropdown.displayName = 'RequestGroupActionsDropdown';
|
||||
@@ -2,24 +2,29 @@ import React, { FC, useCallback } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { hotKeyRefs } from '../../../common/hotkeys';
|
||||
import { createRequest } from '../../hooks/create-request';
|
||||
import { ForceToWorkspace } from '../../redux/modules/helpers';
|
||||
import { importFile } from '../../redux/modules/import';
|
||||
import { selectActiveWorkspace, selectSettings } from '../../redux/selectors';
|
||||
import { Hotkey } from '../hotkey';
|
||||
import { Pane, PaneBody, PaneHeader } from './pane';
|
||||
|
||||
interface Props {
|
||||
handleCreateRequest: () => void;
|
||||
}
|
||||
|
||||
export const PlaceholderRequestPane: FC<Props> = ({
|
||||
handleCreateRequest,
|
||||
}) => {
|
||||
export const PlaceholderRequestPane: FC = () => {
|
||||
const dispatch = useDispatch();
|
||||
const { hotKeyRegistry } = useSelector(selectSettings);
|
||||
const workspaceId = useSelector(selectActiveWorkspace)?._id;
|
||||
const handleImportFile = useCallback(() => dispatch(importFile({ workspaceId, forceToWorkspace: ForceToWorkspace.current })), [workspaceId, dispatch]);
|
||||
|
||||
const createHttpRequest = useCallback(() => {
|
||||
if (workspaceId) {
|
||||
createRequest({
|
||||
requestType: 'HTTP',
|
||||
parentId: workspaceId,
|
||||
workspaceId: workspaceId,
|
||||
});
|
||||
}
|
||||
}, [workspaceId]);
|
||||
|
||||
return (
|
||||
<Pane type="request">
|
||||
<PaneHeader />
|
||||
@@ -67,8 +72,8 @@ export const PlaceholderRequestPane: FC<Props> = ({
|
||||
<button className="btn inline-block btn--clicky" onClick={handleImportFile}>
|
||||
Import from File
|
||||
</button>
|
||||
<button className="btn inline-block btn--clicky" onClick={() => handleCreateRequest()}>
|
||||
New Request
|
||||
<button className="btn inline-block btn--clicky" onClick={createHttpRequest}>
|
||||
New HTTP Request
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -37,7 +37,6 @@ interface Props {
|
||||
forceRefreshCounter: number;
|
||||
forceUpdateRequest: (r: Request, patch: Partial<Request>) => Promise<Request>;
|
||||
forceUpdateRequestHeaders: (r: Request, headers: RequestHeader[]) => Promise<Request>;
|
||||
handleCreateRequest: () => void;
|
||||
handleGenerateCode: Function;
|
||||
handleImport: Function;
|
||||
handleSend: () => void;
|
||||
@@ -64,7 +63,6 @@ export const RequestPane: FC<Props> = ({
|
||||
forceRefreshCounter,
|
||||
forceUpdateRequest,
|
||||
forceUpdateRequestHeaders,
|
||||
handleCreateRequest,
|
||||
handleGenerateCode,
|
||||
handleImport,
|
||||
handleSend,
|
||||
@@ -145,9 +143,7 @@ export const RequestPane: FC<Props> = ({
|
||||
|
||||
if (!request) {
|
||||
return (
|
||||
<PlaceholderRequestPane
|
||||
handleCreateRequest={handleCreateRequest}
|
||||
/>
|
||||
<PlaceholderRequestPane />
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,8 +27,14 @@ export const targetCollect = (connect: DropTargetConnector, monitor: DropTargetM
|
||||
});
|
||||
|
||||
export const isAbove = (monitor: DropTargetMonitor, component: any) => {
|
||||
const hoveredNode = ReactDOM.findDOMNode(component);
|
||||
// @ts-expect-error -- TSCONVERSION
|
||||
let hoveredNode;
|
||||
try {
|
||||
// Try to find the node if it's a class component
|
||||
hoveredNode = ReactDOM.findDOMNode(component);
|
||||
} catch (error: unknown) {
|
||||
// Try to find the component if it's a function component
|
||||
hoveredNode = component.node;
|
||||
}
|
||||
const hoveredTop = hoveredNode.getBoundingClientRect().top;
|
||||
const draggedTop = monitor.getSourceClientOffset()?.y;
|
||||
return draggedTop && hoveredTop > draggedTop;
|
||||
|
||||
@@ -35,7 +35,6 @@ const mapStateToProps = (state: RootState) => ({
|
||||
|
||||
interface Props extends ReduxProps {
|
||||
handleActivateRequest: Function;
|
||||
handleCreateRequest: (id: string) => any;
|
||||
handleCreateRequestGroup: (parentId: string) => void;
|
||||
handleSetRequestPinned: Function;
|
||||
handleSetRequestGroupCollapsed: Function;
|
||||
@@ -53,7 +52,6 @@ class UnconnectedSidebarChildren extends PureComponent<Props> {
|
||||
_renderChildren(children: Child[], isInPinnedList: boolean) {
|
||||
const {
|
||||
filter,
|
||||
handleCreateRequest,
|
||||
handleCreateRequestGroup,
|
||||
handleSetRequestPinned,
|
||||
handleSetRequestGroupCollapsed,
|
||||
@@ -81,7 +79,6 @@ class UnconnectedSidebarChildren extends PureComponent<Props> {
|
||||
handleDuplicateRequest={handleDuplicateRequest}
|
||||
handleGenerateCode={handleGenerateCode}
|
||||
handleCopyAsCurl={handleCopyAsCurl}
|
||||
requestCreate={handleCreateRequest}
|
||||
isActive={child.doc._id === activeRequestId}
|
||||
isPinned={child.pinned}
|
||||
disableDragAndDrop={isInPinnedList}
|
||||
@@ -120,7 +117,6 @@ class UnconnectedSidebarChildren extends PureComponent<Props> {
|
||||
handleSetRequestGroupCollapsed={handleSetRequestGroupCollapsed}
|
||||
handleDuplicateRequestGroup={handleDuplicateRequestGroup}
|
||||
isCollapsed={child.collapsed}
|
||||
handleCreateRequest={handleCreateRequest}
|
||||
handleCreateRequestGroup={handleCreateRequestGroup}
|
||||
requestGroup={requestGroup}
|
||||
hotKeyRegistry={hotKeyRegistry}
|
||||
@@ -141,13 +137,6 @@ class UnconnectedSidebarChildren extends PureComponent<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
_handleCreateRequest() {
|
||||
const { handleCreateRequest, workspace } = this.props;
|
||||
if (workspace) {
|
||||
handleCreateRequest(workspace._id);
|
||||
}
|
||||
}
|
||||
|
||||
_handleCreateRequestGroup() {
|
||||
const { handleCreateRequestGroup, workspace } = this.props;
|
||||
if (workspace) {
|
||||
@@ -161,7 +150,6 @@ class UnconnectedSidebarChildren extends PureComponent<Props> {
|
||||
const contextMenuPortal = ReactDOM.createPortal(
|
||||
<div className="hide">
|
||||
<SidebarCreateDropdown
|
||||
handleCreateRequest={this._handleCreateRequest}
|
||||
handleCreateRequestGroup={this._handleCreateRequestGroup}
|
||||
hotKeyRegistry={hotKeyRegistry}
|
||||
/>
|
||||
|
||||
@@ -1,29 +1,38 @@
|
||||
import { HotKeyRegistry } from 'insomnia-common';
|
||||
import React, { FC, useCallback } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { hotKeyRefs } from '../../../common/hotkeys';
|
||||
import { RequestGroup } from '../../../models/request-group';
|
||||
import { createRequest, CreateRequestType } from '../../hooks/create-request';
|
||||
import { selectActiveWorkspace } from '../../redux/selectors';
|
||||
import { Dropdown } from '../base/dropdown/dropdown';
|
||||
import { DropdownButton } from '../base/dropdown/dropdown-button';
|
||||
import { DropdownHint } from '../base/dropdown/dropdown-hint';
|
||||
import { DropdownItem } from '../base/dropdown/dropdown-item';
|
||||
|
||||
interface Props {
|
||||
handleCreateRequest: (id: string) => any;
|
||||
handleCreateRequestGroup: (requestGroup: RequestGroup) => any;
|
||||
hotKeyRegistry: HotKeyRegistry;
|
||||
right?: boolean;
|
||||
}
|
||||
|
||||
export const SidebarCreateDropdown: FC<Props> = ({
|
||||
handleCreateRequest,
|
||||
handleCreateRequestGroup,
|
||||
hotKeyRegistry,
|
||||
right,
|
||||
}) => {
|
||||
const create = useCallback((value: string) => {
|
||||
handleCreateRequest(value);
|
||||
}, [handleCreateRequest]);
|
||||
const activeWorkspace = useSelector(selectActiveWorkspace);
|
||||
const activeWorkspaceId = activeWorkspace?._id;
|
||||
const create = useCallback((value: CreateRequestType) => {
|
||||
if (activeWorkspaceId) {
|
||||
createRequest({
|
||||
requestType: value,
|
||||
parentId: activeWorkspaceId,
|
||||
workspaceId: activeWorkspaceId,
|
||||
});
|
||||
}
|
||||
}, [activeWorkspaceId]);
|
||||
|
||||
return (
|
||||
<Dropdown right={right}>
|
||||
|
||||
@@ -11,7 +11,6 @@ import { SidebarSortDropdown } from './sidebar-sort-dropdown';
|
||||
|
||||
interface Props {
|
||||
onChange: (value: string) => Promise<void>;
|
||||
requestCreate: (requestType?: string) => void;
|
||||
requestGroupCreate: () => void;
|
||||
sidebarSort: (sortOrder: SortOrder) => void;
|
||||
filter: string;
|
||||
@@ -51,10 +50,6 @@ export class SidebarFilter extends PureComponent<Props> {
|
||||
this.props.requestGroupCreate();
|
||||
}
|
||||
|
||||
_handleRequestCreate(requestType?: string) {
|
||||
this.props.requestCreate(requestType);
|
||||
}
|
||||
|
||||
_handleKeydown(event: KeyboardEvent) {
|
||||
executeHotKey(event, hotKeyRefs.SIDEBAR_FOCUS_FILTER, () => {
|
||||
this._input?.focus();
|
||||
@@ -82,7 +77,6 @@ export class SidebarFilter extends PureComponent<Props> {
|
||||
</div>
|
||||
<SidebarSortDropdown handleSort={sidebarSort} />
|
||||
<SidebarCreateDropdown
|
||||
handleCreateRequest={this._handleRequestCreate}
|
||||
handleCreateRequestGroup={this._handleRequestGroupCreate}
|
||||
hotKeyRegistry={hotKeyRegistry}
|
||||
/>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { autoBindMethodsForReact } from 'class-autobind-decorator';
|
||||
import classnames from 'classnames';
|
||||
import { HotKeyRegistry } from 'insomnia-common';
|
||||
import { noop } from 'ramda-adjunct';
|
||||
import React, { PureComponent } from 'react';
|
||||
import React, { ElementRef, MouseEvent, PureComponent } from 'react';
|
||||
import { PropsWithChildren } from 'react';
|
||||
import { createRef } from 'react';
|
||||
import { DragSource, DragSourceSpec, DropTarget, DropTargetMonitor, DropTargetSpec } from 'react-dnd';
|
||||
@@ -13,7 +13,7 @@ import { RequestGroup } from '../../../models/request-group';
|
||||
import { RootState } from '../../redux/modules';
|
||||
import { selectActiveEnvironment, selectActiveRequest } from '../../redux/selectors';
|
||||
import { Highlight } from '../base/highlight';
|
||||
import { RequestGroupActionsDropdown, UnconnectedRequestGroupActionsDropdown } from '../dropdowns/request-group-actions-dropdown';
|
||||
import { RequestGroupActionsDropdown } from '../dropdowns/request-group-actions-dropdown';
|
||||
import { showModal } from '../modals';
|
||||
import { RequestGroupSettingsModal } from '../modals/request-group-settings-modal';
|
||||
import { DnDDragProps, DnDDropProps, DnDProps, DragObject, dropHandleCreator, hoverHandleCreator, sourceCollect, targetCollect } from './dnd';
|
||||
@@ -30,7 +30,6 @@ interface Props extends DnDProps, ReduxProps, PropsWithChildren<{}> {
|
||||
handleSetRequestGroupCollapsed: Function;
|
||||
handleDuplicateRequestGroup: (requestGroup: RequestGroup) => any;
|
||||
handleActivateRequest: Function;
|
||||
handleCreateRequest: (id: string) => any;
|
||||
handleCreateRequestGroup: (requestGroup: string) => any;
|
||||
filter: string;
|
||||
isActive: boolean;
|
||||
@@ -49,7 +48,7 @@ class UnconnectedSidebarRequestGroupRow extends PureComponent<Props, State> {
|
||||
dragDirection: 0,
|
||||
};
|
||||
|
||||
private dropdownRef = createRef<UnconnectedRequestGroupActionsDropdown>();
|
||||
private dropdownRef = createRef<ElementRef<typeof RequestGroupActionsDropdown>>();
|
||||
private expandTagRef = createRef<HTMLDivElement>();
|
||||
|
||||
getExpandTag() {
|
||||
@@ -61,7 +60,7 @@ class UnconnectedSidebarRequestGroupRow extends PureComponent<Props, State> {
|
||||
handleSetRequestGroupCollapsed(requestGroup._id, !isCollapsed);
|
||||
}
|
||||
|
||||
_handleShowActions(event) {
|
||||
_handleShowActions(event: MouseEvent<HTMLButtonElement>) {
|
||||
event.preventDefault();
|
||||
|
||||
this.dropdownRef.current?.show();
|
||||
@@ -90,7 +89,6 @@ class UnconnectedSidebarRequestGroupRow extends PureComponent<Props, State> {
|
||||
requestGroup,
|
||||
isCollapsed,
|
||||
isActive,
|
||||
handleCreateRequest,
|
||||
handleCreateRequestGroup,
|
||||
handleDuplicateRequestGroup,
|
||||
isDragging,
|
||||
@@ -145,7 +143,6 @@ class UnconnectedSidebarRequestGroupRow extends PureComponent<Props, State> {
|
||||
<div className="sidebar__actions">
|
||||
<RequestGroupActionsDropdown
|
||||
ref={this.dropdownRef}
|
||||
handleCreateRequest={handleCreateRequest}
|
||||
handleCreateRequestGroup={handleCreateRequestGroup}
|
||||
handleDuplicateRequestGroup={handleDuplicateRequestGroup}
|
||||
handleShowSettings={this._handleShowRequestGroupSettings}
|
||||
@@ -172,7 +169,6 @@ class UnconnectedSidebarRequestGroupRow extends PureComponent<Props, State> {
|
||||
handleSetRequestPinned={noop}
|
||||
isActive={false}
|
||||
requestGroup={requestGroup}
|
||||
requestCreate={handleCreateRequest}
|
||||
filter={filter}
|
||||
hotKeyRegistry={hotKeyRegistry}
|
||||
isPinned={false} // Necessary so that plugin actions work
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { autoBindMethodsForReact } from 'class-autobind-decorator';
|
||||
import classnames from 'classnames';
|
||||
import { HotKeyRegistry } from 'insomnia-common';
|
||||
import React, { FC, PureComponent } from 'react';
|
||||
import React, { FC, forwardRef, MouseEvent, ReactElement, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react';
|
||||
import { DragSource, DragSourceSpec, DropTarget, DropTargetSpec } from 'react-dnd';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { AUTOBIND_CFG, CONTENT_TYPE_GRAPHQL } from '../../../common/constants';
|
||||
import { CONTENT_TYPE_GRAPHQL } from '../../../common/constants';
|
||||
import { getMethodOverrideHeader } from '../../../common/misc';
|
||||
import { GrpcRequest, isGrpcRequest } from '../../../models/grpc-request';
|
||||
import * as requestOperations from '../../../models/helpers/request-operations';
|
||||
import { Request } from '../../../models/request';
|
||||
import { RequestGroup } from '../../../models/request-group';
|
||||
import { useNunjucks } from '../../context/nunjucks/use-nunjucks';
|
||||
import { selectActiveEnvironment, selectActiveProject } from '../../redux/selectors';
|
||||
import { createRequest } from '../../hooks/create-request';
|
||||
import { selectActiveEnvironment, selectActiveProject, selectActiveWorkspace } from '../../redux/selectors';
|
||||
import { Editable } from '../base/editable';
|
||||
import { Highlight } from '../base/highlight';
|
||||
import { RequestActionsDropdown } from '../dropdowns/request-actions-dropdown';
|
||||
@@ -23,15 +23,12 @@ import { GrpcTag } from '../tags/grpc-tag';
|
||||
import { MethodTag } from '../tags/method-tag';
|
||||
import { DnDProps, DragObject, dropHandleCreator, hoverHandleCreator, sourceCollect, targetCollect } from './dnd';
|
||||
|
||||
type DerivedProps = ReturnType<typeof useDerivedProps>;
|
||||
|
||||
interface RawProps {
|
||||
handleActivateRequest: Function;
|
||||
handleSetRequestPinned: Function;
|
||||
handleDuplicateRequest: Function;
|
||||
handleGenerateCode: Function;
|
||||
handleCopyAsCurl: Function;
|
||||
requestCreate: Function;
|
||||
filter: string;
|
||||
isActive: boolean;
|
||||
isPinned: boolean;
|
||||
@@ -42,307 +39,255 @@ interface RawProps {
|
||||
disableDragAndDrop?: boolean;
|
||||
}
|
||||
|
||||
type Props = RawProps & DnDProps & DerivedProps;
|
||||
|
||||
interface State {
|
||||
dragDirection: number;
|
||||
isEditing: boolean;
|
||||
renderedUrl: string;
|
||||
}
|
||||
|
||||
@autoBindMethodsForReact(AUTOBIND_CFG)
|
||||
class UnconnectedSidebarRequestRow extends PureComponent<Props, State> {
|
||||
state: State = {
|
||||
dragDirection: 0,
|
||||
isEditing: false,
|
||||
renderedUrl: '',
|
||||
};
|
||||
|
||||
_urlUpdateInterval: NodeJS.Timeout | null = null;
|
||||
_requestActionsDropdown: RequestActionsDropdown | null = null;
|
||||
|
||||
_setRequestActionsDropdownRef(requestActionsDropdown: RequestActionsDropdown) {
|
||||
this._requestActionsDropdown = requestActionsDropdown;
|
||||
}
|
||||
|
||||
_handleShowRequestActions(event) {
|
||||
event.preventDefault();
|
||||
|
||||
this._requestActionsDropdown?.show();
|
||||
}
|
||||
|
||||
_handleEditStart() {
|
||||
this.setState({
|
||||
isEditing: true,
|
||||
});
|
||||
}
|
||||
|
||||
async _handleRequestUpdateName(name) {
|
||||
const { request } = this.props;
|
||||
const patch = {
|
||||
name,
|
||||
};
|
||||
// @ts-expect-error -- TSCONVERSION skip this if request is undefined
|
||||
await requestOperations.update(request, patch);
|
||||
this.setState({
|
||||
isEditing: false,
|
||||
});
|
||||
}
|
||||
|
||||
_handleRequestCreateFromEmpty() {
|
||||
const parentId = this.props.requestGroup?._id;
|
||||
this.props.requestCreate(parentId);
|
||||
}
|
||||
|
||||
_handleRequestActivate() {
|
||||
const { isActive, request, handleActivateRequest } = this.props;
|
||||
|
||||
if (isActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-expect-error -- TSCONVERSION skip this if request is undefined
|
||||
handleActivateRequest(request._id);
|
||||
}
|
||||
|
||||
_handleShowRequestSettings() {
|
||||
showModal(RequestSettingsModal, {
|
||||
request: this.props.request,
|
||||
});
|
||||
}
|
||||
|
||||
_getMethodOverrideHeaderValue() {
|
||||
const { request } = this.props;
|
||||
// @ts-expect-error -- TSCONVERSION skip this if request is undefined or grpc
|
||||
const header = getMethodOverrideHeader(request.headers);
|
||||
|
||||
if (header) {
|
||||
return header.value;
|
||||
}
|
||||
|
||||
// If no override, use GraphQL as override if it's a gql request
|
||||
// @ts-expect-error -- TSCONVERSION skip this if request is undefined or grpc
|
||||
if (request.body && request.body.mimeType === CONTENT_TYPE_GRAPHQL) {
|
||||
return 'GQL';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async _debouncedUpdateRenderedUrl(props: Props) {
|
||||
if (this._urlUpdateInterval !== null) {
|
||||
clearTimeout(this._urlUpdateInterval);
|
||||
}
|
||||
this._urlUpdateInterval = setTimeout(() => {
|
||||
this._updateRenderedUrl(props);
|
||||
}, 300);
|
||||
}
|
||||
|
||||
async _updateRenderedUrl(props: Props) {
|
||||
let renderedUrl;
|
||||
|
||||
try {
|
||||
// @ts-expect-error -- TSCONVERSION skip this if request is undefined or grpc
|
||||
renderedUrl = await props.handleRender(props.request.url);
|
||||
} catch (error) {
|
||||
// Certain things, such as invalid variable tags and Prompts
|
||||
// without titles will result in a failure to parse. Can't do
|
||||
// much else, so let's just give them the unrendered URL
|
||||
// @ts-expect-error -- TSCONVERSION skip this if request is undefined
|
||||
renderedUrl = props.request.url;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
renderedUrl,
|
||||
});
|
||||
}
|
||||
|
||||
setDragDirection(dragDirection) {
|
||||
if (dragDirection !== this.state.dragDirection) {
|
||||
this.setState({
|
||||
dragDirection,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { request } = this.props;
|
||||
|
||||
if (request && !request.name) {
|
||||
this._debouncedUpdateRenderedUrl(this.props);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
UNSAFE_componentWillUpdate(nextProps) {
|
||||
if (!nextProps.request) {
|
||||
return;
|
||||
}
|
||||
|
||||
const requestUrl = this.props.request ? this.props.request.url : '';
|
||||
|
||||
if (nextProps.request.url !== requestUrl) {
|
||||
this._debouncedUpdateRenderedUrl(nextProps);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this._urlUpdateInterval !== null) {
|
||||
clearTimeout(this._urlUpdateInterval);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
activeEnvironment,
|
||||
connectDragSource,
|
||||
connectDropTarget,
|
||||
disableDragAndDrop,
|
||||
filter,
|
||||
handleCopyAsCurl,
|
||||
handleDuplicateRequest,
|
||||
handleGenerateCode,
|
||||
handleSetRequestPinned,
|
||||
hotKeyRegistry,
|
||||
isActive,
|
||||
isDragging,
|
||||
isDraggingOver,
|
||||
isPinned,
|
||||
request,
|
||||
requestGroup,
|
||||
activeProject,
|
||||
} = this.props;
|
||||
const { dragDirection } = this.state;
|
||||
let node;
|
||||
const classes = classnames('sidebar__row', {
|
||||
'sidebar__row--dragging': isDragging,
|
||||
'sidebar__row--dragging-above': isDraggingOver && dragDirection > 0,
|
||||
'sidebar__row--dragging-below': isDraggingOver && dragDirection < 0,
|
||||
});
|
||||
|
||||
if (!request) {
|
||||
node = (
|
||||
<li className={classes}>
|
||||
<div className="sidebar__item">
|
||||
<button className="sidebar__clickable" onClick={this._handleRequestCreateFromEmpty}>
|
||||
<em className="faded">click to add first request...</em>
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
} else {
|
||||
const methodTag =
|
||||
isGrpcRequest(request) ? (
|
||||
<GrpcTag />
|
||||
) : (
|
||||
<MethodTag method={request.method} override={this._getMethodOverrideHeaderValue()} />
|
||||
);
|
||||
node = (
|
||||
<li className={classes}>
|
||||
<div
|
||||
className={classnames('sidebar__item', 'sidebar__item--request', {
|
||||
'sidebar__item--active': isActive,
|
||||
})}
|
||||
>
|
||||
<button
|
||||
className="wide"
|
||||
onClick={this._handleRequestActivate}
|
||||
onContextMenu={this._handleShowRequestActions}
|
||||
>
|
||||
<div className="sidebar__clickable">
|
||||
{methodTag}
|
||||
<Editable
|
||||
value={request.name}
|
||||
fallbackValue={this.state.renderedUrl}
|
||||
blankValue="Empty"
|
||||
className="inline-block"
|
||||
onEditStart={this._handleEditStart}
|
||||
onSubmit={this._handleRequestUpdateName}
|
||||
renderReadView={(value, props) => (
|
||||
<Highlight
|
||||
search={filter}
|
||||
text={value}
|
||||
{...props}
|
||||
title={`${request.name}\n${props.title}`}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<GrpcSpinner requestId={request._id} className="margin-right-sm" />
|
||||
</div>
|
||||
</button>
|
||||
<div className="sidebar__actions">
|
||||
<RequestActionsDropdown
|
||||
right
|
||||
ref={this._setRequestActionsDropdownRef}
|
||||
handleDuplicateRequest={handleDuplicateRequest}
|
||||
handleSetRequestPinned={handleSetRequestPinned}
|
||||
handleGenerateCode={handleGenerateCode}
|
||||
handleCopyAsCurl={handleCopyAsCurl}
|
||||
handleShowSettings={this._handleShowRequestSettings}
|
||||
request={request}
|
||||
isPinned={isPinned}
|
||||
requestGroup={requestGroup}
|
||||
hotKeyRegistry={hotKeyRegistry} // Necessary for plugin actions to have network capabilities
|
||||
activeEnvironment={activeEnvironment}
|
||||
activeProject={activeProject}
|
||||
/>
|
||||
</div>
|
||||
{isPinned && (
|
||||
<div className="sidebar__item__icon-pin">
|
||||
<i className="fa fa-thumb-tack" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
if (disableDragAndDrop) {
|
||||
return node;
|
||||
} else if (!this.state.isEditing) {
|
||||
return connectDragSource(connectDropTarget(node));
|
||||
} else {
|
||||
return connectDropTarget(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
type Props = RawProps & DnDProps;
|
||||
|
||||
const dragSource: DragSourceSpec<Props, DragObject> = {
|
||||
beginDrag(props) {
|
||||
beginDrag({ request }) {
|
||||
return {
|
||||
item: props.request,
|
||||
item: request,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
const dropHandle = dropHandleCreator<Props>({
|
||||
getParentId: props => props.requestGroup?._id || props.request?.parentId,
|
||||
getTargetId: props => props.request?._id,
|
||||
});
|
||||
|
||||
const hoverHandle = hoverHandleCreator<Props>();
|
||||
|
||||
const dragTarget: DropTargetSpec<Props> = {
|
||||
drop: dropHandle,
|
||||
hover: hoverHandle,
|
||||
drop: dropHandleCreator<Props>({
|
||||
getParentId: props => props.requestGroup?._id || props.request?.parentId,
|
||||
getTargetId: props => props.request?._id,
|
||||
}),
|
||||
hover: hoverHandleCreator<Props>(),
|
||||
};
|
||||
|
||||
const source = DragSource('SIDEBAR_REQUEST_ROW', dragSource, sourceCollect)(UnconnectedSidebarRequestRow);
|
||||
const Target = DropTarget('SIDEBAR_REQUEST_ROW', dragTarget, targetCollect)(source);
|
||||
|
||||
const useDerivedProps = () => {
|
||||
export const _SidebarRequestRow: FC<Props> = forwardRef(({
|
||||
connectDragSource,
|
||||
connectDropTarget,
|
||||
disableDragAndDrop,
|
||||
filter,
|
||||
handleActivateRequest,
|
||||
handleCopyAsCurl,
|
||||
handleDuplicateRequest,
|
||||
handleGenerateCode,
|
||||
handleSetRequestPinned,
|
||||
hotKeyRegistry,
|
||||
isActive,
|
||||
isDragging,
|
||||
isDraggingOver,
|
||||
isPinned,
|
||||
request,
|
||||
requestGroup,
|
||||
}, ref) => {
|
||||
const { handleRender } = useNunjucks();
|
||||
const activeProject = useSelector(selectActiveProject);
|
||||
const activeEnvironment = useSelector(selectActiveEnvironment);
|
||||
const activeWorkspace = useSelector(selectActiveWorkspace);
|
||||
const activeWorkspaceId = activeWorkspace?._id;
|
||||
const [dragDirection, setDragDirection] = useState(0);
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
|
||||
return {
|
||||
handleRender,
|
||||
activeProject,
|
||||
activeEnvironment,
|
||||
};
|
||||
};
|
||||
const nodeRef = useRef<HTMLLIElement>(null);
|
||||
useImperativeHandle(ref, () => ({
|
||||
setDragDirection,
|
||||
node: nodeRef.current,
|
||||
}));
|
||||
|
||||
export const SidebarRequestRow: FC<RawProps> = props => {
|
||||
const derivedProps = useDerivedProps();
|
||||
return <Target {...props} {...derivedProps} />;
|
||||
};
|
||||
const startEditing = useCallback(() => {
|
||||
setIsEditing(true);
|
||||
}, []);
|
||||
|
||||
const stopEditing = useCallback(() => {
|
||||
setIsEditing(false);
|
||||
}, []);
|
||||
|
||||
const [renderedUrl, setRenderedUrl] = useState('');
|
||||
|
||||
const requestActionsDropdown = useRef<RequestActionsDropdown | null>(null);
|
||||
|
||||
const handleShowRequestActions = useCallback((event: MouseEvent<HTMLButtonElement>) => {
|
||||
event.preventDefault();
|
||||
|
||||
requestActionsDropdown.current?.show();
|
||||
}, [requestActionsDropdown]);
|
||||
|
||||
const handleRequestUpdateName = useCallback((name: string) => {
|
||||
if (!request) {
|
||||
return;
|
||||
}
|
||||
|
||||
requestOperations.update(request, { name }).then(() => {
|
||||
stopEditing();
|
||||
});
|
||||
}, [request, stopEditing]);
|
||||
|
||||
const handleRequestCreateFromEmpty = useCallback(() => {
|
||||
if (!requestGroup?._id || !activeWorkspaceId) {
|
||||
return;
|
||||
}
|
||||
createRequest({
|
||||
requestType: 'HTTP',
|
||||
parentId: requestGroup?._id,
|
||||
workspaceId: activeWorkspaceId,
|
||||
});
|
||||
}, [requestGroup?._id, activeWorkspaceId]);
|
||||
|
||||
const handleRequestActivate = useCallback(() => {
|
||||
if (isActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
handleActivateRequest(request?._id);
|
||||
}, [isActive, request?._id, handleActivateRequest]);
|
||||
|
||||
const handleShowRequestSettings = useCallback(() => {
|
||||
showModal(RequestSettingsModal, { request });
|
||||
}, [request]);
|
||||
|
||||
const [methodOverrideValue, setMethodOverrideValue] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!request) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isGrpcRequest(request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const header = getMethodOverrideHeader(request.headers);
|
||||
if (header) {
|
||||
setMethodOverrideValue(header.value);
|
||||
return;
|
||||
}
|
||||
|
||||
// If no override, use GraphQL as override if it's a GraphQL request
|
||||
if (request.body && request.body.mimeType === CONTENT_TYPE_GRAPHQL) {
|
||||
setMethodOverrideValue('GQL');
|
||||
return;
|
||||
}
|
||||
|
||||
setMethodOverrideValue(null);
|
||||
return;
|
||||
}, [request]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!request) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isGrpcRequest(request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.name) {
|
||||
setRenderedUrl(request.name);
|
||||
return;
|
||||
}
|
||||
|
||||
handleRender(request.url)
|
||||
.then(requestUrl => {
|
||||
setRenderedUrl(requestUrl);
|
||||
})
|
||||
.catch(() => {
|
||||
// Certain things, such as invalid variable tags and Prompts
|
||||
// without titles will result in a failure to parse. Can't do
|
||||
// much else, so let's just give them the unrendered URL
|
||||
setRenderedUrl(request.url);
|
||||
});
|
||||
|
||||
}, [handleRender, request, request?.url]);
|
||||
|
||||
let node: ReactElement<HTMLLIElement> | null = null;
|
||||
const classes = classnames('sidebar__row', {
|
||||
'sidebar__row--dragging': isDragging,
|
||||
'sidebar__row--dragging-above': isDraggingOver && dragDirection > 0,
|
||||
'sidebar__row--dragging-below': isDraggingOver && dragDirection < 0,
|
||||
});
|
||||
|
||||
if (!request) {
|
||||
node = (
|
||||
<li ref={nodeRef} className={classes}>
|
||||
<div className="sidebar__item">
|
||||
<button className="sidebar__clickable" onClick={handleRequestCreateFromEmpty}>
|
||||
<em className="faded">click to add first request...</em>
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
} else {
|
||||
const methodTag =
|
||||
isGrpcRequest(request) ? (
|
||||
<GrpcTag />
|
||||
) : (
|
||||
<MethodTag method={request.method} override={methodOverrideValue} />
|
||||
);
|
||||
node = (
|
||||
<li ref={nodeRef} className={classes}>
|
||||
<div
|
||||
className={classnames('sidebar__item', 'sidebar__item--request', {
|
||||
'sidebar__item--active': isActive,
|
||||
})}
|
||||
>
|
||||
<button
|
||||
className="wide"
|
||||
onClick={handleRequestActivate}
|
||||
onContextMenu={handleShowRequestActions}
|
||||
>
|
||||
<div className="sidebar__clickable">
|
||||
{methodTag}
|
||||
<Editable
|
||||
value={request.name}
|
||||
fallbackValue={renderedUrl}
|
||||
blankValue="Empty"
|
||||
className="inline-block"
|
||||
onEditStart={startEditing}
|
||||
onSubmit={handleRequestUpdateName}
|
||||
renderReadView={(value, props) => (
|
||||
<Highlight
|
||||
search={filter}
|
||||
text={value}
|
||||
{...props}
|
||||
title={`${request.name}\n${props.title}`}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<GrpcSpinner requestId={request._id} className="margin-right-sm" />
|
||||
</div>
|
||||
</button>
|
||||
<div className="sidebar__actions">
|
||||
<RequestActionsDropdown
|
||||
right
|
||||
ref={requestActionsDropdown}
|
||||
handleDuplicateRequest={handleDuplicateRequest}
|
||||
handleSetRequestPinned={handleSetRequestPinned}
|
||||
handleGenerateCode={handleGenerateCode}
|
||||
handleCopyAsCurl={handleCopyAsCurl}
|
||||
handleShowSettings={handleShowRequestSettings}
|
||||
request={request}
|
||||
isPinned={isPinned}
|
||||
requestGroup={requestGroup}
|
||||
hotKeyRegistry={hotKeyRegistry} // Necessary for plugin actions to have network capabilities
|
||||
activeEnvironment={activeEnvironment}
|
||||
activeProject={activeProject}
|
||||
/>
|
||||
</div>
|
||||
{isPinned && (
|
||||
<div className="sidebar__item__icon-pin">
|
||||
<i className="fa fa-thumb-tack" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
if (disableDragAndDrop) {
|
||||
return node;
|
||||
} else if (!isEditing) {
|
||||
return connectDragSource(connectDropTarget(node));
|
||||
} else {
|
||||
return connectDropTarget(node);
|
||||
}
|
||||
});
|
||||
|
||||
_SidebarRequestRow.displayName = 'SidebarRequestRow';
|
||||
|
||||
const source = DragSource('SIDEBAR_REQUEST_ROW', dragSource, sourceCollect)(_SidebarRequestRow);
|
||||
export const SidebarRequestRow = DropTarget('SIDEBAR_REQUEST_ROW', dragTarget, targetCollect)(source);
|
||||
@@ -35,7 +35,6 @@ interface Props extends ReturnType<typeof mapStateToProps> {
|
||||
handleForceUpdateRequest: (r: Request, patch: Partial<Request>) => Promise<Request>;
|
||||
handleForceUpdateRequestHeaders: (r: Request, headers: RequestHeader[]) => Promise<Request>;
|
||||
handleImport: Function;
|
||||
handleRequestCreate: () => void;
|
||||
handleRequestGroupCreate: () => void;
|
||||
handleSendAndDownloadRequestWithActiveEnvironment: (filepath?: string) => Promise<void>;
|
||||
handleSendRequestWithActiveEnvironment: () => void;
|
||||
@@ -101,7 +100,6 @@ class UnconnectedWrapperDebug extends PureComponent<Props> {
|
||||
activeWorkspace,
|
||||
environments,
|
||||
handleChangeEnvironment,
|
||||
handleRequestCreate,
|
||||
handleRequestGroupCreate,
|
||||
handleSidebarSort,
|
||||
settings,
|
||||
@@ -111,7 +109,6 @@ class UnconnectedWrapperDebug extends PureComponent<Props> {
|
||||
const {
|
||||
handleActivateRequest,
|
||||
handleCopyAsCurl,
|
||||
handleCreateRequest,
|
||||
handleCreateRequestGroup,
|
||||
handleDuplicateRequest,
|
||||
handleDuplicateRequestGroup,
|
||||
@@ -146,7 +143,6 @@ class UnconnectedWrapperDebug extends PureComponent<Props> {
|
||||
<SidebarFilter
|
||||
key={`${activeWorkspace._id}::filter`}
|
||||
onChange={handleSetSidebarFilter}
|
||||
requestCreate={handleRequestCreate}
|
||||
requestGroupCreate={handleRequestGroupCreate}
|
||||
sidebarSort={handleSidebarSort}
|
||||
filter={sidebarFilter || ''}
|
||||
@@ -156,7 +152,6 @@ class UnconnectedWrapperDebug extends PureComponent<Props> {
|
||||
<SidebarChildren
|
||||
childObjects={sidebarChildren}
|
||||
handleActivateRequest={handleActivateRequest}
|
||||
handleCreateRequest={handleCreateRequest}
|
||||
handleCreateRequestGroup={handleCreateRequestGroup}
|
||||
handleSetRequestGroupCollapsed={handleSetRequestGroupCollapsed}
|
||||
handleSetRequestPinned={handleSetRequestPinned}
|
||||
@@ -194,7 +189,6 @@ class UnconnectedWrapperDebug extends PureComponent<Props> {
|
||||
settings,
|
||||
} = this.props;
|
||||
const {
|
||||
handleCreateRequestForWorkspace,
|
||||
handleGenerateCodeForActiveRequest,
|
||||
handleUpdateDownloadPath,
|
||||
handleUpdateRequestMimeType,
|
||||
@@ -229,7 +223,6 @@ class UnconnectedWrapperDebug extends PureComponent<Props> {
|
||||
forceRefreshCounter={forceRefreshKey}
|
||||
forceUpdateRequest={handleForceUpdateRequest}
|
||||
forceUpdateRequestHeaders={handleForceUpdateRequestHeaders}
|
||||
handleCreateRequest={handleCreateRequestForWorkspace}
|
||||
handleGenerateCode={handleGenerateCodeForActiveRequest}
|
||||
handleImport={handleImport}
|
||||
handleSend={handleSendRequestWithActiveEnvironment}
|
||||
|
||||
@@ -128,14 +128,12 @@ export type WrapperProps = AppProps & {
|
||||
handleSetSidebarFilter: (value: string) => Promise<void>;
|
||||
handleShowSettingsModal: Function;
|
||||
handleSetActiveEnvironment: (environmentId: string | null) => Promise<void>;
|
||||
handleCreateRequest: (id: string, requestType?: string) => void;
|
||||
handleDuplicateRequest: Function;
|
||||
handleDuplicateRequestGroup: (requestGroup: RequestGroup) => void;
|
||||
handleCreateRequestGroup: (parentId: string) => void;
|
||||
handleGenerateCodeForActiveRequest: Function;
|
||||
handleGenerateCode: Function;
|
||||
handleCopyAsCurl: Function;
|
||||
handleCreateRequestForWorkspace: (requestType?: string) => void;
|
||||
requestPaneRef: Ref<HTMLElement>;
|
||||
responsePaneRef: Ref<HTMLElement>;
|
||||
handleSetResponsePreviewMode: Function;
|
||||
@@ -434,16 +432,6 @@ export class Wrapper extends PureComponent<WrapperProps, State> {
|
||||
this.props.handleSetResponseFilter(activeRequestId, filter);
|
||||
}
|
||||
|
||||
_handleCreateRequestInWorkspace(requestType?: string) {
|
||||
const { activeWorkspace, handleCreateRequest } = this.props;
|
||||
|
||||
if (!activeWorkspace) {
|
||||
return;
|
||||
}
|
||||
|
||||
handleCreateRequest(activeWorkspace._id, requestType);
|
||||
}
|
||||
|
||||
_handleCreateRequestGroupInWorkspace() {
|
||||
const { activeWorkspace, handleCreateRequestGroup } = this.props;
|
||||
|
||||
@@ -680,45 +668,24 @@ export class Wrapper extends PureComponent<WrapperProps, State> {
|
||||
handleDeleteResponse={this._handleDeleteResponse}
|
||||
handleDeleteResponses={this._handleDeleteResponses}
|
||||
handleForceUpdateRequest={this._handleForceUpdateRequest}
|
||||
handleForceUpdateRequestHeaders={
|
||||
this._handleForceUpdateRequestHeaders
|
||||
}
|
||||
handleForceUpdateRequestHeaders={this._handleForceUpdateRequestHeaders}
|
||||
handleImport={this._handleImport}
|
||||
handleRequestCreate={this._handleCreateRequestInWorkspace}
|
||||
handleRequestGroupCreate={
|
||||
this._handleCreateRequestGroupInWorkspace
|
||||
}
|
||||
handleSendAndDownloadRequestWithActiveEnvironment={
|
||||
this._handleSendAndDownloadRequestWithActiveEnvironment
|
||||
}
|
||||
handleSendRequestWithActiveEnvironment={
|
||||
this._handleSendRequestWithActiveEnvironment
|
||||
}
|
||||
handleRequestGroupCreate={this._handleCreateRequestGroupInWorkspace}
|
||||
handleSendAndDownloadRequestWithActiveEnvironment={this._handleSendAndDownloadRequestWithActiveEnvironment}
|
||||
handleSendRequestWithActiveEnvironment={this._handleSendRequestWithActiveEnvironment}
|
||||
handleSetActiveResponse={this._handleSetActiveResponse}
|
||||
handleSetPreviewMode={this._handleSetPreviewMode}
|
||||
handleSetResponseFilter={this._handleSetResponseFilter}
|
||||
handleShowRequestSettingsModal={
|
||||
this._handleShowRequestSettingsModal
|
||||
}
|
||||
handleShowRequestSettingsModal={this._handleShowRequestSettingsModal}
|
||||
handleSidebarSort={handleSidebarSort}
|
||||
handleUpdateRequestAuthentication={
|
||||
Wrapper._handleUpdateRequestAuthentication
|
||||
}
|
||||
handleUpdateRequestAuthentication={Wrapper._handleUpdateRequestAuthentication}
|
||||
handleUpdateRequestBody={Wrapper._handleUpdateRequestBody}
|
||||
handleUpdateRequestHeaders={
|
||||
Wrapper._handleUpdateRequestHeaders
|
||||
}
|
||||
handleUpdateRequestHeaders={Wrapper._handleUpdateRequestHeaders}
|
||||
handleUpdateRequestMethod={Wrapper._handleUpdateRequestMethod}
|
||||
handleUpdateRequestParameters={
|
||||
Wrapper._handleUpdateRequestParameters
|
||||
}
|
||||
handleUpdateRequestParameters={Wrapper._handleUpdateRequestParameters}
|
||||
handleUpdateRequestUrl={Wrapper._handleUpdateRequestUrl}
|
||||
handleUpdateSettingsUseBulkHeaderEditor={
|
||||
this._handleUpdateSettingsUseBulkHeaderEditor
|
||||
}
|
||||
handleUpdateSettingsUseBulkParametersEditor={
|
||||
this._handleUpdateSettingsUseBulkParametersEditor
|
||||
}
|
||||
handleUpdateSettingsUseBulkHeaderEditor={this._handleUpdateSettingsUseBulkHeaderEditor}
|
||||
handleUpdateSettingsUseBulkParametersEditor={this._handleUpdateSettingsUseBulkParametersEditor}
|
||||
wrapperProps={this.props}
|
||||
/>
|
||||
</Suspense>
|
||||
|
||||
@@ -14,8 +14,6 @@ import {
|
||||
ACTIVITY_HOME,
|
||||
AUTOBIND_CFG,
|
||||
COLLAPSE_SIDEBAR_REMS,
|
||||
CONTENT_TYPE_GRAPHQL,
|
||||
CONTENT_TYPE_JSON,
|
||||
DEFAULT_PANE_HEIGHT,
|
||||
DEFAULT_PANE_WIDTH,
|
||||
DEFAULT_SIDEBAR_WIDTH,
|
||||
@@ -24,8 +22,6 @@ import {
|
||||
MAX_PANE_HEIGHT,
|
||||
MAX_PANE_WIDTH,
|
||||
MAX_SIDEBAR_REMS,
|
||||
METHOD_GET,
|
||||
METHOD_POST,
|
||||
MIN_PANE_HEIGHT,
|
||||
MIN_PANE_WIDTH,
|
||||
MIN_SIDEBAR_REMS,
|
||||
@@ -70,7 +66,6 @@ import { AskModal } from '../components/modals/ask-modal';
|
||||
import { showCookiesModal } from '../components/modals/cookies-modal';
|
||||
import { GenerateCodeModal } from '../components/modals/generate-code-modal';
|
||||
import { showAlert, showModal, showPrompt } from '../components/modals/index';
|
||||
import ProtoFilesModal from '../components/modals/proto-files-modal';
|
||||
import { RequestRenderErrorModal } from '../components/modals/request-render-error-modal';
|
||||
import { RequestSettingsModal } from '../components/modals/request-settings-modal';
|
||||
import RequestSwitcherModal from '../components/modals/request-switcher-modal';
|
||||
@@ -200,19 +195,13 @@ class App extends PureComponent<AppProps, State> {
|
||||
};
|
||||
|
||||
this._savePaneWidth = debounce(paneWidth =>
|
||||
this._updateActiveWorkspaceMeta({
|
||||
paneWidth,
|
||||
}),
|
||||
this._updateActiveWorkspaceMeta({ paneWidth }),
|
||||
);
|
||||
this._savePaneHeight = debounce(paneHeight =>
|
||||
this._updateActiveWorkspaceMeta({
|
||||
paneHeight,
|
||||
}),
|
||||
this._updateActiveWorkspaceMeta({ paneHeight }),
|
||||
);
|
||||
this._saveSidebarWidth = debounce(sidebarWidth =>
|
||||
this._updateActiveWorkspaceMeta({
|
||||
sidebarWidth,
|
||||
}),
|
||||
this._updateActiveWorkspaceMeta({ sidebarWidth }),
|
||||
);
|
||||
this._globalKeyMap = null;
|
||||
this._updateVCSLock = null;
|
||||
@@ -400,51 +389,6 @@ class App extends PureComponent<AppProps, State> {
|
||||
});
|
||||
}
|
||||
|
||||
async _requestCreate(parentId: string, requestType?: string) {
|
||||
if (requestType === 'gRPC') {
|
||||
showModal(ProtoFilesModal, {
|
||||
onSave: async (protoFileId: string) => {
|
||||
const createdRequest = await models.grpcRequest.create({
|
||||
parentId,
|
||||
name: 'New Request',
|
||||
protoFileId,
|
||||
});
|
||||
models.stats.incrementCreatedRequests();
|
||||
trackSegmentEvent(SegmentEvent.requestCreate, { requestType });
|
||||
this._handleSetActiveRequest(createdRequest._id);
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (requestType === 'GraphQL') {
|
||||
const request = await models.request.create({
|
||||
parentId,
|
||||
method: METHOD_POST,
|
||||
headers:[{
|
||||
name: 'Content-Type',
|
||||
value: CONTENT_TYPE_JSON,
|
||||
}],
|
||||
body:{
|
||||
mimeType: CONTENT_TYPE_GRAPHQL,
|
||||
text: '',
|
||||
},
|
||||
name: 'New Request',
|
||||
});
|
||||
models.stats.incrementCreatedRequests();
|
||||
trackSegmentEvent(SegmentEvent.requestCreate, { requestType });
|
||||
this._handleSetActiveRequest(request._id);
|
||||
return;
|
||||
}
|
||||
const request = await models.request.create({
|
||||
parentId,
|
||||
method: METHOD_GET,
|
||||
name: 'New Request',
|
||||
});
|
||||
models.stats.incrementCreatedRequests();
|
||||
trackSegmentEvent(SegmentEvent.requestCreate, { requestType: 'HTTP' });
|
||||
this._handleSetActiveRequest(request._id);
|
||||
}
|
||||
|
||||
async _recalculateMetaSortKey(docs: (RequestGroup | Request | GrpcRequest)[]) {
|
||||
function __updateDoc(doc, metaSortKey) {
|
||||
// @ts-expect-error -- TSCONVERSION the fetched model will only ever be a RequestGroup, Request, or GrpcRequest
|
||||
@@ -901,12 +845,6 @@ class App extends PureComponent<AppProps, State> {
|
||||
}
|
||||
}
|
||||
|
||||
_requestCreateForWorkspace(requestType?: string) {
|
||||
if (this.props.activeWorkspace) {
|
||||
this._requestCreate(this.props.activeWorkspace._id, requestType);
|
||||
}
|
||||
}
|
||||
|
||||
_startDragSidebar() {
|
||||
this.setState({
|
||||
draggingSidebar: true,
|
||||
@@ -1508,7 +1446,6 @@ class App extends PureComponent<AppProps, State> {
|
||||
paneWidth={paneWidth}
|
||||
paneHeight={paneHeight}
|
||||
sidebarWidth={sidebarWidth}
|
||||
handleCreateRequestForWorkspace={this._requestCreateForWorkspace}
|
||||
handleSetRequestPinned={this._handleSetRequestPinned}
|
||||
handleSetRequestGroupCollapsed={this._handleSetRequestGroupCollapsed}
|
||||
handleActivateRequest={this._handleSetActiveRequest}
|
||||
@@ -1521,7 +1458,6 @@ class App extends PureComponent<AppProps, State> {
|
||||
handleStartDragPaneVertical={this._startDragPaneVertical}
|
||||
handleResetDragPaneHorizontal={this._resetDragPaneHorizontal}
|
||||
handleResetDragPaneVertical={this._resetDragPaneVertical}
|
||||
handleCreateRequest={this._requestCreate}
|
||||
handleDuplicateRequest={this._requestDuplicate}
|
||||
handleDuplicateRequestGroup={App._requestGroupDuplicate}
|
||||
handleCreateRequestGroup={this._requestGroupCreate}
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
import { unreachableCase } from 'ts-assert-unreachable';
|
||||
|
||||
import { SegmentEvent, trackSegmentEvent } from '../../common/analytics';
|
||||
import {
|
||||
CONTENT_TYPE_GRAPHQL,
|
||||
CONTENT_TYPE_JSON,
|
||||
METHOD_GET,
|
||||
METHOD_POST,
|
||||
} from '../../common/constants';
|
||||
import * as models from '../../models';
|
||||
import { isGrpcRequestId } from '../../models/grpc-request';
|
||||
import { GrpcRequestMeta } from '../../models/grpc-request-meta';
|
||||
import { RequestMeta } from '../../models/request-meta';
|
||||
import { WorkspaceMeta } from '../../models/workspace-meta';
|
||||
import { showModal } from '../components/modals';
|
||||
import ProtoFilesModal from '../components/modals/proto-files-modal';
|
||||
|
||||
export const updateActiveWorkspaceMeta = async (
|
||||
patch: Partial<WorkspaceMeta>,
|
||||
workspaceId: string
|
||||
) => {
|
||||
const activeWorkspaceMeta = await models.workspaceMeta.getByParentId(
|
||||
workspaceId
|
||||
);
|
||||
|
||||
if (activeWorkspaceMeta) {
|
||||
await models.workspaceMeta.update(activeWorkspaceMeta, patch);
|
||||
}
|
||||
};
|
||||
|
||||
export const updateRequestMetaByParentId = async (
|
||||
requestId: string,
|
||||
patch: Partial<GrpcRequestMeta> | Partial<RequestMeta>
|
||||
) => {
|
||||
if (isGrpcRequestId(requestId)) {
|
||||
await models.grpcRequestMeta.updateOrCreateByParentId(requestId, patch);
|
||||
return;
|
||||
}
|
||||
|
||||
await models.requestMeta.updateOrCreateByParentId(requestId, patch);
|
||||
};
|
||||
|
||||
export const setActiveRequest = async (
|
||||
activeRequestId: string,
|
||||
workspaceId: string
|
||||
) => {
|
||||
await updateActiveWorkspaceMeta({ activeRequestId }, workspaceId);
|
||||
await updateRequestMetaByParentId(activeRequestId, {
|
||||
lastActive: Date.now(),
|
||||
});
|
||||
};
|
||||
|
||||
export type CreateRequestType = 'HTTP' | 'gRPC' | 'GraphQL';
|
||||
type RequestCreator = (input: {
|
||||
parentId: string;
|
||||
requestType: CreateRequestType;
|
||||
workspaceId: string;
|
||||
}) => Promise<void>;
|
||||
|
||||
export const createRequest: RequestCreator = async ({
|
||||
parentId,
|
||||
requestType,
|
||||
workspaceId,
|
||||
}) => {
|
||||
let requestId = '';
|
||||
|
||||
switch (requestType) {
|
||||
case 'gRPC': {
|
||||
showModal(ProtoFilesModal, {
|
||||
onSave: async (protoFileId: string) => {
|
||||
const createdRequest = await models.grpcRequest.create({
|
||||
parentId,
|
||||
name: 'New Request',
|
||||
protoFileId,
|
||||
});
|
||||
models.stats.incrementCreatedRequests();
|
||||
requestId = createdRequest._id;
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case 'GraphQL': {
|
||||
const request = await models.request.create({
|
||||
parentId,
|
||||
method: METHOD_POST,
|
||||
headers: [
|
||||
{
|
||||
name: 'Content-Type',
|
||||
value: CONTENT_TYPE_JSON,
|
||||
},
|
||||
],
|
||||
body: {
|
||||
mimeType: CONTENT_TYPE_GRAPHQL,
|
||||
text: '',
|
||||
},
|
||||
name: 'New Request',
|
||||
});
|
||||
models.stats.incrementCreatedRequests();
|
||||
requestId = request._id;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'HTTP': {
|
||||
const request = await models.request.create({
|
||||
parentId,
|
||||
method: METHOD_GET,
|
||||
name: 'New Request',
|
||||
});
|
||||
models.stats.incrementCreatedRequests();
|
||||
requestId = request._id;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
unreachableCase(
|
||||
requestType,
|
||||
"tried to create a request but didn't specify the type"
|
||||
);
|
||||
}
|
||||
|
||||
trackSegmentEvent(SegmentEvent.requestCreate, { requestType });
|
||||
setActiveRequest(requestId, workspaceId);
|
||||
};
|
||||
Reference in new issue
Block a user