import type { Environment } from '@yaakapp-internal/models'; import { duplicateModel, patchModel } from '@yaakapp-internal/models'; import classNames from 'classnames'; import type { ReactNode } from 'react'; import React, { useCallback, useState } from 'react'; import { createSubEnvironmentAndActivate } from '../commands/createEnvironment'; import { useEnvironmentsBreakdown } from '../hooks/useEnvironmentsBreakdown'; import { deleteModelWithConfirm } from '../lib/deleteModelWithConfirm'; import { isBaseEnvironment } from '../lib/model_util'; import { showPrompt } from '../lib/prompt'; import { resolvedModelName } from '../lib/resolvedModelName'; import { showColorPicker } from '../lib/showColorPicker'; import { Banner } from './core/Banner'; import { Button } from './core/Button'; import type { DropdownItem } from './core/Dropdown'; import { ContextMenu } from './core/Dropdown'; import { Icon } from './core/Icon'; import { IconButton } from './core/IconButton'; import { IconTooltip } from './core/IconTooltip'; import { InlineCode } from './core/InlineCode'; import { Separator } from './core/Separator'; import { SplitLayout } from './core/SplitLayout'; import { EnvironmentColorIndicator } from './EnvironmentColorIndicator'; import { EnvironmentEditor } from './EnvironmentEditor'; import { EnvironmentSharableTooltip } from './EnvironmentSharableTooltip'; interface Props { initialEnvironment: Environment | null; } export const EnvironmentEditDialog = function ({ initialEnvironment }: Props) { const { baseEnvironment, otherBaseEnvironments, subEnvironments, allEnvironments } = useEnvironmentsBreakdown(); const [selectedEnvironmentId, setSelectedEnvironmentId] = useState( initialEnvironment?.id ?? null, ); const selectedEnvironment = selectedEnvironmentId != null ? allEnvironments.find((e) => e.id === selectedEnvironmentId) : baseEnvironment; const handleCreateEnvironment = async () => { if (baseEnvironment == null) return; const id = await createSubEnvironmentAndActivate.mutateAsync(baseEnvironment); if (id != null) setSelectedEnvironmentId(id); }; const handleDuplicateEnvironment = useCallback(async (environment: Environment) => { const name = await showPrompt({ id: 'duplicate-environment', title: 'Duplicate Environment', label: 'Name', defaultValue: environment.name, }); if (name) { const newId = await duplicateModel({ ...environment, name, public: false }); setSelectedEnvironmentId(newId); } }, []); const handleDeleteEnvironment = useCallback( async (environment: Environment) => { await deleteModelWithConfirm(environment); if (selectedEnvironmentId === environment.id) { setSelectedEnvironmentId(baseEnvironment?.id ?? null); } }, [baseEnvironment?.id, selectedEnvironmentId], ); if (baseEnvironment == null) { return null; } return ( ( )} secondSlot={() => selectedEnvironment == null ? (
Failed to find selected environment {selectedEnvironmentId}
) : ( ) } /> ); }; function EnvironmentDialogSidebarButton({ children, className, active, onClick, deleteEnvironment, rightSlot, outerRightSlot, duplicateEnvironment, environment, }: { className?: string; children: ReactNode; active: boolean; onClick: () => void; rightSlot?: ReactNode; outerRightSlot?: ReactNode; environment: Environment; deleteEnvironment: ((environment: Environment) => void) | null; duplicateEnvironment: ((environment: Environment) => void) | null; }) { const [showContextMenu, setShowContextMenu] = useState<{ x: number; y: number; } | null>(null); const handleContextMenu = useCallback((e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); setShowContextMenu({ x: e.clientX, y: e.clientY }); }, []); return ( <>
{outerRightSlot}
setShowContextMenu(null)} items={[ { label: 'Rename', leftSlot: , hidden: isBaseEnvironment(environment), onSelect: async () => { const name = await showPrompt({ id: 'rename-environment', title: 'Rename Environment', description: ( <> Enter a new name for {environment.name} ), label: 'Name', confirmText: 'Save', placeholder: 'New Name', defaultValue: environment.name, }); if (name == null) return; await patchModel(environment, { name }); }, }, ...((duplicateEnvironment ? [ { label: 'Duplicate', leftSlot: , onSelect: () => { duplicateEnvironment?.(environment); }, }, ] : []) as DropdownItem[]), { label: environment.color ? 'Change Color' : 'Assign Color', leftSlot: , hidden: isBaseEnvironment(environment), onSelect: async () => showColorPicker(environment), }, { label: `Make ${environment.public ? 'Private' : 'Sharable'}`, leftSlot: , rightSlot: , onSelect: async () => { await patchModel(environment, { public: !environment.public }); }, }, ...((deleteEnvironment ? [ { color: 'danger', label: 'Delete', leftSlot: , onSelect: () => { deleteEnvironment(environment); }, }, ] : []) as DropdownItem[]), ]} /> ); } const sharableTooltip = ( );