mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
improvement(credentials): ui (#3322)
* improvement(credentials): ui * fix: credentials logic * improvement(credentials): ui * improvement(credentials): members UI * improvement(secrets): ui * fix(credentials): show error when OAuth deletion fails due to missing fields - Add deleteError state to track and display deletion errors - Keep confirmation dialog open when deletion fails - Show user-friendly error message when accountId or providerId is missing - Add loading state to delete button during deletion - Display error message in confirmation dialog with proper styling Co-authored-by: Emir Karabeg <emir-karabeg@users.noreply.github.com> * ran lint * removed worktree file --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Emir Karabeg <emir-karabeg@users.noreply.github.com> Co-authored-by: Waleed Latif <walif6@gmail.com>
This commit is contained in:
co-authored by
Emir Karabeg
Cursor Agent
Waleed Latif
parent
60f9eb21bf
commit
8f9b859a53
+6
-6
@@ -142,7 +142,7 @@ export function ApiKeys({ onOpenChange }: ApiKeysProps) {
|
||||
strokeWidth={2}
|
||||
/>
|
||||
<Input
|
||||
placeholder='Search API keys...'
|
||||
placeholder='Search Sim keys...'
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
className='h-auto flex-1 border-0 bg-transparent p-0 font-base leading-none placeholder:text-[var(--text-tertiary)] focus-visible:ring-0 focus-visible:ring-offset-0'
|
||||
@@ -195,7 +195,7 @@ export function ApiKeys({ onOpenChange }: ApiKeysProps) {
|
||||
</div>
|
||||
{workspaceKeys.length === 0 ? (
|
||||
<div className='text-[13px] text-[var(--text-muted)]'>
|
||||
No workspace API keys yet
|
||||
No workspace Sim keys yet
|
||||
</div>
|
||||
) : (
|
||||
workspaceKeys.map((key) => (
|
||||
@@ -301,7 +301,7 @@ export function ApiKeys({ onOpenChange }: ApiKeysProps) {
|
||||
</div>
|
||||
{isConflict && (
|
||||
<div className='text-[12px] text-[var(--text-error)] leading-tight'>
|
||||
Workspace API key with the same name overrides this. Rename your
|
||||
Workspace Sim key with the same name overrides this. Rename your
|
||||
personal key to use it.
|
||||
</div>
|
||||
)}
|
||||
@@ -317,7 +317,7 @@ export function ApiKeys({ onOpenChange }: ApiKeysProps) {
|
||||
filteredWorkspaceKeys.length === 0 &&
|
||||
(personalKeys.length > 0 || workspaceKeys.length > 0) && (
|
||||
<div className='py-[16px] text-center text-[13px] text-[var(--text-muted)]'>
|
||||
No API keys found matching "{searchTerm}"
|
||||
No Sim keys found matching "{searchTerm}"
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
@@ -331,7 +331,7 @@ export function ApiKeys({ onOpenChange }: ApiKeysProps) {
|
||||
<div className='mt-auto flex items-center justify-between'>
|
||||
<div className='flex items-center gap-[8px]'>
|
||||
<span className='font-medium text-[13px] text-[var(--text-secondary)]'>
|
||||
Allow personal API keys
|
||||
Allow personal Sim keys
|
||||
</span>
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger asChild>
|
||||
@@ -383,7 +383,7 @@ export function ApiKeys({ onOpenChange }: ApiKeysProps) {
|
||||
{/* Delete Confirmation Dialog */}
|
||||
<Modal open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
|
||||
<ModalContent size='sm'>
|
||||
<ModalHeader>Delete API key</ModalHeader>
|
||||
<ModalHeader>Delete Sim key</ModalHeader>
|
||||
<ModalBody>
|
||||
<p className='text-[12px] text-[var(--text-secondary)]'>
|
||||
Deleting{' '}
|
||||
|
||||
+9
-9
@@ -62,8 +62,8 @@ export function CreateApiKeyModal({
|
||||
if (isDuplicate) {
|
||||
setCreateError(
|
||||
keyType === 'workspace'
|
||||
? `A workspace API key named "${trimmedName}" already exists. Please choose a different name.`
|
||||
: `A personal API key named "${trimmedName}" already exists. Please choose a different name.`
|
||||
? `A workspace Sim key named "${trimmedName}" already exists. Please choose a different name.`
|
||||
: `A personal Sim key named "${trimmedName}" already exists. Please choose a different name.`
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -86,11 +86,11 @@ export function CreateApiKeyModal({
|
||||
} catch (error: unknown) {
|
||||
logger.error('API key creation failed:', { error })
|
||||
const errorMessage =
|
||||
error instanceof Error ? error.message : 'Failed to create API key. Please try again.'
|
||||
error instanceof Error ? error.message : 'Failed to create Sim key. Please try again.'
|
||||
if (errorMessage.toLowerCase().includes('already exists')) {
|
||||
setCreateError(errorMessage)
|
||||
} else {
|
||||
setCreateError('Failed to create API key. Please check your connection and try again.')
|
||||
setCreateError('Failed to create Sim key. Please check your connection and try again.')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,7 +113,7 @@ export function CreateApiKeyModal({
|
||||
{/* Create API Key Dialog */}
|
||||
<Modal open={open} onOpenChange={onOpenChange}>
|
||||
<ModalContent size='sm'>
|
||||
<ModalHeader>Create new API key</ModalHeader>
|
||||
<ModalHeader>Create new Sim key</ModalHeader>
|
||||
<ModalBody>
|
||||
<p className='text-[12px] text-[var(--text-secondary)]'>
|
||||
{keyType === 'workspace'
|
||||
@@ -125,7 +125,7 @@ export function CreateApiKeyModal({
|
||||
{canManageWorkspaceKeys && (
|
||||
<div className='flex flex-col gap-[8px]'>
|
||||
<p className='font-medium text-[13px] text-[var(--text-secondary)]'>
|
||||
API Key Type
|
||||
Sim Key Type
|
||||
</p>
|
||||
<ButtonGroup
|
||||
value={keyType}
|
||||
@@ -143,7 +143,7 @@ export function CreateApiKeyModal({
|
||||
)}
|
||||
<div className='flex flex-col gap-[8px]'>
|
||||
<p className='font-medium text-[13px] text-[var(--text-secondary)]'>
|
||||
Enter a name for your API key to help you identify it later.
|
||||
Enter a name for your Sim key to help you identify it later.
|
||||
</p>
|
||||
{/* Hidden decoy fields to prevent browser autofill */}
|
||||
<input
|
||||
@@ -216,10 +216,10 @@ export function CreateApiKeyModal({
|
||||
}}
|
||||
>
|
||||
<ModalContent size='sm'>
|
||||
<ModalHeader>Your API key has been created</ModalHeader>
|
||||
<ModalHeader>Your Sim key has been created</ModalHeader>
|
||||
<ModalBody>
|
||||
<p className='text-[12px] text-[var(--text-secondary)]'>
|
||||
This is the only time you will see your API key.{' '}
|
||||
This is the only time you will see your Sim key.{' '}
|
||||
<span className='font-semibold text-[var(--text-primary)]'>
|
||||
Copy it now and store it securely.
|
||||
</span>
|
||||
|
||||
+828
-640
File diff suppressed because it is too large
Load Diff
+4
-4
@@ -19,7 +19,6 @@ import {
|
||||
} from 'lucide-react'
|
||||
import {
|
||||
Card,
|
||||
Connections,
|
||||
HexSimple,
|
||||
Key,
|
||||
SModal,
|
||||
@@ -32,6 +31,7 @@ import {
|
||||
SModalSidebarItem,
|
||||
SModalSidebarSection,
|
||||
SModalSidebarSectionTitle,
|
||||
TerminalWindow,
|
||||
} from '@/components/emcn'
|
||||
import { AgentSkillsIcon, McpIcon } from '@/components/icons'
|
||||
import { useSession } from '@/lib/auth/auth-client'
|
||||
@@ -153,11 +153,11 @@ const allNavigationItems: NavigationItem[] = [
|
||||
requiresHosted: true,
|
||||
requiresTeam: true,
|
||||
},
|
||||
{ id: 'credentials', label: 'Credentials', icon: Connections, section: 'account' },
|
||||
{ id: 'credentials', label: 'Secrets', icon: Key, section: 'account' },
|
||||
{ id: 'custom-tools', label: 'Custom Tools', icon: Wrench, section: 'tools' },
|
||||
{ id: 'skills', label: 'Skills', icon: AgentSkillsIcon, section: 'tools' },
|
||||
{ id: 'mcp', label: 'MCP Tools', icon: McpIcon, section: 'tools' },
|
||||
{ id: 'apikeys', label: 'API Keys', icon: Key, section: 'system' },
|
||||
{ id: 'apikeys', label: 'Sim Keys', icon: TerminalWindow, section: 'system' },
|
||||
{ id: 'workflow-mcp-servers', label: 'MCP Servers', icon: Server, section: 'system' },
|
||||
{
|
||||
id: 'byok',
|
||||
@@ -461,7 +461,7 @@ export function SettingsModal({ open, onOpenChange }: SettingsModalProps) {
|
||||
</VisuallyHidden.Root>
|
||||
<VisuallyHidden.Root>
|
||||
<DialogPrimitive.Description>
|
||||
Configure your workspace settings, credentials, and preferences
|
||||
Configure your workspace settings, secrets, and preferences
|
||||
</DialogPrimitive.Description>
|
||||
</VisuallyHidden.Root>
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ export { PanelLeft } from './panel-left'
|
||||
export { Play, PlayOutline } from './play'
|
||||
export { Redo } from './redo'
|
||||
export { Rocket } from './rocket'
|
||||
export { TerminalWindow } from './terminal-window'
|
||||
export { Trash } from './trash'
|
||||
export { Trash2 } from './trash2'
|
||||
export { Undo } from './undo'
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import type { SVGProps } from 'react'
|
||||
|
||||
/**
|
||||
* Terminal window icon component
|
||||
* @param props - SVG properties including className, fill, etc.
|
||||
*/
|
||||
export function TerminalWindow(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width='16'
|
||||
height='14'
|
||||
viewBox='0 0 16 14'
|
||||
fill='none'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d='M3 0C1.34315 0 0 1.34315 0 3V11C0 12.6569 1.34315 14 3 14H13C14.6569 14 16 12.6569 16 11V3C16 1.34315 14.6569 0 13 0H3ZM1 3C1 1.89543 1.89543 1 3 1H13C14.1046 1 15 1.89543 15 3V4H1V3ZM1 5H15V11C15 12.1046 14.1046 13 13 13H3C1.89543 13 1 12.1046 1 11V5Z'
|
||||
fill='currentColor'
|
||||
/>
|
||||
<circle cx='3.5' cy='2.5' r='0.75' fill='currentColor' />
|
||||
<circle cx='5.75' cy='2.5' r='0.75' fill='currentColor' />
|
||||
<circle cx='8' cy='2.5' r='0.75' fill='currentColor' />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user