mirror of
https://github.com/Kong/insomnia.git
synced 2026-04-23 07:38:58 -04:00
Import into the active space (#3795)
This commit is contained in:
@@ -31,6 +31,7 @@ import { isCookieJar } from '../models/cookie-jar';
|
||||
import { isEnvironment } from '../models/environment';
|
||||
import { isUnitTestSuite } from '../models/unit-test-suite';
|
||||
import { isUnitTest } from '../models/unit-test';
|
||||
import { resetKeys } from '../sync/vcs/ignore-keys';
|
||||
|
||||
const EXPORT_FORMAT = 4;
|
||||
|
||||
@@ -210,6 +211,8 @@ export async function exportRequestsData(
|
||||
if (isWorkspace(d)) {
|
||||
// @ts-expect-error -- TSCONVERSION maybe this needs to be added to the upstream type?
|
||||
d._type = EXPORT_TYPE_WORKSPACE;
|
||||
// reset the parentId of a workspace
|
||||
resetKeys(d);
|
||||
} else if (isCookieJar(d)) {
|
||||
// @ts-expect-error -- TSCONVERSION maybe this needs to be added to the upstream type?
|
||||
d._type = EXPORT_TYPE_COOKIE_JAR;
|
||||
|
||||
@@ -39,6 +39,7 @@ interface ConvertResult {
|
||||
|
||||
export interface ImportRawConfig {
|
||||
getWorkspaceId: ImportToWorkspacePrompt;
|
||||
getSpaceId?: () => Promise<string | null>;
|
||||
getWorkspaceScope?: SetWorkspaceScopePrompt;
|
||||
enableDiffBasedPatching?: boolean;
|
||||
enableDiffDeep?: boolean;
|
||||
@@ -112,6 +113,7 @@ export async function importRaw(
|
||||
{
|
||||
getWorkspaceId,
|
||||
getWorkspaceScope,
|
||||
getSpaceId,
|
||||
enableDiffBasedPatching,
|
||||
enableDiffDeep,
|
||||
bypassDiffProps,
|
||||
@@ -246,15 +248,18 @@ export async function importRaw(
|
||||
updateDoc.url = resource.url;
|
||||
}
|
||||
|
||||
// If workspace, don't overwrite the existing scope
|
||||
// If workspace preserve the scope and parentId of the existing workspace while importing
|
||||
if (isWorkspace(model)) {
|
||||
(updateDoc as Workspace).scope = (existingDoc as Workspace).scope;
|
||||
(updateDoc as Workspace).parentId = (existingDoc as Workspace).parentId;
|
||||
}
|
||||
|
||||
newDoc = await db.docUpdate(existingDoc, updateDoc);
|
||||
} else {
|
||||
// If workspace, check and set the scope and parentId while importing a new workspace
|
||||
if (isWorkspace(model)) {
|
||||
await updateWorkspaceScope(resource as Workspace, resultsType, getWorkspaceScope);
|
||||
await createWorkspaceInSpace(resource as Workspace, getSpaceId);
|
||||
}
|
||||
|
||||
newDoc = await db.docCreate(model.type, resource);
|
||||
@@ -306,7 +311,7 @@ async function updateWorkspaceScope(
|
||||
resultType: ConvertResultType,
|
||||
getWorkspaceScope?: SetWorkspaceScopePrompt,
|
||||
) {
|
||||
// Set the workspace scope if creating a new workspace
|
||||
// Set the workspace scope if creating a new workspace during import
|
||||
// IF is creating a new workspace
|
||||
// AND imported resource has no preset scope property OR scope is null
|
||||
// AND we have a function to get scope
|
||||
@@ -328,6 +333,17 @@ async function updateWorkspaceScope(
|
||||
}
|
||||
}
|
||||
|
||||
async function createWorkspaceInSpace(
|
||||
resource: Workspace,
|
||||
getSpaceId?: () => Promise<string | null>,
|
||||
) {
|
||||
if (getSpaceId) {
|
||||
// Set the workspace parent if creating a new workspace during import
|
||||
// @ts-expect-error workspace parent can be null or string
|
||||
resource.parentId = await getSpaceId();
|
||||
}
|
||||
}
|
||||
|
||||
export const isApiSpecImport = ({ id }: Pick<ConvertResultType, 'id'>) => (
|
||||
id === 'openapi3' || id === 'swagger2'
|
||||
);
|
||||
|
||||
@@ -5,17 +5,19 @@ import ModalHeader from '../base/modal-header';
|
||||
import ModalFooter from '../base/modal-footer';
|
||||
import { autoBindMethodsForReact } from 'class-autobind-decorator';
|
||||
import { AUTOBIND_CFG } from '../../../common/constants';
|
||||
import { showModal } from '.';
|
||||
|
||||
export interface SelectModalShowOptions {
|
||||
message: string | null;
|
||||
onCancel?: () => void;
|
||||
onDone?: (selectedValue: string | null) => Promise<void>;
|
||||
onDone?: (selectedValue: string | null) => void | Promise<void>;
|
||||
options: {
|
||||
name: string;
|
||||
value: string;
|
||||
}[];
|
||||
title: string | null;
|
||||
value: string | null;
|
||||
noEscape?: boolean;
|
||||
}
|
||||
|
||||
const initialState: SelectModalShowOptions = {
|
||||
@@ -47,6 +49,7 @@ export class SelectModal extends PureComponent<{}, SelectModalShowOptions> {
|
||||
options,
|
||||
title,
|
||||
value,
|
||||
noEscape,
|
||||
}: SelectModalShowOptions = initialState) {
|
||||
this.setState({
|
||||
message,
|
||||
@@ -55,6 +58,7 @@ export class SelectModal extends PureComponent<{}, SelectModalShowOptions> {
|
||||
options,
|
||||
title,
|
||||
value,
|
||||
noEscape,
|
||||
});
|
||||
this.modal.current?.show();
|
||||
setTimeout(() => {
|
||||
@@ -63,9 +67,10 @@ export class SelectModal extends PureComponent<{}, SelectModalShowOptions> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { message, title, options, value, onCancel } = this.state;
|
||||
const { message, title, options, value, onCancel, noEscape } = this.state;
|
||||
|
||||
return (
|
||||
<Modal ref={this.modal} onCancel={onCancel}>
|
||||
<Modal ref={this.modal} onCancel={onCancel} noEscape={noEscape}>
|
||||
<ModalHeader>{title || 'Confirm?'}</ModalHeader>
|
||||
<ModalBody className="wide pad">
|
||||
<p>{message}</p>
|
||||
@@ -88,3 +93,5 @@ export class SelectModal extends PureComponent<{}, SelectModalShowOptions> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const showSelectModal = (opts: SelectModalShowOptions) => showModal(SelectModal, opts);
|
||||
|
||||
@@ -1,75 +1,77 @@
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import React, { FC, useCallback } from 'react';
|
||||
import Hotkey from '../hotkey';
|
||||
import { hotKeyRefs } from '../../../common/hotkeys';
|
||||
import * as hotkeys from '../../../common/hotkeys';
|
||||
import { Pane, PaneBody, PaneHeader } from './pane';
|
||||
import type { HandleImportFileCallback } from '../wrapper';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { importFile } from '../../redux/modules/import';
|
||||
import { selectActiveWorkspace } from '../../redux/selectors';
|
||||
|
||||
interface Props {
|
||||
hotKeyRegistry: hotkeys.HotKeyRegistry;
|
||||
handleImportFile: HandleImportFileCallback;
|
||||
handleCreateRequest: () => void;
|
||||
}
|
||||
|
||||
const PlaceholderRequestPane: FunctionComponent<Props> = ({
|
||||
const PlaceholderRequestPane: FC<Props> = ({
|
||||
hotKeyRegistry,
|
||||
handleImportFile,
|
||||
handleCreateRequest,
|
||||
}) => (
|
||||
<Pane type="request">
|
||||
<PaneHeader />
|
||||
<PaneBody placeholder>
|
||||
<div>
|
||||
<table className="table--fancy">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>New Request</td>
|
||||
<td className="text-right">
|
||||
<code>
|
||||
<Hotkey
|
||||
keyBindings={hotKeyRegistry[hotKeyRefs.REQUEST_SHOW_CREATE.id]}
|
||||
useFallbackMessage
|
||||
/>
|
||||
</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Switch Requests</td>
|
||||
<td className="text-right">
|
||||
<code>
|
||||
<Hotkey
|
||||
keyBindings={hotKeyRegistry[hotKeyRefs.REQUEST_QUICK_SWITCH.id]}
|
||||
useFallbackMessage
|
||||
/>
|
||||
</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Edit Environments</td>
|
||||
<td className="text-right">
|
||||
<code>
|
||||
<Hotkey
|
||||
keyBindings={hotKeyRegistry[hotKeyRefs.ENVIRONMENT_SHOW_EDITOR.id]}
|
||||
useFallbackMessage
|
||||
/>
|
||||
</code>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
const workspaceId = useSelector(selectActiveWorkspace)?._id;
|
||||
const handleImportFile = useCallback(() => dispatch(importFile({ workspaceId })), [workspaceId, dispatch]);
|
||||
|
||||
<div className="text-center pane__body--placeholder__cta">
|
||||
{/* @ts-expect-error -- TSCONVERSION event not used */}
|
||||
<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>
|
||||
return (
|
||||
<Pane type="request">
|
||||
<PaneHeader />
|
||||
<PaneBody placeholder>
|
||||
<div>
|
||||
<table className="table--fancy">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>New Request</td>
|
||||
<td className="text-right">
|
||||
<code>
|
||||
<Hotkey
|
||||
keyBindings={hotKeyRegistry[hotKeyRefs.REQUEST_SHOW_CREATE.id]}
|
||||
useFallbackMessage />
|
||||
</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Switch Requests</td>
|
||||
<td className="text-right">
|
||||
<code>
|
||||
<Hotkey
|
||||
keyBindings={hotKeyRegistry[hotKeyRefs.REQUEST_QUICK_SWITCH.id]}
|
||||
useFallbackMessage />
|
||||
</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Edit Environments</td>
|
||||
<td className="text-right">
|
||||
<code>
|
||||
<Hotkey
|
||||
keyBindings={hotKeyRegistry[hotKeyRefs.ENVIRONMENT_SHOW_EDITOR.id]}
|
||||
useFallbackMessage />
|
||||
</code>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div className="text-center pane__body--placeholder__cta">
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</PaneBody>
|
||||
</Pane>
|
||||
);
|
||||
</PaneBody>
|
||||
</Pane>
|
||||
);
|
||||
};
|
||||
|
||||
export default PlaceholderRequestPane;
|
||||
|
||||
@@ -30,7 +30,6 @@ import PlaceholderRequestPane from './placeholder-request-pane';
|
||||
import { Pane, paneBodyClasses, PaneHeader } from './pane';
|
||||
import classnames from 'classnames';
|
||||
import { queryAllWorkspaceUrls } from '../../../models/helpers/query-all-workspace-urls';
|
||||
import type { HandleImportFileCallback } from '../wrapper';
|
||||
import { HandleGetRenderContext, HandleRender } from '../../../common/render';
|
||||
|
||||
interface Props {
|
||||
@@ -55,7 +54,6 @@ interface Props {
|
||||
updateSettingsUseBulkHeaderEditor: Function;
|
||||
updateSettingsUseBulkParametersEditor: (useBulkParametersEditor: boolean) => Promise<Settings>;
|
||||
handleImport: Function;
|
||||
handleImportFile: HandleImportFileCallback;
|
||||
workspace: Workspace;
|
||||
settings: Settings;
|
||||
isVariableUncovered: boolean;
|
||||
@@ -132,7 +130,6 @@ class RequestPane extends PureComponent<Props> {
|
||||
handleGenerateCode,
|
||||
handleGetRenderContext,
|
||||
handleImport,
|
||||
handleImportFile,
|
||||
handleCreateRequest,
|
||||
handleRender,
|
||||
handleSend,
|
||||
@@ -161,7 +158,6 @@ class RequestPane extends PureComponent<Props> {
|
||||
return (
|
||||
<PlaceholderRequestPane
|
||||
hotKeyRegistry={hotKeyRegistry}
|
||||
handleImportFile={handleImportFile}
|
||||
handleCreateRequest={handleCreateRequest}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -7,9 +7,10 @@ import { strings } from '../../../common/strings';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { selectActiveSpaceName, selectActiveWorkspace } from '../../redux/selectors';
|
||||
import ExportRequestsModal from '../modals/export-requests-modal';
|
||||
import { exportAllToFile, importClipBoard, importFile, importUri } from '../../redux/modules/global';
|
||||
import { exportAllToFile } from '../../redux/modules/global';
|
||||
import { getAppName } from '../../../common/constants';
|
||||
import { getWorkspaceLabel } from '../../../common/get-workspace-label';
|
||||
import { importClipBoard, importFile, importUri } from '../../redux/modules/import';
|
||||
|
||||
interface Props {
|
||||
hideSettingsModal: () => void;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { Fragment, PureComponent, ReactNode } from 'react';
|
||||
import { autoBindMethodsForReact } from 'class-autobind-decorator';
|
||||
import PageLayout from './page-layout';
|
||||
import type { HandleImportFileCallback, WrapperProps } from './wrapper';
|
||||
import type { WrapperProps } from './wrapper';
|
||||
import RequestPane from './panes/request-pane';
|
||||
import ErrorBoundary from './error-boundary';
|
||||
import ResponsePane from './panes/response-pane';
|
||||
@@ -30,7 +30,6 @@ interface Props {
|
||||
handleForceUpdateRequest: (r: Request, patch: Partial<Request>) => Promise<Request>;
|
||||
handleForceUpdateRequestHeaders: (r: Request, headers: RequestHeader[]) => Promise<Request>;
|
||||
handleImport: Function;
|
||||
handleImportFile: HandleImportFileCallback;
|
||||
handleRequestCreate: () => void;
|
||||
handleRequestGroupCreate: () => void;
|
||||
handleSendAndDownloadRequestWithActiveEnvironment: (filepath?: string) => Promise<void>;
|
||||
@@ -196,7 +195,6 @@ class WrapperDebug extends PureComponent<Props> {
|
||||
handleForceUpdateRequest,
|
||||
handleForceUpdateRequestHeaders,
|
||||
handleImport,
|
||||
handleImportFile,
|
||||
handleSendAndDownloadRequestWithActiveEnvironment,
|
||||
handleSendRequestWithActiveEnvironment,
|
||||
handleUpdateRequestAuthentication,
|
||||
@@ -261,7 +259,6 @@ class WrapperDebug extends PureComponent<Props> {
|
||||
handleGenerateCode={handleGenerateCodeForActiveRequest}
|
||||
handleGetRenderContext={handleGetRenderContext}
|
||||
handleImport={handleImport}
|
||||
handleImportFile={handleImportFile}
|
||||
handleRender={handleRender}
|
||||
handleSend={handleSendRequestWithActiveEnvironment}
|
||||
handleSendAndDownload={handleSendAndDownloadRequestWithActiveEnvironment}
|
||||
|
||||
@@ -30,14 +30,10 @@ import TimeFromNow from './time-from-now';
|
||||
import Highlight from './base/highlight';
|
||||
import { fuzzyMatchAll, isNotNullOrUndefined } from '../../common/misc';
|
||||
import type {
|
||||
HandleImportClipboardCallback,
|
||||
HandleImportFileCallback,
|
||||
HandleImportUriCallback,
|
||||
WrapperProps,
|
||||
} from './wrapper';
|
||||
import Notice from './notice';
|
||||
import PageLayout from './page-layout';
|
||||
import { ForceToWorkspaceKeys } from '../redux/modules/helpers';
|
||||
import coreLogo from '../images/insomnia-core-logo.png';
|
||||
import { parseApiSpec, ParsedApiSpec } from '../../common/api-specs';
|
||||
import { RemoteWorkspacesDropdown } from './dropdowns/remote-workspaces-dropdown';
|
||||
@@ -52,22 +48,16 @@ import { cloneGitRepository } from '../redux/modules/git';
|
||||
import { MemClient } from '../../sync/git/mem-client';
|
||||
import { SpaceDropdown } from './dropdowns/space-dropdown';
|
||||
import { initializeLocalProjectAndMarkForSync } from '../../sync/vcs/initialize-project';
|
||||
import { importClipBoard, importFile, importUri } from '../redux/modules/import';
|
||||
import { ForceToWorkspace } from '../redux/modules/helpers';
|
||||
|
||||
interface RenderedCard {
|
||||
card: ReactNode;
|
||||
lastModifiedTimestamp?: number | null;
|
||||
}
|
||||
|
||||
interface ReduxDispatchProps {
|
||||
handleCreateWorkspace: typeof createWorkspace;
|
||||
handleGitCloneWorkspace: typeof cloneGitRepository;
|
||||
}
|
||||
|
||||
interface Props extends ReduxDispatchProps {
|
||||
interface Props extends ReturnType<typeof mapDispatchToProps> {
|
||||
wrapperProps: WrapperProps;
|
||||
handleImportFile: HandleImportFileCallback;
|
||||
handleImportUri: HandleImportUriCallback;
|
||||
handleImportClipboard: HandleImportClipboardCallback;
|
||||
}
|
||||
|
||||
interface State {
|
||||
@@ -116,13 +106,13 @@ class WrapperHome extends PureComponent<Props, State> {
|
||||
|
||||
_handleImportFile() {
|
||||
this.props.handleImportFile({
|
||||
forceToWorkspace: ForceToWorkspaceKeys.new,
|
||||
forceToWorkspace: ForceToWorkspace.new,
|
||||
});
|
||||
}
|
||||
|
||||
_handleImportClipBoard() {
|
||||
this.props.handleImportClipboard({
|
||||
forceToWorkspace: ForceToWorkspaceKeys.new,
|
||||
forceToWorkspace: ForceToWorkspace.new,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -134,7 +124,7 @@ class WrapperHome extends PureComponent<Props, State> {
|
||||
placeholder: 'https://website.com/insomnia-import.json',
|
||||
onComplete: uri => {
|
||||
this.props.handleImportUri(uri, {
|
||||
forceToWorkspace: ForceToWorkspaceKeys.new,
|
||||
forceToWorkspace: ForceToWorkspace.new,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -421,9 +411,22 @@ class WrapperHome extends PureComponent<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch): ReduxDispatchProps => ({
|
||||
handleCreateWorkspace: bindActionCreators(createWorkspace, dispatch),
|
||||
handleGitCloneWorkspace: bindActionCreators(cloneGitRepository, dispatch),
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
const bound = bindActionCreators({
|
||||
createWorkspace,
|
||||
cloneGitRepository,
|
||||
importFile,
|
||||
importClipBoard,
|
||||
importUri,
|
||||
}, dispatch);
|
||||
|
||||
return ({
|
||||
handleCreateWorkspace: bound.createWorkspace,
|
||||
handleGitCloneWorkspace: bound.cloneGitRepository,
|
||||
handleImportFile: bound.importFile,
|
||||
handleImportUri: bound.importUri,
|
||||
handleImportClipboard: bound.importClipBoard,
|
||||
});
|
||||
};
|
||||
|
||||
export default connect(null, mapDispatchToProps)(WrapperHome);
|
||||
|
||||
@@ -4,17 +4,20 @@ import 'swagger-ui-react/swagger-ui.css';
|
||||
import { showPrompt } from './modals';
|
||||
import type { BaseModel } from '../../models';
|
||||
import { AUTOBIND_CFG, getAppLongName, getAppName, getAppSynopsis } from '../../common/constants';
|
||||
import type { HandleImportFileCallback, HandleImportUriCallback, WrapperProps } from './wrapper';
|
||||
import type { WrapperProps } from './wrapper';
|
||||
import { database as db } from '../../common/database';
|
||||
import { ForceToWorkspaceKeys } from '../redux/modules/helpers';
|
||||
import OnboardingContainer from './onboarding-container';
|
||||
import { isWorkspace, WorkspaceScopeKeys } from '../../models/workspace';
|
||||
import Analytics from './analytics';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { importFile, importUri } from '../redux/modules/import';
|
||||
import { connect } from 'react-redux';
|
||||
import { ForceToWorkspace } from '../redux/modules/helpers';
|
||||
|
||||
interface Props {
|
||||
type ReduxProps = ReturnType<typeof mapDispatchToProps>;
|
||||
|
||||
interface Props extends ReduxProps {
|
||||
wrapperProps: WrapperProps;
|
||||
handleImportFile: HandleImportFileCallback;
|
||||
handleImportUri: HandleImportUriCallback;
|
||||
}
|
||||
|
||||
interface State {
|
||||
@@ -64,9 +67,8 @@ class WrapperOnboarding extends PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
_handleImportFile() {
|
||||
const { handleImportFile } = this.props;
|
||||
handleImportFile({
|
||||
forceToWorkspace: ForceToWorkspaceKeys.new,
|
||||
this.props.handleImportFile({
|
||||
forceToWorkspace: ForceToWorkspace.new,
|
||||
forceToScope: WorkspaceScopeKeys.design,
|
||||
});
|
||||
}
|
||||
@@ -80,7 +82,7 @@ class WrapperOnboarding extends PureComponent<Props, State> {
|
||||
label: 'URI to Import',
|
||||
onComplete: value => {
|
||||
handleImportUri(value, {
|
||||
forceToWorkspace: ForceToWorkspaceKeys.new,
|
||||
forceToWorkspace: ForceToWorkspace.new,
|
||||
forceToScope: WorkspaceScopeKeys.design,
|
||||
});
|
||||
},
|
||||
@@ -160,4 +162,16 @@ class WrapperOnboarding extends PureComponent<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
export default WrapperOnboarding;
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
const bound = bindActionCreators({
|
||||
importFile,
|
||||
importUri,
|
||||
}, dispatch);
|
||||
|
||||
return ({
|
||||
handleImportFile: bound.importFile,
|
||||
handleImportUri: bound.importUri,
|
||||
});
|
||||
};
|
||||
|
||||
export default connect(null, mapDispatchToProps)(WrapperOnboarding);
|
||||
|
||||
@@ -79,7 +79,6 @@ import type { GlobalActivity } from '../../common/constants';
|
||||
import ProtoFilesModal from './modals/proto-files-modal';
|
||||
import { GrpcDispatchModalWrapper } from '../context/grpc';
|
||||
import WrapperMigration from './wrapper-migration';
|
||||
import type { ImportOptions } from '../redux/modules/global';
|
||||
import WrapperAnalytics from './wrapper-analytics';
|
||||
import { HandleGetRenderContext, HandleRender } from '../../common/render';
|
||||
import { RequestGroup } from '../../models/request-group';
|
||||
@@ -134,10 +133,6 @@ export type WrapperProps = AppProps & {
|
||||
gitVCS: GitVCS | null;
|
||||
}
|
||||
|
||||
export type HandleImportFileCallback = (options?: ImportOptions) => void;
|
||||
export type HandleImportClipboardCallback = (options?: ImportOptions) => void;
|
||||
export type HandleImportUriCallback = (uri: string, options?: ImportOptions) => void;
|
||||
|
||||
interface State {
|
||||
forceRefreshKey: number;
|
||||
activeGitBranch: string;
|
||||
@@ -302,18 +297,6 @@ class Wrapper extends PureComponent<WrapperProps, State> {
|
||||
return models.settings.update(this.props.settings, { useBulkParametersEditor });
|
||||
}
|
||||
|
||||
_handleImportFile(options?: ImportOptions) {
|
||||
this.props.handleImportFileToWorkspace({ workspaceId: this.props.activeWorkspace?._id, ...options });
|
||||
}
|
||||
|
||||
_handleImportUri(uri: string, options?: ImportOptions) {
|
||||
this.props.handleImportUriToWorkspace(uri, { workspaceId: this.props.activeWorkspace?._id, ...options });
|
||||
}
|
||||
|
||||
_handleImportClipBoard(options?: ImportOptions) {
|
||||
this.props.handleImportClipBoardToWorkspace({ workspaceId: this.props.activeWorkspace?._id, ...options });
|
||||
}
|
||||
|
||||
_handleSetActiveResponse(responseId: string | null) {
|
||||
if (!this.props.activeRequest) {
|
||||
console.warn('Tried to set active response when request not active');
|
||||
@@ -756,9 +739,6 @@ class Wrapper extends PureComponent<WrapperProps, State> {
|
||||
{(activity === ACTIVITY_HOME || !activeWorkspace) && (
|
||||
<WrapperHome
|
||||
wrapperProps={this.props}
|
||||
handleImportFile={this._handleImportFile}
|
||||
handleImportUri={this._handleImportUri}
|
||||
handleImportClipboard={this._handleImportClipBoard}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -792,7 +772,6 @@ class Wrapper extends PureComponent<WrapperProps, State> {
|
||||
handleForceUpdateRequest={this._handleForceUpdateRequest}
|
||||
handleForceUpdateRequestHeaders={this._handleForceUpdateRequestHeaders}
|
||||
handleImport={this._handleImport}
|
||||
handleImportFile={this._handleImportFile}
|
||||
handleRequestCreate={this._handleCreateRequestInWorkspace}
|
||||
handleRequestGroupCreate={this._handleCreateRequestGroupInWorkspace}
|
||||
handleSendAndDownloadRequestWithActiveEnvironment={
|
||||
@@ -827,11 +806,7 @@ class Wrapper extends PureComponent<WrapperProps, State> {
|
||||
{activity === ACTIVITY_ANALYTICS && <WrapperAnalytics wrapperProps={this.props} />}
|
||||
|
||||
{(activity === ACTIVITY_ONBOARDING || activity === null) && (
|
||||
<WrapperOnboarding
|
||||
wrapperProps={this.props}
|
||||
handleImportFile={this._handleImportFile}
|
||||
handleImportUri={this._handleImportUri}
|
||||
/>
|
||||
<WrapperOnboarding wrapperProps={this.props} />
|
||||
)}
|
||||
</Fragment>
|
||||
</Fragment>
|
||||
|
||||
@@ -32,15 +32,12 @@ import CookiesModal from '../components/modals/cookies-modal';
|
||||
import RequestSwitcherModal from '../components/modals/request-switcher-modal';
|
||||
import SettingsModal, { TAB_INDEX_SHORTCUTS } from '../components/modals/settings-modal';
|
||||
import {
|
||||
importUri,
|
||||
loadRequestStart,
|
||||
loadRequestStop,
|
||||
newCommand,
|
||||
setActiveWorkspace,
|
||||
setActiveActivity,
|
||||
goToNextActivity,
|
||||
importFile,
|
||||
importClipBoard,
|
||||
exportRequestsToFile,
|
||||
} from '../redux/modules/global';
|
||||
import { initialize } from '../redux/modules/entities';
|
||||
@@ -124,6 +121,7 @@ import { WorkspaceMeta } from '../../models/workspace-meta';
|
||||
import { Response } from '../../models/response';
|
||||
import { RenderContextAndKeys } from '../../common/render';
|
||||
import { RootState } from '../redux/modules';
|
||||
import { importUri } from '../redux/modules/import';
|
||||
|
||||
export type AppProps = ReturnType<typeof mapStateToProps> & ReturnType<typeof mapDispatchToProps>;
|
||||
|
||||
@@ -1372,7 +1370,7 @@ class App extends PureComponent<AppProps, State> {
|
||||
'drop',
|
||||
async e => {
|
||||
e.preventDefault();
|
||||
const { activeWorkspace, handleImportUriToWorkspace } = this.props;
|
||||
const { activeWorkspace, handleImportUri } = this.props;
|
||||
|
||||
if (!activeWorkspace) {
|
||||
return;
|
||||
@@ -1397,7 +1395,7 @@ class App extends PureComponent<AppProps, State> {
|
||||
),
|
||||
addCancel: true,
|
||||
});
|
||||
handleImportUriToWorkspace(uri, { workspaceId: activeWorkspace?._id });
|
||||
handleImportUri(uri, { workspaceId: activeWorkspace?._id });
|
||||
},
|
||||
false,
|
||||
);
|
||||
@@ -1755,15 +1753,13 @@ function mapStateToProps(state: RootState) {
|
||||
|
||||
const mapDispatchToProps = (dispatch: Dispatch<Action<any>>) => {
|
||||
const {
|
||||
importUri: handleImportUriToWorkspace,
|
||||
importUri: handleImportUri,
|
||||
loadRequestStart: handleStartLoading,
|
||||
loadRequestStop: handleStopLoading,
|
||||
setActiveWorkspace: handleSetActiveWorkspace,
|
||||
newCommand: handleCommand,
|
||||
setActiveActivity: handleSetActiveActivity,
|
||||
goToNextActivity: handleGoToNextActivity,
|
||||
importFile: handleImportFileToWorkspace,
|
||||
importClipBoard: handleImportClipBoardToWorkspace,
|
||||
exportRequestsToFile: handleExportRequestsToFile,
|
||||
initialize: handleInitializeEntities,
|
||||
} = bindActionCreators({
|
||||
@@ -1774,21 +1770,17 @@ const mapDispatchToProps = (dispatch: Dispatch<Action<any>>) => {
|
||||
setActiveWorkspace,
|
||||
setActiveActivity,
|
||||
goToNextActivity,
|
||||
importFile,
|
||||
importClipBoard,
|
||||
exportRequestsToFile,
|
||||
initialize,
|
||||
}, dispatch);
|
||||
return {
|
||||
handleCommand,
|
||||
handleImportUriToWorkspace,
|
||||
handleImportUri,
|
||||
handleSetActiveWorkspace,
|
||||
handleSetActiveActivity,
|
||||
handleStartLoading,
|
||||
handleStopLoading,
|
||||
handleGoToNextActivity,
|
||||
handleImportFileToWorkspace,
|
||||
handleImportClipBoardToWorkspace,
|
||||
handleExportRequestsToFile,
|
||||
handleInitializeEntities,
|
||||
handleMoveDoc: _moveDoc, // TODO this doesn't use dispatch.. it's unclear why it needs to be here.
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import { askToImportIntoWorkspace, ForceToWorkspaceKeys } from '../helpers';
|
||||
import { askToImportIntoWorkspace, ForceToWorkspace } from '../helpers';
|
||||
import * as modals from '../../../components/modals';
|
||||
|
||||
jest.mock('../../../components/modals');
|
||||
|
||||
describe('askToImportIntoWorkspace', () => {
|
||||
it('should return null if no active workspace', () => {
|
||||
const func = askToImportIntoWorkspace({ workspaceId: undefined, forceToWorkspace: ForceToWorkspaceKeys.new });
|
||||
const func = askToImportIntoWorkspace({ workspaceId: undefined, forceToWorkspace: ForceToWorkspace.new });
|
||||
expect(func()).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null if forcing to a new workspace', () => {
|
||||
const func = askToImportIntoWorkspace({ workspaceId: 'id', forceToWorkspace: ForceToWorkspaceKeys.new });
|
||||
const func = askToImportIntoWorkspace({ workspaceId: 'id', forceToWorkspace: ForceToWorkspace.new });
|
||||
expect(func()).toBeNull();
|
||||
});
|
||||
|
||||
it('should return id if forcing to a current workspace', () => {
|
||||
const currentWorkspaceId = 'currentId';
|
||||
const func = askToImportIntoWorkspace({ workspaceId: currentWorkspaceId, forceToWorkspace: ForceToWorkspaceKeys.current });
|
||||
const func = askToImportIntoWorkspace({ workspaceId: currentWorkspaceId, forceToWorkspace: ForceToWorkspace.current });
|
||||
expect(func()).toBe(currentWorkspaceId);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,16 +1,10 @@
|
||||
import electron, { OpenDialogOptions } from 'electron';
|
||||
import electron from 'electron';
|
||||
import React, { Fragment } from 'react';
|
||||
import { combineReducers, Dispatch } from 'redux';
|
||||
import fs, { NoParamCallback } from 'fs';
|
||||
import path from 'path';
|
||||
import AskModal from '../../../ui/components/modals/ask-modal';
|
||||
import moment from 'moment';
|
||||
import {
|
||||
ImportRawConfig,
|
||||
ImportResult,
|
||||
importRaw,
|
||||
importUri as _importUri,
|
||||
} from '../../../common/import';
|
||||
import {
|
||||
exportRequestsData,
|
||||
exportRequestsHAR,
|
||||
@@ -31,13 +25,11 @@ import SettingsModal, {
|
||||
TAB_INDEX_THEMES,
|
||||
} from '../../components/modals/settings-modal';
|
||||
import install from '../../../plugins/install';
|
||||
import type { ForceToWorkspace } from './helpers';
|
||||
import { askToImportIntoWorkspace, askToSetWorkspaceScope } from './helpers';
|
||||
import { createPlugin } from '../../../plugins/create';
|
||||
import { reloadPlugins } from '../../../plugins';
|
||||
import { setTheme } from '../../../plugins/misc';
|
||||
import type { GlobalActivity } from '../../../common/constants';
|
||||
import { isWorkspace, Workspace, WorkspaceScope } from '../../../models/workspace';
|
||||
import { isWorkspace } from '../../../models/workspace';
|
||||
import {
|
||||
ACTIVITY_DEBUG,
|
||||
ACTIVITY_HOME,
|
||||
@@ -55,6 +47,7 @@ import { Request } from '../../../models/request';
|
||||
import { Environment, isEnvironment } from '../../../models/environment';
|
||||
import { BASE_SPACE_ID } from '../../../models/space';
|
||||
import { unreachableCase } from 'ts-assert-unreachable';
|
||||
import { importUri } from './import';
|
||||
|
||||
export const LOCALSTORAGE_PREFIX = 'insomnia::meta';
|
||||
const LOGIN_STATE_CHANGE = 'global/login-state-change';
|
||||
@@ -197,7 +190,7 @@ export const newCommand = (command: string, args: any) => async (dispatch: Dispa
|
||||
),
|
||||
addCancel: true,
|
||||
});
|
||||
dispatch(importUri(args.uri, { workspaceId: args.workspaceId }));
|
||||
dispatch(importUri(args.uri, { workspaceId: args.workspaceId, forceToSpace: 'prompt' }));
|
||||
break;
|
||||
|
||||
case COMMAND_PLUGIN_INSTALL:
|
||||
@@ -389,141 +382,6 @@ export const setActiveWorkspace = (workspaceId: string | null) => {
|
||||
};
|
||||
};
|
||||
|
||||
export interface ImportOptions {
|
||||
workspaceId?: string
|
||||
forceToWorkspace?: ForceToWorkspace;
|
||||
forceToScope?: WorkspaceScope;
|
||||
}
|
||||
|
||||
export const importFile = (
|
||||
{ workspaceId, forceToScope, forceToWorkspace }: ImportOptions = {},
|
||||
) => async (dispatch: Dispatch) => {
|
||||
dispatch(loadStart());
|
||||
const options: OpenDialogOptions = {
|
||||
title: 'Import Insomnia Data',
|
||||
buttonLabel: 'Import',
|
||||
properties: ['openFile'],
|
||||
filters: [
|
||||
// @ts-expect-error https://github.com/electron/electron/pull/29322
|
||||
{
|
||||
extensions: [
|
||||
'',
|
||||
'sh',
|
||||
'txt',
|
||||
'json',
|
||||
'har',
|
||||
'curl',
|
||||
'bash',
|
||||
'shell',
|
||||
'yaml',
|
||||
'yml',
|
||||
'wsdl',
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const { canceled, filePaths } = await electron.remote.dialog.showOpenDialog(options);
|
||||
|
||||
if (canceled) {
|
||||
// It was cancelled, so let's bail out
|
||||
dispatch(loadStop());
|
||||
return;
|
||||
}
|
||||
|
||||
// Let's import all the files!
|
||||
for (const filePath of filePaths) {
|
||||
try {
|
||||
const uri = `file://${filePath}`;
|
||||
const options: ImportRawConfig = {
|
||||
getWorkspaceScope: askToSetWorkspaceScope(forceToScope),
|
||||
getWorkspaceId: askToImportIntoWorkspace({ workspaceId, forceToWorkspace }),
|
||||
};
|
||||
const result = await _importUri(uri, options);
|
||||
handleImportResult(result, 'The file does not contain a valid specification.');
|
||||
} catch (err) {
|
||||
showModal(AlertModal, {
|
||||
title: 'Import Failed',
|
||||
message: err + '',
|
||||
});
|
||||
} finally {
|
||||
dispatch(loadStop());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleImportResult = (result: ImportResult, errorMessage: string) => {
|
||||
const { error, summary } = result;
|
||||
|
||||
if (error) {
|
||||
showError({
|
||||
title: 'Import Failed',
|
||||
message: errorMessage,
|
||||
error,
|
||||
});
|
||||
return [];
|
||||
}
|
||||
|
||||
models.stats.incrementRequestStats({
|
||||
createdRequests: summary[models.request.type].length + summary[models.grpcRequest.type].length,
|
||||
});
|
||||
return (summary[models.workspace.type] as Workspace[]) || [];
|
||||
};
|
||||
|
||||
export const importClipBoard = (
|
||||
{ forceToScope, forceToWorkspace, workspaceId }: ImportOptions = {},
|
||||
) => async (dispatch: Dispatch) => {
|
||||
dispatch(loadStart());
|
||||
const schema = electron.clipboard.readText();
|
||||
|
||||
if (!schema) {
|
||||
showModal(AlertModal, {
|
||||
title: 'Import Failed',
|
||||
message: 'Your clipboard appears to be empty.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Let's import all the paths!
|
||||
try {
|
||||
const options: ImportRawConfig = {
|
||||
getWorkspaceScope: askToSetWorkspaceScope(forceToScope),
|
||||
getWorkspaceId: askToImportIntoWorkspace({ workspaceId, forceToWorkspace }),
|
||||
};
|
||||
const result = await importRaw(schema, options);
|
||||
handleImportResult(result, 'Your clipboard does not contain a valid specification.');
|
||||
} catch (err) {
|
||||
showModal(AlertModal, {
|
||||
title: 'Import Failed',
|
||||
message: 'Your clipboard does not contain a valid specification.',
|
||||
});
|
||||
} finally {
|
||||
dispatch(loadStop());
|
||||
}
|
||||
};
|
||||
|
||||
export const importUri = (
|
||||
uri: string,
|
||||
{ forceToScope, forceToWorkspace, workspaceId }: ImportOptions = {},
|
||||
) => async (dispatch: Dispatch) => {
|
||||
dispatch(loadStart());
|
||||
|
||||
try {
|
||||
const options: ImportRawConfig = {
|
||||
getWorkspaceScope: askToSetWorkspaceScope(forceToScope),
|
||||
getWorkspaceId: askToImportIntoWorkspace({ workspaceId, forceToWorkspace }),
|
||||
};
|
||||
const result = await _importUri(uri, options);
|
||||
handleImportResult(result, 'The URI does not contain a valid specification.');
|
||||
} catch (err) {
|
||||
showModal(AlertModal, {
|
||||
title: 'Import Failed',
|
||||
message: err + '',
|
||||
});
|
||||
} finally {
|
||||
dispatch(loadStop());
|
||||
}
|
||||
};
|
||||
|
||||
const VALUE_JSON = 'json';
|
||||
const VALUE_YAML = 'yaml';
|
||||
const VALUE_HAR = 'har';
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { showModal } from '../../components/modals';
|
||||
import AskModal from '../../components/modals/ask-modal';
|
||||
import { WorkspaceScope, WorkspaceScopeKeys } from '../../../models/workspace';
|
||||
import { ValueOf } from 'type-fest';
|
||||
import { showSelectModal } from '../../components/modals/select-modal';
|
||||
import { BASE_SPACE_ID, Space } from '../../../models/space';
|
||||
import { getAppName } from '../../../common/constants';
|
||||
|
||||
export const ForceToWorkspaceKeys = {
|
||||
new: 'new',
|
||||
current: 'current',
|
||||
} as const;
|
||||
|
||||
export type ForceToWorkspace = ValueOf<typeof ForceToWorkspaceKeys>;
|
||||
export enum ForceToWorkspace {
|
||||
new = 'new',
|
||||
current = 'current'
|
||||
}
|
||||
|
||||
export type ImportToWorkspacePrompt = () => null | string | Promise<null | string>;
|
||||
export function askToImportIntoWorkspace({ workspaceId, forceToWorkspace }: { workspaceId?: string; forceToWorkspace?: ForceToWorkspace; }): ImportToWorkspacePrompt {
|
||||
@@ -18,10 +18,10 @@ export function askToImportIntoWorkspace({ workspaceId, forceToWorkspace }: { wo
|
||||
}
|
||||
|
||||
switch (forceToWorkspace) {
|
||||
case ForceToWorkspaceKeys.new:
|
||||
case ForceToWorkspace.new:
|
||||
return null;
|
||||
|
||||
case ForceToWorkspaceKeys.current:
|
||||
case ForceToWorkspace.current:
|
||||
return workspaceId;
|
||||
|
||||
default:
|
||||
@@ -63,3 +63,30 @@ export function askToSetWorkspaceScope(scope?: WorkspaceScope): SetWorkspaceScop
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export type SetSpaceIdPrompt = () => Promise<string | null>;
|
||||
export function askToImportIntoSpace({ spaces, activeSpace }: { spaces: Space[]; activeSpace?: Space; }): SetSpaceIdPrompt {
|
||||
return function() {
|
||||
return new Promise(resolve => {
|
||||
// If no spaces exist, return null (indicating no parent/space)
|
||||
if (spaces.length === 0) {
|
||||
return resolve(null);
|
||||
}
|
||||
|
||||
const options = [{ name: getAppName(), value: BASE_SPACE_ID }, ...spaces.map(space => ({ name: space.name, value: space._id }))];
|
||||
|
||||
const defaultValue = activeSpace?._id || options[0].value;
|
||||
|
||||
showSelectModal({
|
||||
title: 'Import',
|
||||
message: 'Select a space to import into',
|
||||
options,
|
||||
value: defaultValue,
|
||||
noEscape: true,
|
||||
onDone: selectedSpaceId => {
|
||||
resolve(selectedSpaceId === BASE_SPACE_ID ? null : selectedSpaceId);
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
162
packages/insomnia-app/app/ui/redux/modules/import.ts
Normal file
162
packages/insomnia-app/app/ui/redux/modules/import.ts
Normal file
@@ -0,0 +1,162 @@
|
||||
import electron, { OpenDialogOptions } from 'electron';
|
||||
import { AnyAction } from 'redux';
|
||||
import {
|
||||
ImportRawConfig,
|
||||
ImportResult,
|
||||
importRaw,
|
||||
importUri as _importUri,
|
||||
} from '../../../common/import';
|
||||
import { WorkspaceScope, Workspace } from '../../../models/workspace';
|
||||
import { showModal, showError } from '../../components/modals';
|
||||
import AlertModal from '../../components/modals/alert-modal';
|
||||
import { loadStart, loadStop } from './global';
|
||||
import { ForceToWorkspace, askToSetWorkspaceScope, askToImportIntoWorkspace, askToImportIntoSpace } from './helpers';
|
||||
import * as models from '../../../models';
|
||||
import { RootState } from '.';
|
||||
import { selectActiveSpace, selectSpaces } from '../selectors';
|
||||
import { ThunkAction } from 'redux-thunk';
|
||||
|
||||
export interface ImportOptions {
|
||||
workspaceId?: string;
|
||||
forceToSpace?: 'active' | 'prompt';
|
||||
forceToWorkspace?: ForceToWorkspace;
|
||||
forceToScope?: WorkspaceScope;
|
||||
}
|
||||
|
||||
const handleImportResult = (result: ImportResult, errorMessage: string) => {
|
||||
const { error, summary } = result;
|
||||
|
||||
if (error) {
|
||||
showError({
|
||||
title: 'Import Failed',
|
||||
message: errorMessage,
|
||||
error,
|
||||
});
|
||||
return [];
|
||||
}
|
||||
|
||||
models.stats.incrementRequestStats({
|
||||
createdRequests: summary[models.request.type].length + summary[models.grpcRequest.type].length,
|
||||
});
|
||||
return (summary[models.workspace.type] as Workspace[]) || [];
|
||||
};
|
||||
|
||||
const convertToRawConfig = ({
|
||||
forceToScope,
|
||||
forceToWorkspace,
|
||||
workspaceId,
|
||||
forceToSpace,
|
||||
}: ImportOptions,
|
||||
state: RootState): ImportRawConfig => {
|
||||
const activeSpace = selectActiveSpace(state);
|
||||
const spaces = selectSpaces(state);
|
||||
|
||||
return ({
|
||||
getWorkspaceScope: askToSetWorkspaceScope(forceToScope),
|
||||
getWorkspaceId: askToImportIntoWorkspace({ workspaceId, forceToWorkspace }),
|
||||
// Currently, just return the active space instead of prompting for which space to import into
|
||||
getSpaceId: forceToSpace === 'prompt' ? askToImportIntoSpace({ spaces, activeSpace }) : () => Promise.resolve(activeSpace?._id || null),
|
||||
});
|
||||
};
|
||||
|
||||
export const importFile = (
|
||||
options: ImportOptions = {},
|
||||
): ThunkAction<void, RootState, void, AnyAction> => async (dispatch, getState) => {
|
||||
dispatch(loadStart());
|
||||
|
||||
const openDialogOptions: OpenDialogOptions = {
|
||||
title: 'Import Insomnia Data',
|
||||
buttonLabel: 'Import',
|
||||
properties: ['openFile'],
|
||||
filters: [
|
||||
// @ts-expect-error https://github.com/electron/electron/pull/29322
|
||||
{
|
||||
extensions: [
|
||||
'',
|
||||
'sh',
|
||||
'txt',
|
||||
'json',
|
||||
'har',
|
||||
'curl',
|
||||
'bash',
|
||||
'shell',
|
||||
'yaml',
|
||||
'yml',
|
||||
'wsdl',
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const { canceled, filePaths } = await electron.remote.dialog.showOpenDialog(openDialogOptions);
|
||||
|
||||
if (canceled) {
|
||||
// It was cancelled, so let's bail out
|
||||
dispatch(loadStop());
|
||||
return;
|
||||
}
|
||||
|
||||
// Let's import all the files!
|
||||
for (const filePath of filePaths) {
|
||||
try {
|
||||
const uri = `file://${filePath}`;
|
||||
const config = convertToRawConfig(options, getState());
|
||||
const result = await _importUri(uri, config);
|
||||
handleImportResult(result, 'The file does not contain a valid specification.');
|
||||
} catch (err) {
|
||||
showModal(AlertModal, {
|
||||
title: 'Import Failed',
|
||||
message: err + '',
|
||||
});
|
||||
} finally {
|
||||
dispatch(loadStop());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const importClipBoard = (
|
||||
options: ImportOptions = {},
|
||||
): ThunkAction<void, RootState, void, AnyAction> => async (dispatch, getState) => {
|
||||
dispatch(loadStart());
|
||||
const schema = electron.clipboard.readText();
|
||||
|
||||
if (!schema) {
|
||||
showModal(AlertModal, {
|
||||
title: 'Import Failed',
|
||||
message: 'Your clipboard appears to be empty.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Let's import all the paths!
|
||||
try {
|
||||
const config = convertToRawConfig(options, getState());
|
||||
const result = await importRaw(schema, config);
|
||||
handleImportResult(result, 'Your clipboard does not contain a valid specification.');
|
||||
} catch (err) {
|
||||
showModal(AlertModal, {
|
||||
title: 'Import Failed',
|
||||
message: 'Your clipboard does not contain a valid specification.',
|
||||
});
|
||||
} finally {
|
||||
dispatch(loadStop());
|
||||
}
|
||||
};
|
||||
|
||||
export const importUri = (
|
||||
uri: string,
|
||||
options: ImportOptions = {},
|
||||
): ThunkAction<void, RootState, void, AnyAction> => async (dispatch, getState) => {
|
||||
dispatch(loadStart());
|
||||
try {
|
||||
const config = convertToRawConfig(options, getState());
|
||||
const result = await _importUri(uri, config);
|
||||
handleImportResult(result, 'The URI does not contain a valid specification.');
|
||||
} catch (err) {
|
||||
showModal(AlertModal, {
|
||||
title: 'Import Failed',
|
||||
message: err + '',
|
||||
});
|
||||
} finally {
|
||||
dispatch(loadStop());
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user