From fc9b9165b0c889a3e0984b27b455aee64de94c42 Mon Sep 17 00:00:00 2001 From: Abhimanyu Yadav <122007096+Abhi1992002@users.noreply.github.com> Date: Thu, 12 Feb 2026 18:27:06 +0530 Subject: [PATCH] refactor(frontend): remove default expiration date from API key credentials form (#12092) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Changes 🏗️ Removed the default expiration date for API keys in the credentials modal. Previously, API keys were set to expire the next day by default, but now the expiration date field starts empty, allowing users to explicitly choose whether they want to set an expiration date. ### Checklist 📋 #### For code changes: - [x] I have clearly listed my changes in the PR description - [x] I have made a test plan - [x] I have tested my changes according to the test plan: - [x] Open the API key credentials modal and verify the expiration date field is empty by default - [x] Test creating an API key with and without an expiration date - [x] Verify both scenarios work correctly

Greptile Overview

Greptile Summary

Removed the default expiration date for API key credentials in the credentials modal. Previously, API keys were automatically set to expire the next day at midnight. Now the expiration date field starts empty, allowing users to explicitly choose whether to set an expiration. - Removed `getDefaultExpirationDate()` helper function that calculated tomorrow's date - Changed default `expiresAt` value from calculated date to empty string - Backend already supports optional expiration (`expires_at?: number`), so no backend changes needed - Form submission correctly handles empty expiration by passing `undefined` to the API

Confidence Score: 5/5

- This PR is safe to merge with minimal risk - The changes are straightforward and well-contained. The refactor removes a helper function and changes a default value. The backend API already supports optional expiration dates, and the form submission logic correctly handles empty values by passing undefined. The change improves UX by not forcing a default expiration date on users. - No files require special attention
--- .../APIKeyCredentialsModal.tsx | 8 ++- .../useAPIKeyCredentialsModal.ts | 51 +++++++++---------- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/autogpt_platform/frontend/src/components/contextual/CredentialsInput/components/APIKeyCredentialsModal/APIKeyCredentialsModal.tsx b/autogpt_platform/frontend/src/components/contextual/CredentialsInput/components/APIKeyCredentialsModal/APIKeyCredentialsModal.tsx index 90f6c0ff70..1c455863dd 100644 --- a/autogpt_platform/frontend/src/components/contextual/CredentialsInput/components/APIKeyCredentialsModal/APIKeyCredentialsModal.tsx +++ b/autogpt_platform/frontend/src/components/contextual/CredentialsInput/components/APIKeyCredentialsModal/APIKeyCredentialsModal.tsx @@ -30,6 +30,7 @@ export function APIKeyCredentialsModal({ const { form, isLoading, + isSubmitting, supportsApiKey, providerName, schemaDescription, @@ -138,7 +139,12 @@ export function APIKeyCredentialsModal({ /> )} /> - diff --git a/autogpt_platform/frontend/src/components/contextual/CredentialsInput/components/APIKeyCredentialsModal/useAPIKeyCredentialsModal.ts b/autogpt_platform/frontend/src/components/contextual/CredentialsInput/components/APIKeyCredentialsModal/useAPIKeyCredentialsModal.ts index 72599a2e79..1f3d4c9085 100644 --- a/autogpt_platform/frontend/src/components/contextual/CredentialsInput/components/APIKeyCredentialsModal/useAPIKeyCredentialsModal.ts +++ b/autogpt_platform/frontend/src/components/contextual/CredentialsInput/components/APIKeyCredentialsModal/useAPIKeyCredentialsModal.ts @@ -4,6 +4,7 @@ import { CredentialsMetaInput, } from "@/lib/autogpt-server-api/types"; import { zodResolver } from "@hookform/resolvers/zod"; +import { useState } from "react"; import { useForm, type UseFormReturn } from "react-hook-form"; import { z } from "zod"; @@ -26,6 +27,7 @@ export function useAPIKeyCredentialsModal({ }: Args): { form: UseFormReturn; isLoading: boolean; + isSubmitting: boolean; supportsApiKey: boolean; provider?: string; providerName?: string; @@ -33,6 +35,7 @@ export function useAPIKeyCredentialsModal({ onSubmit: (values: APIKeyFormValues) => Promise; } { const credentials = useCredentials(schema, siblingInputs); + const [isSubmitting, setIsSubmitting] = useState(false); const formSchema = z.object({ apiKey: z.string().min(1, "API Key is required"), @@ -40,48 +43,42 @@ export function useAPIKeyCredentialsModal({ expiresAt: z.string().optional(), }); - function getDefaultExpirationDate(): string { - const tomorrow = new Date(); - tomorrow.setDate(tomorrow.getDate() + 1); - tomorrow.setHours(0, 0, 0, 0); - const year = tomorrow.getFullYear(); - const month = String(tomorrow.getMonth() + 1).padStart(2, "0"); - const day = String(tomorrow.getDate()).padStart(2, "0"); - const hours = String(tomorrow.getHours()).padStart(2, "0"); - const minutes = String(tomorrow.getMinutes()).padStart(2, "0"); - return `${year}-${month}-${day}T${hours}:${minutes}`; - } - const form = useForm({ resolver: zodResolver(formSchema), defaultValues: { apiKey: "", title: "", - expiresAt: getDefaultExpirationDate(), + expiresAt: "", }, }); async function onSubmit(values: APIKeyFormValues) { if (!credentials || credentials.isLoading) return; - const expiresAt = values.expiresAt - ? new Date(values.expiresAt).getTime() / 1000 - : undefined; - const newCredentials = await credentials.createAPIKeyCredentials({ - api_key: values.apiKey, - title: values.title, - expires_at: expiresAt, - }); - onCredentialsCreate({ - provider: credentials.provider, - id: newCredentials.id, - type: "api_key", - title: newCredentials.title, - }); + setIsSubmitting(true); + try { + const expiresAt = values.expiresAt + ? new Date(values.expiresAt).getTime() / 1000 + : undefined; + const newCredentials = await credentials.createAPIKeyCredentials({ + api_key: values.apiKey, + title: values.title, + expires_at: expiresAt, + }); + onCredentialsCreate({ + provider: credentials.provider, + id: newCredentials.id, + type: "api_key", + title: newCredentials.title, + }); + } finally { + setIsSubmitting(false); + } } return { form, isLoading: !credentials || credentials.isLoading, + isSubmitting, supportsApiKey: !!credentials?.supportsApiKey, provider: credentials?.provider, providerName: