From 73c366dc27514b01092e2ebd09fe6bb7e91ac7b1 Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Fri, 16 May 2025 09:12:36 -0700 Subject: [PATCH] Hopefully fix weird env routing issue --- src-web/commands/createEnvironment.ts | 51 ++++++++++++++++++++ src-web/components/CommandPaletteDialog.tsx | 6 +-- src-web/components/EnvironmentEditDialog.tsx | 45 +++++++++-------- src-web/hooks/useCreateEnvironment.ts | 50 ------------------- 4 files changed, 77 insertions(+), 75 deletions(-) create mode 100644 src-web/commands/createEnvironment.ts delete mode 100644 src-web/hooks/useCreateEnvironment.ts diff --git a/src-web/commands/createEnvironment.ts b/src-web/commands/createEnvironment.ts new file mode 100644 index 00000000..9a12a5d0 --- /dev/null +++ b/src-web/commands/createEnvironment.ts @@ -0,0 +1,51 @@ +import { createWorkspaceModel, type Environment } from '@yaakapp-internal/models'; +import { activeWorkspaceIdAtom } from '../hooks/useActiveWorkspace'; +import { createFastMutation } from '../hooks/useFastMutation'; +import { jotaiStore } from '../lib/jotai'; +import { showPrompt } from '../lib/prompt'; +import { setWorkspaceSearchParams } from '../lib/setWorkspaceSearchParams'; + +export const createEnvironmentAndActivate = createFastMutation< + string | null, + unknown, + Environment | null +>({ + mutationKey: ['create_environment'], + mutationFn: async (baseEnvironment) => { + if (baseEnvironment == null) { + throw new Error('No base environment passed'); + } + + const workspaceId = jotaiStore.get(activeWorkspaceIdAtom); + if (workspaceId == null) { + throw new Error('Cannot create environment when no active workspace'); + } + + const name = await showPrompt({ + id: 'new-environment', + title: 'New Environment', + description: 'Create multiple environments with different sets of variables', + label: 'Name', + placeholder: 'My Environment', + defaultValue: 'My Environment', + confirmText: 'Create', + }); + if (name == null) return null; + + return createWorkspaceModel({ + model: 'environment', + name, + variables: [], + workspaceId, + base: false, + }); + }, + onSuccess: async (environmentId) => { + if (environmentId == null) { + return; // Was not created + } + + console.log('NAVIGATING', jotaiStore.get(activeWorkspaceIdAtom), environmentId); + setWorkspaceSearchParams({ environment_id: environmentId }); + }, +}); diff --git a/src-web/components/CommandPaletteDialog.tsx b/src-web/components/CommandPaletteDialog.tsx index 1faa3067..1010a045 100644 --- a/src-web/components/CommandPaletteDialog.tsx +++ b/src-web/components/CommandPaletteDialog.tsx @@ -5,6 +5,7 @@ import { useAtomValue } from 'jotai'; import type { KeyboardEvent, ReactNode } from 'react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { createFolder } from '../commands/commands'; +import { createEnvironmentAndActivate } from '../commands/createEnvironment'; import { openSettings } from '../commands/openSettings'; import { switchWorkspace } from '../commands/switchWorkspace'; import { useActiveCookieJar } from '../hooks/useActiveCookieJar'; @@ -12,7 +13,6 @@ import { useActiveEnvironment } from '../hooks/useActiveEnvironment'; import { useActiveRequest } from '../hooks/useActiveRequest'; import { activeWorkspaceIdAtom } from '../hooks/useActiveWorkspace'; import { useAllRequests } from '../hooks/useAllRequests'; -import { useCreateEnvironment } from '../hooks/useCreateEnvironment'; import { useCreateWorkspace } from '../hooks/useCreateWorkspace'; import { useDebouncedState } from '../hooks/useDebouncedState'; import { useEnvironmentsBreakdown } from '../hooks/useEnvironmentsBreakdown'; @@ -72,7 +72,6 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) { const activeCookieJar = useActiveCookieJar(); const [recentRequests] = useRecentRequests(); const [, setSidebarHidden] = useSidebarHidden(); - const { mutate: createEnvironment } = useCreateEnvironment(); const { mutate: sendRequest } = useSendAnyHttpRequest(); const workspaceCommands = useMemo(() => { @@ -139,7 +138,7 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) { { key: 'environment.create', label: 'Create Environment', - onSelect: () => createEnvironment(baseEnvironment), + onSelect: () => createEnvironmentAndActivate.mutate(baseEnvironment), }, { key: 'sidebar.toggle', @@ -190,7 +189,6 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) { activeEnvironment, activeRequest, baseEnvironment, - createEnvironment, createWorkspace, httpRequestActions, sendRequest, diff --git a/src-web/components/EnvironmentEditDialog.tsx b/src-web/components/EnvironmentEditDialog.tsx index d9bccdfe..f8d772ad 100644 --- a/src-web/components/EnvironmentEditDialog.tsx +++ b/src-web/components/EnvironmentEditDialog.tsx @@ -4,7 +4,7 @@ import type { GenericCompletionOption } from '@yaakapp-internal/plugins'; import classNames from 'classnames'; import type { ReactNode } from 'react'; import React, { useCallback, useMemo, useState } from 'react'; -import { useCreateEnvironment } from '../hooks/useCreateEnvironment'; +import { createEnvironmentAndActivate } from '../commands/createEnvironment'; import { useEnvironmentsBreakdown } from '../hooks/useEnvironmentsBreakdown'; import { useIsEncryptionEnabled } from '../hooks/useIsEncryptionEnabled'; import { useKeyValue } from '../hooks/useKeyValue'; @@ -41,7 +41,6 @@ interface Props { } export const EnvironmentEditDialog = function ({ initialEnvironment }: Props) { - const createEnvironment = useCreateEnvironment(); const { baseEnvironment, otherBaseEnvironments, subEnvironments, allEnvironments } = useEnvironmentsBreakdown(); const [selectedEnvironmentId, setSelectedEnvironmentId] = useState( @@ -55,7 +54,7 @@ export const EnvironmentEditDialog = function ({ initialEnvironment }: Props) { const handleCreateEnvironment = async () => { if (baseEnvironment == null) return; - const id = await createEnvironment.mutateAsync(baseEnvironment); + const id = await createEnvironmentAndActivate.mutateAsync(baseEnvironment); if (id != null) setSelectedEnvironmentId(id); }; @@ -162,30 +161,30 @@ export const EnvironmentEditDialog = function ({ initialEnvironment }: Props) { }; const EnvironmentEditor = function ({ - environment: activeEnvironment, + environment: selectedEnvironment, className, }: { environment: Environment; className?: string; }) { - const activeWorkspaceId = activeEnvironment.workspaceId; + const workspaceId = selectedEnvironment.workspaceId; const isEncryptionEnabled = useIsEncryptionEnabled(); const valueVisibility = useKeyValue({ namespace: 'global', - key: ['environmentValueVisibility', activeWorkspaceId], + key: ['environmentValueVisibility', workspaceId], fallback: false, }); const { allEnvironments } = useEnvironmentsBreakdown(); const handleChange = useCallback( - (variables: PairWithId[]) => patchModel(activeEnvironment, { variables }), - [activeEnvironment], + (variables: PairWithId[]) => patchModel(selectedEnvironment, { variables }), + [selectedEnvironment], ); const [forceUpdateKey, regenerateForceUpdateKey] = useRandomKey(); // Gather a list of env names from other environments to help the user get them aligned const nameAutocomplete = useMemo(() => { const options: GenericCompletionOption[] = []; - if (activeEnvironment.base) { + if (selectedEnvironment.base) { return { options }; } @@ -195,7 +194,7 @@ const EnvironmentEditor = function ({ const containingEnvs = allEnvironments.filter((e) => e.variables.some((v) => v.name === name), ); - const isAlreadyInActive = containingEnvs.find((e) => e.id === activeEnvironment.id); + const isAlreadyInActive = containingEnvs.find((e) => e.id === selectedEnvironment.id); if (isAlreadyInActive) continue; options.push({ label: name, @@ -204,7 +203,7 @@ const EnvironmentEditor = function ({ }); } return { options }; - }, [activeEnvironment.base, activeEnvironment.id, allEnvironments]); + }, [selectedEnvironment.base, selectedEnvironment.id, allEnvironments]); const validateName = useCallback((name: string) => { // Empty just means the variable doesn't have a name yet and is unusable @@ -217,11 +216,11 @@ const EnvironmentEditor = function ({ if (!isEncryptionEnabled) { return true; } else { - return !activeEnvironment.variables.every( + return !selectedEnvironment.variables.every( (v) => v.value === '' || analyzeTemplate(v.value) !== 'insecure', ); } - }, [activeEnvironment.variables, isEncryptionEnabled]); + }, [selectedEnvironment.variables, isEncryptionEnabled]); const encryptEnvironment = (environment: Environment) => { withEncryptionEnabled(async () => { @@ -238,10 +237,10 @@ const EnvironmentEditor = function ({ return ( -
{activeEnvironment?.name}
+
{selectedEnvironment?.name}
{isEncryptionEnabled ? ( promptToEncrypt ? ( - encryptEnvironment(activeEnvironment)}> + encryptEnvironment(selectedEnvironment)}> Encrypt All Variables ) : ( @@ -257,9 +256,9 @@ const EnvironmentEditor = function ({ )}
- {activeEnvironment.public && promptToEncrypt && ( + {selectedEnvironment.public && promptToEncrypt && ( @@ -277,11 +276,15 @@ const EnvironmentEditor = function ({ valueType={valueType} valueAutocompleteVariables valueAutocompleteFunctions - forcedEnvironmentId={activeEnvironment.id} - forceUpdateKey={`${activeEnvironment.id}::${forceUpdateKey}`} - pairs={activeEnvironment.variables} + forceUpdateKey={`${selectedEnvironment.id}::${forceUpdateKey}`} + pairs={selectedEnvironment.variables} onChange={handleChange} - stateKey={`environment.${activeEnvironment.id}`} + stateKey={`environment.${selectedEnvironment.id}`} + forcedEnvironmentId={ + // Editing the base environment should resolve variables using the active environment. + // Editing a sub environment should resolve variables as if it's the active environment + selectedEnvironment.base ? undefined : selectedEnvironment.id + } />
diff --git a/src-web/hooks/useCreateEnvironment.ts b/src-web/hooks/useCreateEnvironment.ts deleted file mode 100644 index 34f4a923..00000000 --- a/src-web/hooks/useCreateEnvironment.ts +++ /dev/null @@ -1,50 +0,0 @@ -import type { Environment } from '@yaakapp-internal/models'; -import { createWorkspaceModel } from '@yaakapp-internal/models'; -import { useAtomValue } from 'jotai'; -import { showPrompt } from '../lib/prompt'; -import { setWorkspaceSearchParams } from '../lib/setWorkspaceSearchParams'; -import { activeWorkspaceIdAtom } from './useActiveWorkspace'; -import { useFastMutation } from './useFastMutation'; - -export function useCreateEnvironment() { - const workspaceId = useAtomValue(activeWorkspaceIdAtom); - - return useFastMutation({ - mutationKey: ['create_environment', workspaceId], - mutationFn: async (baseEnvironment) => { - if (baseEnvironment == null) { - throw new Error('No base environment passed'); - } - - if (workspaceId == null) { - throw new Error('Cannot create environment when no active workspace'); - } - - const name = await showPrompt({ - id: 'new-environment', - title: 'New Environment', - description: 'Create multiple environments with different sets of variables', - label: 'Name', - placeholder: 'My Environment', - defaultValue: 'My Environment', - confirmText: 'Create', - }); - if (name == null) return null; - - return createWorkspaceModel({ - model: 'environment', - name, - variables: [], - workspaceId, - base: false, - }); - }, - onSuccess: async (environmentId) => { - if (environmentId == null) { - return; // Was not created - } - - setWorkspaceSearchParams({ environment_id: environmentId }); - }, - }); -}