Filter out current variable from autocomplete and show sub environment variables in base environment autocomplete

This commit is contained in:
Gregory Schier
2025-09-29 06:57:04 -07:00
parent b9613591f8
commit 6abbdc8726
6 changed files with 41 additions and 21 deletions

View File

@@ -17,7 +17,7 @@ import { DismissibleBanner } from './core/DismissibleBanner';
import type { GenericCompletionConfig } from './core/Editor/genericCompletion'; import type { GenericCompletionConfig } from './core/Editor/genericCompletion';
import { Heading } from './core/Heading'; import { Heading } from './core/Heading';
import type { PairWithId } from './core/PairEditor'; import type { PairWithId } from './core/PairEditor';
import { ensurePairId } from './core/PairEditor'; import { ensurePairId } from './core/PairEditor.util';
import { PairOrBulkEditor } from './core/PairOrBulkEditor'; import { PairOrBulkEditor } from './core/PairOrBulkEditor';
import { VStack } from './core/Stacks'; import { VStack } from './core/Stacks';
import { EnvironmentColorIndicator } from './EnvironmentColorIndicator'; import { EnvironmentColorIndicator } from './EnvironmentColorIndicator';
@@ -151,7 +151,7 @@ export function EnvironmentEditor({
namePlaceholder="VAR_NAME" namePlaceholder="VAR_NAME"
nameValidate={validateName} nameValidate={validateName}
valueType={valueType} valueType={valueType}
valueAutocompleteVariables valueAutocompleteVariables='environment'
valueAutocompleteFunctions valueAutocompleteFunctions
forceUpdateKey={`${environment.id}::${forceUpdateKey}`} forceUpdateKey={`${environment.id}::${forceUpdateKey}`}
pairs={environment.variables} pairs={environment.variables}

View File

@@ -10,7 +10,8 @@ import { DetailsBanner } from './core/DetailsBanner';
import type { GenericCompletionConfig } from './core/Editor/genericCompletion'; import type { GenericCompletionConfig } from './core/Editor/genericCompletion';
import type { InputProps } from './core/Input'; import type { InputProps } from './core/Input';
import type { Pair, PairEditorProps } from './core/PairEditor'; import type { Pair, PairEditorProps } from './core/PairEditor';
import { ensurePairId, PairEditorRow } from './core/PairEditor'; import { PairEditorRow } from './core/PairEditor';
import { ensurePairId } from './core/PairEditor.util';
import { PairOrBulkEditor } from './core/PairOrBulkEditor'; import { PairOrBulkEditor } from './core/PairOrBulkEditor';
import { HStack } from './core/Stacks'; import { HStack } from './core/Stacks';

View File

@@ -66,7 +66,7 @@ export interface EditorProps {
autoSelect?: boolean; autoSelect?: boolean;
autocomplete?: GenericCompletionConfig; autocomplete?: GenericCompletionConfig;
autocompleteFunctions?: boolean; autocompleteFunctions?: boolean;
autocompleteVariables?: boolean; autocompleteVariables?: boolean | ((v: WrappedEnvironmentVariable) => boolean);
className?: string; className?: string;
defaultValue?: string | null; defaultValue?: string | null;
disableTabIndent?: boolean; disableTabIndent?: boolean;
@@ -138,8 +138,13 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
const settings = useAtomValue(settingsAtom); const settings = useAtomValue(settingsAtom);
const allEnvironmentVariables = useEnvironmentVariables(forcedEnvironmentId ?? null); const allEnvironmentVariables = useEnvironmentVariables(forcedEnvironmentId ?? null);
const environmentVariables = autocompleteVariables ? allEnvironmentVariables : emptyVariables;
const useTemplating = !!(autocompleteFunctions || autocompleteVariables || autocomplete); const useTemplating = !!(autocompleteFunctions || autocompleteVariables || autocomplete);
const environmentVariables = useMemo(() => {
if (!autocompleteVariables) return emptyVariables;
return typeof autocompleteVariables === 'function'
? allEnvironmentVariables.filter(autocompleteVariables)
: allEnvironmentVariables;
}, [allEnvironmentVariables, autocompleteVariables]);
if (settings && wrapLines === undefined) { if (settings && wrapLines === undefined) {
wrapLines = settings.editorSoftWrap; wrapLines = settings.editorSoftWrap;

View File

@@ -12,11 +12,11 @@ import {
} from 'react'; } from 'react';
import type { XYCoord } from 'react-dnd'; import type { XYCoord } from 'react-dnd';
import { useDrag, useDrop } from 'react-dnd'; import { useDrag, useDrop } from 'react-dnd';
import type { WrappedEnvironmentVariable } from '../../hooks/useEnvironmentVariables';
import { useRandomKey } from '../../hooks/useRandomKey'; import { useRandomKey } from '../../hooks/useRandomKey';
import { useToggle } from '../../hooks/useToggle'; import { useToggle } from '../../hooks/useToggle';
import { languageFromContentType } from '../../lib/contentType'; import { languageFromContentType } from '../../lib/contentType';
import { showDialog } from '../../lib/dialog'; import { showDialog } from '../../lib/dialog';
import { generateId } from '../../lib/generateId';
import { showPrompt } from '../../lib/prompt'; import { showPrompt } from '../../lib/prompt';
import { DropMarker } from '../DropMarker'; import { DropMarker } from '../DropMarker';
import { SelectFile } from '../SelectFile'; import { SelectFile } from '../SelectFile';
@@ -24,12 +24,14 @@ import { Button } from './Button';
import { Checkbox } from './Checkbox'; import { Checkbox } from './Checkbox';
import type { DropdownItem } from './Dropdown'; import type { DropdownItem } from './Dropdown';
import { Dropdown } from './Dropdown'; import { Dropdown } from './Dropdown';
import type { EditorProps } from './Editor/Editor';
import { Editor } from './Editor/Editor'; import { Editor } from './Editor/Editor';
import type { GenericCompletionConfig } from './Editor/genericCompletion'; import type { GenericCompletionConfig } from './Editor/genericCompletion';
import { Icon } from './Icon'; import { Icon } from './Icon';
import { IconButton } from './IconButton'; import { IconButton } from './IconButton';
import type { InputProps } from './Input'; import type { InputProps } from './Input';
import { Input } from './Input'; import { Input } from './Input';
import { ensurePairId } from './PairEditor.util';
import { PlainInput } from './PlainInput'; import { PlainInput } from './PlainInput';
import type { RadioDropdownItem } from './RadioDropdown'; import type { RadioDropdownItem } from './RadioDropdown';
import { RadioDropdown } from './RadioDropdown'; import { RadioDropdown } from './RadioDropdown';
@@ -55,7 +57,7 @@ export type PairEditorProps = {
stateKey: InputProps['stateKey']; stateKey: InputProps['stateKey'];
valueAutocomplete?: (name: string) => GenericCompletionConfig | undefined; valueAutocomplete?: (name: string) => GenericCompletionConfig | undefined;
valueAutocompleteFunctions?: boolean; valueAutocompleteFunctions?: boolean;
valueAutocompleteVariables?: boolean; valueAutocompleteVariables?: boolean | 'environment';
valuePlaceholder?: string; valuePlaceholder?: string;
valueType?: InputProps['type'] | ((pair: Pair) => InputProps['type']); valueType?: InputProps['type'] | ((pair: Pair) => InputProps['type']);
valueValidate?: InputProps['validate']; valueValidate?: InputProps['validate'];
@@ -471,6 +473,15 @@ export function PairEditorRow({
[pair, onEnd], [pair, onEnd],
); );
// Filter out the current pair name
const valueAutocompleteVariablesFiltered = useMemo<EditorProps['autocompleteVariables']>(() => {
if (valueAutocompleteVariables === 'environment') {
return (v: WrappedEnvironmentVariable): boolean => v.variable.name !== pair.name;
} else {
return valueAutocompleteVariables;
}
}, [pair.name, valueAutocompleteVariables]);
connectDrag(ref); connectDrag(ref);
connectDrop(ref); connectDrop(ref);
@@ -601,7 +612,7 @@ export function PairEditorRow({
placeholder={valuePlaceholder ?? 'value'} placeholder={valuePlaceholder ?? 'value'}
autocomplete={valueAutocomplete?.(pair.name)} autocomplete={valueAutocomplete?.(pair.name)}
autocompleteFunctions={valueAutocompleteFunctions} autocompleteFunctions={valueAutocompleteFunctions}
autocompleteVariables={valueAutocompleteVariables} autocompleteVariables={valueAutocompleteVariablesFiltered}
/> />
)} )}
</div> </div>
@@ -761,12 +772,3 @@ function MultilineEditDialog({
</div> </div>
); );
} }
// eslint-disable-next-line react-refresh/only-export-components
export function ensurePairId(p: Pair): PairWithId {
if (typeof p.id === 'string') {
return p as PairWithId;
} else {
return { ...p, id: p.id ?? generateId() };
}
}

View File

@@ -0,0 +1,10 @@
import { generateId } from '../../lib/generateId';
import type { Pair, PairWithId } from './PairEditor';
export function ensurePairId(p: Pair): PairWithId {
if (typeof p.id === 'string') {
return p as PairWithId;
} else {
return { ...p, id: p.id ?? generateId() };
}
}

View File

@@ -3,7 +3,7 @@ import { foldersAtom } from '@yaakapp-internal/models';
import { useAtomValue } from 'jotai'; import { useAtomValue } from 'jotai';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { jotaiStore } from '../lib/jotai'; import { jotaiStore } from '../lib/jotai';
import { isFolderEnvironment } from '../lib/model_util'; import { isBaseEnvironment, isFolderEnvironment } from '../lib/model_util';
import { useActiveEnvironment } from './useActiveEnvironment'; import { useActiveEnvironment } from './useActiveEnvironment';
import { useActiveRequest } from './useActiveRequest'; import { useActiveRequest } from './useActiveRequest';
import { useEnvironmentsBreakdown } from './useEnvironmentsBreakdown'; import { useEnvironmentsBreakdown } from './useEnvironmentsBreakdown';
@@ -24,11 +24,13 @@ export function useEnvironmentVariables(targetEnvironmentId: string | null) {
wrapVariables(folderEnvironments.find((fe) => fe.parentId === f.id) ?? null), wrapVariables(folderEnvironments.find((fe) => fe.parentId === f.id) ?? null),
); );
// Folder environments also can auto-complete from the active environment // Add active environment variables to everything except sub environments
const activeEnvironmentVariables = const activeEnvironmentVariables =
targetEnvironment == null || isFolderEnvironment(targetEnvironment) targetEnvironment == null || // Editing request
isFolderEnvironment(targetEnvironment) || // Editing folder variables
isBaseEnvironment(targetEnvironment) // Editing global variables
? wrapVariables(activeEnvironment) ? wrapVariables(activeEnvironment)
: []; : wrapVariables(targetEnvironment); // Add own variables for sub environments
const allVariables = [ const allVariables = [
...folderVariables, ...folderVariables,