diff --git a/src-web/components/EnvironmentEditDialog.tsx b/src-web/components/EnvironmentEditDialog.tsx index 589e43e2..a0630b05 100644 --- a/src-web/components/EnvironmentEditDialog.tsx +++ b/src-web/components/EnvironmentEditDialog.tsx @@ -180,6 +180,7 @@ const EnvironmentEditor = function ({
{ return pairs .filter((p) => !(p.name.trim() === '' && p.value.trim() === '')) - .map((p) => `${p.name}: ${p.value}`) + .map(pairToLine) .join('\n'); }, [pairs]); @@ -45,12 +45,17 @@ export function BulkPairEditor({ ); } +function pairToLine(pair: Pair) { + const value = pair.value.replaceAll('\n', '\\n'); + return `${pair.name}: ${value}`; +} + function lineToPair(line: string): PairWithId { const [, name, value] = line.match(/^(:?[^:]+):\s+(.*)$/) ?? []; return { enabled: true, name: (name ?? '').trim(), - value: (value ?? '').trim(), + value: (value ?? '').replaceAll('\\n', '\n').trim(), id: generateId(), }; } diff --git a/src-web/components/core/PairEditor.tsx b/src-web/components/core/PairEditor.tsx index fc960b92..1fb82078 100644 --- a/src-web/components/core/PairEditor.tsx +++ b/src-web/components/core/PairEditor.tsx @@ -1,4 +1,3 @@ -import { formatSize } from '@yaakapp-internal/lib/formatSize'; import classNames from 'classnames'; import type { EditorView } from 'codemirror'; import { @@ -24,7 +23,6 @@ import { Button } from './Button'; import { Checkbox } from './Checkbox'; import type { DropdownItem } from './Dropdown'; import { Dropdown } from './Dropdown'; -import type { EditorProps } from './Editor/Editor'; import { Editor } from './Editor/Editor'; import type { GenericCompletionConfig } from './Editor/genericCompletion'; import { Icon } from './Icon'; @@ -41,6 +39,7 @@ export interface PairEditorRef { export type PairEditorProps = { allowFileValues?: boolean; + allowMultilineValues?: boolean; className?: string; forceUpdateKey?: string; nameAutocomplete?: GenericCompletionConfig; @@ -79,6 +78,7 @@ export const PairEditor = forwardRef(function Pa { stateKey, allowFileValues, + allowMultilineValues, className, forceUpdateKey, nameAutocomplete, @@ -229,6 +229,7 @@ export const PairEditor = forwardRef(function Pa {hoveredIndex === i && } (function Pa ); })} {!showAll && pairs.length > MAX_INITIAL_PAIRS && ( - )} @@ -289,6 +285,7 @@ type PairEditorRowProps = { } & Pick< PairEditorProps, | 'allowFileValues' + | 'allowMultilineValues' | 'forceUpdateKey' | 'nameAutocomplete' | 'nameAutocompleteVariables' @@ -304,6 +301,7 @@ type PairEditorRowProps = { function PairEditorRow({ allowFileValues, + allowMultilineValues, className, forceFocusNamePairId, forceFocusValuePairId, @@ -330,7 +328,6 @@ function PairEditorRow({ const ref = useRef(null); const nameInputRef = useRef(null); const valueInputRef = useRef(null); - const valueLanguage = languageFromContentType(pair.contentType ?? null); useEffect(() => { if (forceFocusNamePairId === pair.id) { @@ -347,17 +344,6 @@ function PairEditorRow({ const handleFocus = useCallback(() => onFocus?.(pair), [onFocus, pair]); const handleDelete = useCallback(() => onDelete?.(pair, false), [onDelete, pair]); - const deleteItems = useMemo( - (): DropdownItem[] => [ - { - label: 'Delete', - onSelect: handleDelete, - color: 'danger', - }, - ], - [handleDelete], - ); - const handleChangeEnabled = useMemo( () => (enabled: boolean) => onChange({ ...pair, enabled }), [onChange, pair], @@ -396,11 +382,27 @@ function PairEditorRow({ hide={hide} onChange={handleChangeValueText} defaultValue={pair.value} - language={valueLanguage} + contentType={pair.contentType ?? null} /> ), }), - [handleChangeValueText, pair.name, pair.value, valueLanguage], + [handleChangeValueText, pair.contentType, pair.name, pair.value], + ); + + const defaultItems = useMemo( + (): DropdownItem[] => [ + { + label: 'Edit Multi-line', + onSelect: handleEditMultiLineValue, + hidden: !allowMultilineValues, + }, + { + label: 'Delete', + onSelect: handleDelete, + color: 'danger', + }, + ], + [allowMultilineValues, handleDelete, handleEditMultiLineValue], ); const [, connectDrop] = useDrop( @@ -524,8 +526,9 @@ function PairEditorRow({ size="sm" onClick={handleEditMultiLineValue} title={pair.value} + className="text-xs font-mono" > - Edit {formatSize(pair.value.length)} + {pair.value.split('\n').join(' ')} ) : ( ) : ( - + , + color: 'danger', }, ], [editMultiLine, onChangeContentType, onChangeFile, onDelete, pair.contentType, pair.isFile], @@ -673,16 +676,17 @@ function isPairEmpty(pair: Pair): boolean { function MultilineEditDialog({ defaultValue, - language, + contentType, onChange, hide, }: { defaultValue: string; - language: EditorProps['language']; + contentType: string | null; onChange: (value: string) => void; hide: () => void; }) { const [value, setValue] = useState(defaultValue); + const language = languageFromContentType(contentType, value); return (