Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 19 additions & 11 deletions src-web/components/ImportDataDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import { open } from '@tauri-apps/plugin-dialog';
import { useState } from 'react';
import { useLocalStorage } from 'react-use';
import { Button } from './core/Button';
import { VStack } from './core/Stacks';
import { SelectFile } from './SelectFile';

interface Props {
importData: (filePath: string) => Promise<void>;
importData: (filePaths: string[]) => Promise<void>;
}

export function ImportDataDialog({ importData }: Props) {
const [isLoading, setIsLoading] = useState<boolean>(false);
const [filePath, setFilePath] = useLocalStorage<string | null>('importFilePath', null);
const [filePaths, setFilePaths] = useState<string[]>([]);

const handleSelectFiles = async () => {
const result = await open({ title: 'Select File(s)', multiple: true });
if (result == null) return;
setFilePaths(Array.isArray(result) ? result : [result]);
};

const fileCount = filePaths.length;

return (
<VStack space={5} className="pb-4">
Expand All @@ -26,20 +33,21 @@ export function ImportDataDialog({ importData }: Props) {
</ul>
</VStack>
<VStack space={2}>
<SelectFile
filePath={filePath ?? null}
onChange={({ filePath }) => setFilePath(filePath)}
/>
{filePath && (
<Button color="secondary" size="sm" onClick={handleSelectFiles}>
{fileCount > 0
? `${fileCount} file${fileCount !== 1 ? 's' : ''} selected`
: 'Select File(s)'}
</Button>
{fileCount > 0 && (
<Button
color="primary"
disabled={!filePath || isLoading}
disabled={isLoading}
isLoading={isLoading}
size="sm"
onClick={async () => {
setIsLoading(true);
try {
await importData(filePath);
await importData(filePaths);
} finally {
setIsLoading(false);
}
Expand Down
60 changes: 39 additions & 21 deletions src-web/lib/importData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ export const importData = createFastMutation({
title: 'Import Data',
size: 'sm',
render: ({ hide }) => {
const importAndHide = async (filePath: string) => {
const importAndHide = async (filePaths: string[]) => {
try {
const didImport = await performImport(filePath);
const didImport = await performImport(filePaths);
if (!didImport) {
return;
}
Expand All @@ -49,14 +49,32 @@ export const importData = createFastMutation({
},
});

async function performImport(filePath: string): Promise<boolean> {
async function performImport(filePaths: string[]): Promise<boolean> {
const activeWorkspace = jotaiStore.get(activeWorkspaceAtom);
const imported = await invokeCmd<BatchUpsertResult>('cmd_import_data', {
filePath,
workspaceId: activeWorkspace?.id,
});

const importedWorkspace = imported.workspaces[0];
const combined: BatchUpsertResult = {
workspaces: [],
environments: [],
folders: [],
httpRequests: [],
grpcRequests: [],
websocketRequests: [],
};

for (const filePath of filePaths) {
const imported = await invokeCmd<BatchUpsertResult>('cmd_import_data', {
filePath,
workspaceId: activeWorkspace?.id,
});
combined.workspaces.push(...imported.workspaces);
combined.environments.push(...imported.environments);
combined.folders.push(...imported.folders);
combined.httpRequests.push(...imported.httpRequests);
combined.grpcRequests.push(...imported.grpcRequests);
combined.websocketRequests.push(...imported.websocketRequests);
}

const importedWorkspace = combined.workspaces[0];

showDialog({
id: 'import-complete',
Expand All @@ -67,23 +85,23 @@ async function performImport(filePath: string): Promise<boolean> {
return (
<VStack space={3} className="pb-4">
<ul className="list-disc pl-6">
{imported.workspaces.length > 0 && (
<li>{pluralizeCount('Workspace', imported.workspaces.length)}</li>
{combined.workspaces.length > 0 && (
<li>{pluralizeCount('Workspace', combined.workspaces.length)}</li>
)}
{imported.environments.length > 0 && (
<li>{pluralizeCount('Environment', imported.environments.length)}</li>
{combined.environments.length > 0 && (
<li>{pluralizeCount('Environment', combined.environments.length)}</li>
)}
{imported.folders.length > 0 && (
<li>{pluralizeCount('Folder', imported.folders.length)}</li>
{combined.folders.length > 0 && (
<li>{pluralizeCount('Folder', combined.folders.length)}</li>
)}
{imported.httpRequests.length > 0 && (
<li>{pluralizeCount('HTTP Request', imported.httpRequests.length)}</li>
{combined.httpRequests.length > 0 && (
<li>{pluralizeCount('HTTP Request', combined.httpRequests.length)}</li>
)}
{imported.grpcRequests.length > 0 && (
<li>{pluralizeCount('GRPC Request', imported.grpcRequests.length)}</li>
{combined.grpcRequests.length > 0 && (
<li>{pluralizeCount('GRPC Request', combined.grpcRequests.length)}</li>
)}
{imported.websocketRequests.length > 0 && (
<li>{pluralizeCount('Websocket Request', imported.websocketRequests.length)}</li>
{combined.websocketRequests.length > 0 && (
<li>{pluralizeCount('Websocket Request', combined.websocketRequests.length)}</li>
)}
</ul>
<div>
Expand All @@ -97,7 +115,7 @@ async function performImport(filePath: string): Promise<boolean> {
});

if (importedWorkspace != null) {
const environmentId = imported.environments[0]?.id ?? null;
const environmentId = combined.environments[0]?.id ?? null;
await router.navigate({
to: '/workspaces/$workspaceId',
params: { workspaceId: importedWorkspace.id },
Expand Down