polish changes

This commit is contained in:
Ryan Crabbe
2026-03-07 08:58:28 -08:00
parent 8388e77b59
commit 37de206c5b
6 changed files with 83 additions and 99 deletions
@@ -1,8 +1,6 @@
import { deleteHashicorpVaultConfig } from "@/components/networking";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { createQueryKeys } from "../common/queryKeysFactory";
const hashicorpVaultKeys = createQueryKeys("hashicorpVaultConfig");
import { hashicorpVaultKeys } from "./useHashicorpVaultConfig";
export const useDeleteHashicorpVaultConfig = (accessToken: string | null) => {
const queryClient = useQueryClient();
@@ -3,7 +3,7 @@ import { useQuery } from "@tanstack/react-query";
import useAuthorized from "../useAuthorized";
import { createQueryKeys } from "../common/queryKeysFactory";
const hashicorpVaultKeys = createQueryKeys("hashicorpVaultConfig");
export const hashicorpVaultKeys = createQueryKeys("hashicorpVaultConfig");
export const useHashicorpVaultConfig = () => {
const { accessToken } = useAuthorized();
@@ -1,8 +1,6 @@
import { updateHashicorpVaultConfig } from "@/components/networking";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { createQueryKeys } from "../common/queryKeysFactory";
const hashicorpVaultKeys = createQueryKeys("hashicorpVaultConfig");
import { hashicorpVaultKeys } from "./useHashicorpVaultConfig";
export const useUpdateHashicorpVaultConfig = (accessToken: string | null) => {
const queryClient = useQueryClient();
@@ -50,7 +50,7 @@ const EditHashicorpVaultModal: React.FC<EditHashicorpVaultModalProps> = ({
const [form] = Form.useForm();
const { accessToken } = useAuthorized();
const { data } = useHashicorpVaultConfig();
const { mutateAsync, isPending } = useUpdateHashicorpVaultConfig(accessToken);
const { mutate, isPending } = useUpdateHashicorpVaultConfig(accessToken);
const schema = data?.field_schema;
const properties = schema?.properties ?? {};
@@ -70,7 +70,7 @@ const EditHashicorpVaultModal: React.FC<EditHashicorpVaultModalProps> = ({
}
}, [isVisible, data, form]);
const handleSubmit = async (formValues: Record<string, any>) => {
const handleSubmit = (formValues: Record<string, any>) => {
const config: Record<string, any> = {};
for (const [key, value] of Object.entries(formValues)) {
if (value !== undefined && value !== null && value !== "") {
@@ -83,7 +83,7 @@ const EditHashicorpVaultModal: React.FC<EditHashicorpVaultModalProps> = ({
// Sensitive field left blank → omit from payload (keep existing)
}
await mutateAsync(config, {
mutate(config, {
onSuccess: () => {
NotificationManager.success("Hashicorp Vault configuration updated successfully");
onSuccess();
@@ -28,14 +28,13 @@ const descriptionsConfig = {
export default function HashicorpVault() {
const { accessToken } = useAuthorized();
const { data, isLoading, isError, error, refetch } = useHashicorpVaultConfig();
const { data, isLoading, isError, error } = useHashicorpVaultConfig();
const { mutate: deleteConfig, isPending: isDeleting } = useDeleteHashicorpVaultConfig(accessToken);
const { mutateAsync: updateConfig } = useUpdateHashicorpVaultConfig(accessToken);
const { mutate: updateConfig, isPending: isClearingField } = useUpdateHashicorpVaultConfig(accessToken);
const [isEditModalVisible, setIsEditModalVisible] = useState(false);
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const [clearingField, setClearingField] = useState<string | null>(null);
const [isClearingField, setIsClearingField] = useState(false);
const [isTesting, setIsTesting] = useState(false);
const rawValues = data?.values ?? {};
@@ -66,19 +65,17 @@ export default function HashicorpVault() {
});
};
const handleClearField = async () => {
const handleClearField = () => {
if (!clearingField) return;
setIsClearingField(true);
try {
await updateConfig({ [clearingField]: "" });
NotificationManager.success(`${FIELD_LABELS[clearingField] ?? clearingField} cleared`);
setClearingField(null);
refetch();
} catch (err) {
NotificationManager.fromBackend(err);
} finally {
setIsClearingField(false);
}
updateConfig({ [clearingField]: "" }, {
onSuccess: () => {
NotificationManager.success(`${FIELD_LABELS[clearingField] ?? clearingField} cleared`);
setClearingField(null);
},
onError: (err) => {
NotificationManager.fromBackend(err);
},
});
};
const renderValue = (key: string) => {
@@ -140,84 +137,79 @@ export default function HashicorpVault() {
/>
</Card>
) : (
<Space direction="vertical" size="large" className="w-full">
<Card>
<Space direction="vertical" size="large" className="w-full">
{/* Header */}
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<KeyRound className="w-6 h-6 text-gray-400" />
<div>
<Title level={3} style={{ marginBottom: 0 }}>Hashicorp Vault</Title>
<Text type="secondary">Manage secret manager configuration</Text>
</div>
</div>
<div className="flex items-center gap-3">
{isConfigured && (
<>
<Button
icon={<PlugZap className="w-4 h-4" />}
loading={isTesting}
onClick={handleTestConnection}
>
Test Connection
</Button>
<Button
icon={<Edit className="w-4 h-4" />}
onClick={() => setIsEditModalVisible(true)}
>
Edit Configuration
</Button>
<Button
danger
icon={<Trash2 className="w-4 h-4" />}
onClick={() => setIsDeleteModalOpen(true)}
>
Delete Configuration
</Button>
</>
)}
<Card>
<Space direction="vertical" size="large" className="w-full">
{/* Header */}
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<KeyRound className="w-6 h-6 text-gray-400" />
<div>
<Title level={3} style={{ marginBottom: 0 }}>Hashicorp Vault</Title>
<Text type="secondary">Manage secret manager configuration</Text>
</div>
</div>
{isConfigured && (
<Alert
type="info"
showIcon
message="Secrets must be stored with the field name &quot;key&quot;"
description={
<>
<Text code>vault kv put secret/SECRET_NAME key=secret_value</Text>
<br />
<Typography.Link
href="https://docs.litellm.ai/docs/secret_managers/hashicorp_vault"
target="_blank"
>
View documentation
</Typography.Link>
</>
}
/>
)}
<div className="flex items-center gap-3">
{isConfigured && (
<>
<Button
icon={<PlugZap className="w-4 h-4" />}
loading={isTesting}
onClick={handleTestConnection}
>
Test Connection
</Button>
<Button
icon={<Edit className="w-4 h-4" />}
onClick={() => setIsEditModalVisible(true)}
>
Edit Configuration
</Button>
<Button
danger
icon={<Trash2 className="w-4 h-4" />}
onClick={() => setIsDeleteModalOpen(true)}
>
Delete Configuration
</Button>
</>
)}
</div>
</div>
{isConfigured ? (
renderSettings()
) : (
<HashicorpVaultEmptyPlaceholder onAdd={() => setIsEditModalVisible(true)} />
)}
</Space>
</Card>
</Space>
{isConfigured && (
<Alert
type="info"
showIcon
message={'Secrets must be stored with the field name "key"'}
description={
<>
<Text code>vault kv put secret/SECRET_NAME key=secret_value</Text>
<br />
<Typography.Link
href="https://docs.litellm.ai/docs/secret_managers/hashicorp_vault"
target="_blank"
>
View documentation
</Typography.Link>
</>
}
/>
)}
{isConfigured ? (
renderSettings()
) : (
<HashicorpVaultEmptyPlaceholder onAdd={() => setIsEditModalVisible(true)} />
)}
</Space>
</Card>
)}
<EditHashicorpVaultModal
isVisible={isEditModalVisible}
onCancel={() => setIsEditModalVisible(false)}
onSuccess={() => {
setIsEditModalVisible(false);
refetch();
}}
onSuccess={() => setIsEditModalVisible(false)}
/>
<DeleteResourceModal
@@ -8893,11 +8893,7 @@ export const getHashicorpVaultConfig = async (accessToken: string) => {
});
if (!response.ok) {
const errorData = await response.json();
const detail = errorData?.detail;
const errorMessage =
(typeof detail === "object" && detail?.error) ||
(typeof detail === "string" && detail) ||
deriveErrorMessage(errorData);
const errorMessage = deriveErrorMessage(errorData);
throw new Error(errorMessage);
}
const data = await response.json();