mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-23 05:47:59 -05:00
improvement(ui): fixed some styling for credential selector
This commit is contained in:
@@ -21,6 +21,7 @@ import {
|
||||
getProviderIdFromServiceId,
|
||||
getServiceByProviderAndId,
|
||||
getServiceIdFromScopes,
|
||||
parseProvider,
|
||||
} from '@/lib/oauth'
|
||||
import { saveToStorage } from '@/stores/workflows/persistence'
|
||||
|
||||
@@ -168,26 +169,62 @@ export function CredentialSelector({
|
||||
|
||||
// Get provider icon
|
||||
const getProviderIcon = (providerName: OAuthProvider) => {
|
||||
const providerConfig = OAUTH_PROVIDERS[providerName]
|
||||
if (providerConfig) {
|
||||
return providerConfig.icon({ className: 'h-4 w-4' })
|
||||
const { baseProvider } = parseProvider(providerName)
|
||||
const baseProviderConfig = OAUTH_PROVIDERS[baseProvider]
|
||||
|
||||
if (!baseProviderConfig) {
|
||||
return <ExternalLink className="h-4 w-4" />
|
||||
}
|
||||
return <ExternalLink className="h-4 w-4" />
|
||||
|
||||
// For compound providers, find the specific service
|
||||
if (providerName.includes('-')) {
|
||||
for (const service of Object.values(baseProviderConfig.services)) {
|
||||
if (service.providerId === providerName) {
|
||||
return service.icon({ className: 'h-4 w-4' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to base provider icon
|
||||
return baseProviderConfig.icon({ className: 'h-4 w-4' })
|
||||
}
|
||||
|
||||
// Get provider name
|
||||
const getProviderName = (providerName: OAuthProvider) => {
|
||||
const effectiveServiceId = getServiceId()
|
||||
try {
|
||||
// First try to get the service by provider and service ID
|
||||
const service = getServiceByProviderAndId(providerName, effectiveServiceId)
|
||||
return service.name
|
||||
} catch (error) {
|
||||
// Fallback to provider name if service not found
|
||||
const providerConfig = OAUTH_PROVIDERS[providerName]
|
||||
if (providerConfig) {
|
||||
return providerConfig.name
|
||||
// If that fails, try to get the service by parsing the provider
|
||||
try {
|
||||
const { baseProvider } = parseProvider(providerName)
|
||||
const baseProviderConfig = OAUTH_PROVIDERS[baseProvider]
|
||||
|
||||
// For compound providers like 'google-sheets', try to find the specific service
|
||||
if (providerName.includes('-')) {
|
||||
const serviceKey = providerName.split('-')[1] || ''
|
||||
for (const [key, service] of Object.entries(baseProviderConfig?.services || {})) {
|
||||
if (key === serviceKey || key === providerName || service.providerId === providerName) {
|
||||
return service.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to provider name if service not found
|
||||
if (baseProviderConfig) {
|
||||
return baseProviderConfig.name
|
||||
}
|
||||
} catch (parseError) {
|
||||
// Ignore parse error and continue to final fallback
|
||||
}
|
||||
|
||||
// Final fallback: capitalize the provider name
|
||||
return providerName
|
||||
.split('-')
|
||||
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
||||
.join(' ')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,8 +246,8 @@ export function CredentialSelector({
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center gap-2">
|
||||
<Key className="h-4 w-4" />
|
||||
<span>{label}</span>
|
||||
{getProviderIcon(provider)}
|
||||
<span className="text-muted-foreground">{label}</span>
|
||||
</div>
|
||||
)}
|
||||
<ChevronDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
@@ -228,7 +265,7 @@ export function CredentialSelector({
|
||||
</div>
|
||||
) : (
|
||||
<div className="p-4 text-center">
|
||||
<p className="text-sm">No credentials found.</p>
|
||||
<p className="text-sm font-medium">No credentials found.</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Connect a new account to continue.
|
||||
</p>
|
||||
@@ -255,7 +292,7 @@ export function CredentialSelector({
|
||||
<CommandGroup>
|
||||
<CommandItem onSelect={handleAddCredential}>
|
||||
<div className="flex items-center gap-2 text-primary">
|
||||
<ExternalLink className="h-4 w-4" />
|
||||
{getProviderIcon(provider)}
|
||||
<span>Connect {getProviderName(provider)} account</span>
|
||||
</div>
|
||||
</CommandItem>
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
OAuthProvider,
|
||||
getProviderIdFromServiceId,
|
||||
getServiceIdFromScopes,
|
||||
parseProvider,
|
||||
} from '@/lib/oauth'
|
||||
import { saveToStorage } from '@/stores/workflows/persistence'
|
||||
|
||||
@@ -60,10 +61,25 @@ export function OAuthRequiredModal({
|
||||
requiredScopes = [],
|
||||
serviceId,
|
||||
}: OAuthRequiredModalProps) {
|
||||
// Get provider configuration
|
||||
const providerConfig = OAUTH_PROVIDERS[provider]
|
||||
const providerName = providerConfig?.name || provider
|
||||
const ProviderIcon = providerConfig?.icon || (() => null)
|
||||
// Get provider configuration and service
|
||||
const effectiveServiceId = serviceId || getServiceIdFromScopes(provider, requiredScopes)
|
||||
const { baseProvider } = parseProvider(provider)
|
||||
const baseProviderConfig = OAUTH_PROVIDERS[baseProvider]
|
||||
|
||||
// Default to base provider name and icon
|
||||
let providerName = baseProviderConfig?.name || provider
|
||||
let ProviderIcon = baseProviderConfig?.icon || (() => null)
|
||||
|
||||
// Try to find the specific service
|
||||
if (baseProviderConfig) {
|
||||
for (const service of Object.values(baseProviderConfig.services)) {
|
||||
if (service.id === effectiveServiceId || service.providerId === provider) {
|
||||
providerName = service.name
|
||||
ProviderIcon = service.icon
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Filter out userinfo scopes as they're not relevant to show to users
|
||||
const displayScopes = requiredScopes.filter(
|
||||
@@ -73,7 +89,6 @@ export function OAuthRequiredModal({
|
||||
const handleRedirectToSettings = () => {
|
||||
try {
|
||||
// Determine the appropriate serviceId and providerId
|
||||
const effectiveServiceId = serviceId || getServiceIdFromScopes(provider, requiredScopes)
|
||||
const providerId = getProviderIdFromServiceId(effectiveServiceId)
|
||||
|
||||
// Store information about the required connection
|
||||
@@ -98,7 +113,6 @@ export function OAuthRequiredModal({
|
||||
const handleConnectDirectly = async () => {
|
||||
try {
|
||||
// Determine the appropriate serviceId and providerId
|
||||
const effectiveServiceId = serviceId || getServiceIdFromScopes(provider, requiredScopes)
|
||||
const providerId = getProviderIdFromServiceId(effectiveServiceId)
|
||||
|
||||
// Store information about the required connection
|
||||
|
||||
10
lib/oauth.ts
10
lib/oauth.ts
@@ -39,6 +39,7 @@ export interface OAuthServiceConfig {
|
||||
description: string
|
||||
providerId: string
|
||||
icon: (props: { className?: string }) => ReactNode
|
||||
baseProviderIcon: (props: { className?: string }) => ReactNode
|
||||
scopes: string[]
|
||||
}
|
||||
|
||||
@@ -55,6 +56,7 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
|
||||
description: 'Automate email workflows and enhance communication efficiency.',
|
||||
providerId: 'google-email',
|
||||
icon: (props) => GmailIcon(props),
|
||||
baseProviderIcon: (props) => GoogleIcon(props),
|
||||
scopes: [
|
||||
'https://www.googleapis.com/auth/gmail.send',
|
||||
'https://www.googleapis.com/auth/gmail.readonly',
|
||||
@@ -66,6 +68,7 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
|
||||
description: 'Streamline file organization and document workflows.',
|
||||
providerId: 'google-drive',
|
||||
icon: (props) => GoogleDriveIcon(props),
|
||||
baseProviderIcon: (props) => GoogleIcon(props),
|
||||
scopes: ['https://www.googleapis.com/auth/drive'],
|
||||
},
|
||||
'google-docs': {
|
||||
@@ -74,6 +77,7 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
|
||||
description: 'Create, read, and edit Google Documents programmatically.',
|
||||
providerId: 'google-docs',
|
||||
icon: (props) => GoogleDocsIcon(props),
|
||||
baseProviderIcon: (props) => GoogleIcon(props),
|
||||
scopes: ['https://www.googleapis.com/auth/documents'],
|
||||
},
|
||||
'google-sheets': {
|
||||
@@ -82,6 +86,7 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
|
||||
description: 'Manage and analyze data with Google Sheets integration.',
|
||||
providerId: 'google-sheets',
|
||||
icon: (props) => GoogleSheetsIcon(props),
|
||||
baseProviderIcon: (props) => GoogleIcon(props),
|
||||
scopes: ['https://www.googleapis.com/auth/spreadsheets'],
|
||||
},
|
||||
'google-calendar': {
|
||||
@@ -90,6 +95,7 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
|
||||
description: 'Schedule and manage events with Google Calendar.',
|
||||
providerId: 'google-calendar',
|
||||
icon: (props) => GoogleCalendarIcon(props),
|
||||
baseProviderIcon: (props) => GoogleIcon(props),
|
||||
scopes: ['https://www.googleapis.com/auth/calendar'],
|
||||
},
|
||||
},
|
||||
@@ -106,6 +112,7 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
|
||||
description: 'Manage repositories, issues, and pull requests.',
|
||||
providerId: 'github-repo',
|
||||
icon: (props) => GithubIcon(props),
|
||||
baseProviderIcon: (props) => GithubIcon(props),
|
||||
scopes: ['repo', 'user'],
|
||||
},
|
||||
'github-workflow': {
|
||||
@@ -114,6 +121,7 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
|
||||
description: 'Trigger and manage GitHub Actions workflows.',
|
||||
providerId: 'github-workflow',
|
||||
icon: (props) => GithubIcon(props),
|
||||
baseProviderIcon: (props) => GithubIcon(props),
|
||||
scopes: ['repo', 'workflow'],
|
||||
},
|
||||
},
|
||||
@@ -130,6 +138,7 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
|
||||
description: 'Post tweets and interact with the X API.',
|
||||
providerId: 'x',
|
||||
icon: (props) => xIcon(props),
|
||||
baseProviderIcon: (props) => xIcon(props),
|
||||
scopes: [],
|
||||
},
|
||||
},
|
||||
@@ -146,6 +155,7 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
|
||||
description: 'Connect to your Supabase projects and manage data.',
|
||||
providerId: 'supabase',
|
||||
icon: (props) => SupabaseIcon(props),
|
||||
baseProviderIcon: (props) => SupabaseIcon(props),
|
||||
scopes: ['database.read', 'database.write', 'projects.read'],
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user