diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index ce004d3e..96606d78 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1002,8 +1002,11 @@ async fn cmd_export_data( window: WebviewWindow, export_path: &str, workspace_ids: Vec<&str>, + include_environments: bool, ) -> Result<(), String> { - let export_data = get_workspace_export_resources(window.app_handle(), workspace_ids).await; + let export_data = get_workspace_export_resources(&window, workspace_ids, include_environments) + .await + .map_err(|e| e.to_string())?; let f = File::options() .create(true) .truncate(true) diff --git a/src-tauri/yaak-models/src/queries.rs b/src-tauri/yaak-models/src/queries.rs index 8bdc75cc..87d7745b 100644 --- a/src-tauri/yaak-models/src/queries.rs +++ b/src-tauri/yaak-models/src/queries.rs @@ -2175,7 +2175,8 @@ pub async fn batch_upsert( pub async fn get_workspace_export_resources( mgr: &impl Manager, workspace_ids: Vec<&str>, -) -> WorkspaceExport { + include_environments: bool, +) -> Result { let mut data = WorkspaceExport { yaak_version: mgr.package_info().version.clone().to_string(), yaak_schema: 2, @@ -2190,24 +2191,19 @@ pub async fn get_workspace_export_resources( }; for workspace_id in workspace_ids { - data.resources - .workspaces - .push(get_workspace(mgr, workspace_id).await.expect("Failed to get workspace")); - data.resources.environments.append( - &mut list_environments(mgr, workspace_id).await.expect("Failed to get environments"), - ); - data.resources - .folders - .append(&mut list_folders(mgr, workspace_id).await.expect("Failed to get folders")); - data.resources.http_requests.append( - &mut list_http_requests(mgr, workspace_id).await.expect("Failed to get http requests"), - ); - data.resources.grpc_requests.append( - &mut list_grpc_requests(mgr, workspace_id).await.expect("Failed to get grpc requests"), - ); + data.resources.workspaces.push(get_workspace(mgr, workspace_id).await?); + data.resources.environments.append(&mut list_environments(mgr, workspace_id).await?); + data.resources.folders.append(&mut list_folders(mgr, workspace_id).await?); + data.resources.http_requests.append(&mut list_http_requests(mgr, workspace_id).await?); + data.resources.grpc_requests.append(&mut list_grpc_requests(mgr, workspace_id).await?); } - data + // Nuke environments if we don't want them + if !include_environments { + data.resources.environments.clear(); + } + + Ok(data) } // Generate the created_at or updated_at timestamps for an upsert operation, depending on the ID diff --git a/src-tauri/yaak-sync/src/error.rs b/src-tauri/yaak-sync/src/error.rs index 3e183ac4..b82a9a80 100644 --- a/src-tauri/yaak-sync/src/error.rs +++ b/src-tauri/yaak-sync/src/error.rs @@ -13,9 +13,6 @@ pub enum Error { #[error("Unknown model: {0}")] UnknownModel(String), - #[error("Workspace not configured for sync: {0}")] - WorkspaceSyncNotConfigured(String), - #[error("I/o error: {0}")] IoError(#[from] io::Error), @@ -24,7 +21,7 @@ pub enum Error { #[error("Invalid sync file: {0}")] InvalidSyncFile(String), - + #[error("Watch error: {0}")] NotifyError(#[from] notify::Error), } diff --git a/src-tauri/yaak-sync/src/sync.rs b/src-tauri/yaak-sync/src/sync.rs index 602f7f1e..663ff61c 100644 --- a/src-tauri/yaak-sync/src/sync.rs +++ b/src-tauri/yaak-sync/src/sync.rs @@ -111,7 +111,7 @@ pub(crate) async fn get_db_candidates( sync_dir: &Path, ) -> Result> { let models: HashMap<_, _> = - workspace_models(mgr, workspace_id).await.into_iter().map(|m| (m.id(), m)).collect(); + workspace_models(mgr, workspace_id).await?.into_iter().map(|m| (m.id(), m)).collect(); let sync_states: HashMap<_, _> = list_sync_states_for_workspace(mgr, workspace_id, sync_dir) .await? .into_iter() @@ -270,12 +270,15 @@ pub(crate) fn compute_sync_ops( .collect() } -async fn workspace_models(mgr: &impl Manager, workspace_id: &str) -> Vec { - let resources = get_workspace_export_resources(mgr, vec![workspace_id]).await.resources; +async fn workspace_models( + mgr: &impl Manager, + workspace_id: &str, +) -> Result> { + let resources = get_workspace_export_resources(mgr, vec![workspace_id], true).await?.resources; let workspace = resources.workspaces.iter().find(|w| w.id == workspace_id); let workspace = match workspace { - None => return Vec::new(), + None => return Ok(Vec::new()), Some(w) => w, }; @@ -294,7 +297,7 @@ async fn workspace_models(mgr: &impl Manager, workspace_id: &str) sync_models.push(SyncModel::GrpcRequest(m)); } - sync_models + Ok(sync_models) } pub(crate) async fn apply_sync_ops( diff --git a/src-web/components/CommandPaletteDialog.tsx b/src-web/components/CommandPaletteDialog.tsx index ff9b35d8..c67bdcc2 100644 --- a/src-web/components/CommandPaletteDialog.tsx +++ b/src-web/components/CommandPaletteDialog.tsx @@ -420,7 +420,7 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
{filteredGroups.map((g) => (
- + {g.label} {g.items.map((v) => ( diff --git a/src-web/components/ExportDataDialog.tsx b/src-web/components/ExportDataDialog.tsx index a5f2ebc1..69f73e1c 100644 --- a/src-web/components/ExportDataDialog.tsx +++ b/src-web/components/ExportDataDialog.tsx @@ -6,6 +6,7 @@ import { useActiveWorkspace } from '../hooks/useActiveWorkspace'; import { useWorkspaces } from '../hooks/useWorkspaces'; import { pluralizeCount } from '../lib/pluralize'; import { invokeCmd } from '../lib/tauri'; +import { Banner } from './core/Banner'; import { Button } from './core/Button'; import { Checkbox } from './core/Checkbox'; import { HStack, VStack } from './core/Stacks'; @@ -39,6 +40,7 @@ function ExportDataDialogContent({ allWorkspaces: Workspace[]; activeWorkspace: Workspace; }) { + const [includeEnvironments, setIncludeEnvironments] = useState(true); const [selectedWorkspaces, setSelectedWorkspaces] = useState>({ [activeWorkspace.id]: true, }); @@ -67,10 +69,14 @@ function ExportDataDialogContent({ return; } - await invokeCmd('cmd_export_data', { workspaceIds: ids, exportPath }); + await invokeCmd('cmd_export_data', { + workspaceIds: ids, + exportPath, + includeEnvironments: includeEnvironments, + }); onHide(); onSuccess(exportPath); - }, [onHide, onSuccess, selectedWorkspaces, workspaces]); + }, [includeEnvironments, onHide, onSuccess, selectedWorkspaces, workspaces]); const allSelected = workspaces.every((w) => selectedWorkspaces[w.id]); const numSelected = Object.values(selectedWorkspaces).filter(Boolean).length; @@ -117,6 +123,18 @@ function ExportDataDialogContent({ ))} + +
+ Extra Settings +
+ +
+
+
diff --git a/src-web/components/Settings/SettingsGeneral.tsx b/src-web/components/Settings/SettingsGeneral.tsx index 8c5852ec..86f24441 100644 --- a/src-web/components/Settings/SettingsGeneral.tsx +++ b/src-web/components/Settings/SettingsGeneral.tsx @@ -89,7 +89,7 @@ export function SettingsGeneral() { - + Workspace{' '}
{workspace.name} @@ -134,7 +134,7 @@ export function SettingsGeneral() { - App Info + App Info {appInfo.version} {title ? ( - + {title} ) : ( diff --git a/src-web/components/core/Heading.tsx b/src-web/components/core/Heading.tsx index 148a840e..a53945a0 100644 --- a/src-web/components/core/Heading.tsx +++ b/src-web/components/core/Heading.tsx @@ -2,19 +2,19 @@ import classNames from 'classnames'; import type { HTMLAttributes } from 'react'; interface Props extends HTMLAttributes { - size?: 1 | 2 | 3; + level?: 1 | 2 | 3; } -export function Heading({ className, size = 1, ...props }: Props) { - const Component = size === 1 ? 'h1' : size === 2 ? 'h2' : 'h3'; +export function Heading({ className, level = 1, ...props }: Props) { + const Component = level === 1 ? 'h1' : level === 2 ? 'h2' : 'h3'; return ( diff --git a/src-web/hooks/useExportData.tsx b/src-web/hooks/useExportData.tsx index ca0437e1..50257ec7 100644 --- a/src-web/hooks/useExportData.tsx +++ b/src-web/hooks/useExportData.tsx @@ -21,7 +21,7 @@ export function useExportData() { showDialog({ id: 'export-data', - title: 'Export App Data', + title: 'Export Data', size: 'md', noPadding: true, render: ({ hide }) => (