mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-10 15:38:00 -05:00
fix(slack): set depends on for slack channel channel subblock (#1177)
* fix(slack): set depends on for slack channel * use foreign credential check * fix * fix clearing of block
This commit is contained in:
committed by
GitHub
parent
cadfcdbfbd
commit
ebb8cf8bf9
@@ -1,12 +1,14 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useParams } from 'next/navigation'
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
||||
import {
|
||||
type SlackChannelInfo,
|
||||
SlackChannelSelector,
|
||||
} from '@/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/channel-selector/components/slack-channel-selector'
|
||||
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/hooks/use-depends-on-gate'
|
||||
import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/hooks/use-foreign-credential'
|
||||
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/hooks/use-sub-block-value'
|
||||
import type { SubBlockConfig } from '@/blocks/types'
|
||||
|
||||
@@ -15,7 +17,6 @@ interface ChannelSelectorInputProps {
|
||||
subBlock: SubBlockConfig
|
||||
disabled?: boolean
|
||||
onChannelSelect?: (channelId: string) => void
|
||||
credential?: string
|
||||
isPreview?: boolean
|
||||
previewValue?: any | null
|
||||
}
|
||||
@@ -25,10 +26,11 @@ export function ChannelSelectorInput({
|
||||
subBlock,
|
||||
disabled = false,
|
||||
onChannelSelect,
|
||||
credential: providedCredential,
|
||||
isPreview = false,
|
||||
previewValue,
|
||||
}: ChannelSelectorInputProps) {
|
||||
const params = useParams()
|
||||
const workflowIdFromUrl = (params?.workflowId as string) || ''
|
||||
// Use the proper hook to get the current value and setter (same as file-selector)
|
||||
const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlock.id)
|
||||
// Reactive upstream fields
|
||||
@@ -42,20 +44,22 @@ export function ChannelSelectorInput({
|
||||
const provider = subBlock.provider || 'slack'
|
||||
const isSlack = provider === 'slack'
|
||||
// Central dependsOn gating
|
||||
const { finalDisabled } = useDependsOnGate(blockId, subBlock, { disabled, isPreview })
|
||||
const { finalDisabled, dependsOn, dependencyValues } = useDependsOnGate(blockId, subBlock, {
|
||||
disabled,
|
||||
isPreview,
|
||||
})
|
||||
|
||||
// Get the credential for the provider - use provided credential or fall back to reactive values
|
||||
let credential: string
|
||||
if (providedCredential) {
|
||||
credential = providedCredential
|
||||
} else if ((authMethod as string) === 'bot_token' && (botToken as string)) {
|
||||
credential = botToken as string
|
||||
} else {
|
||||
credential = (connectedCredential as string) || ''
|
||||
}
|
||||
// Choose credential strictly based on auth method
|
||||
const credential: string =
|
||||
(authMethod as string) === 'bot_token'
|
||||
? (botToken as string) || ''
|
||||
: (connectedCredential as string) || ''
|
||||
|
||||
// Use preview value when in preview mode, otherwise use store value
|
||||
const value = isPreview ? previewValue : storeValue
|
||||
// Determine if connected OAuth credential is foreign (not applicable for bot tokens)
|
||||
const { isForeignCredential } = useForeignCredential(
|
||||
'slack',
|
||||
(authMethod as string) === 'bot_token' ? '' : (connectedCredential as string) || ''
|
||||
)
|
||||
|
||||
// Get the current value from the store or prop value if in preview mode (same pattern as file-selector)
|
||||
useEffect(() => {
|
||||
@@ -65,6 +69,21 @@ export function ChannelSelectorInput({
|
||||
}
|
||||
}, [isPreview, previewValue, storeValue])
|
||||
|
||||
// Clear channel when any declared dependency changes (e.g., authMethod/credential)
|
||||
const prevDepsSigRef = useRef<string>('')
|
||||
useEffect(() => {
|
||||
if (dependsOn.length === 0) return
|
||||
const currentSig = JSON.stringify(dependencyValues)
|
||||
if (prevDepsSigRef.current && prevDepsSigRef.current !== currentSig) {
|
||||
if (!isPreview) {
|
||||
setSelectedChannelId('')
|
||||
setChannelInfo(null)
|
||||
setStoreValue('')
|
||||
}
|
||||
}
|
||||
prevDepsSigRef.current = currentSig
|
||||
}, [dependsOn, dependencyValues, isPreview, setStoreValue])
|
||||
|
||||
// Handle channel selection (same pattern as file-selector)
|
||||
const handleChannelChange = (channelId: string, info?: SlackChannelInfo) => {
|
||||
setSelectedChannelId(channelId)
|
||||
@@ -90,6 +109,8 @@ export function ChannelSelectorInput({
|
||||
credential={credential}
|
||||
label={subBlock.placeholder || 'Select Slack channel'}
|
||||
disabled={finalDisabled}
|
||||
workflowId={workflowIdFromUrl}
|
||||
isForeignCredential={isForeignCredential}
|
||||
/>
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
|
||||
@@ -24,6 +24,8 @@ interface SlackChannelSelectorProps {
|
||||
credential: string
|
||||
label?: string
|
||||
disabled?: boolean
|
||||
workflowId?: string
|
||||
isForeignCredential?: boolean
|
||||
}
|
||||
|
||||
export function SlackChannelSelector({
|
||||
@@ -32,6 +34,8 @@ export function SlackChannelSelector({
|
||||
credential,
|
||||
label = 'Select Slack channel',
|
||||
disabled = false,
|
||||
workflowId,
|
||||
isForeignCredential = false,
|
||||
}: SlackChannelSelectorProps) {
|
||||
const [channels, setChannels] = useState<SlackChannelInfo[]>([])
|
||||
const [loading, setLoading] = useState(false)
|
||||
@@ -51,7 +55,7 @@ export function SlackChannelSelector({
|
||||
const res = await fetch('/api/tools/slack/channels', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ credential }),
|
||||
body: JSON.stringify({ credential, workflowId }),
|
||||
})
|
||||
|
||||
if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`)
|
||||
@@ -125,6 +129,7 @@ export function SlackChannelSelector({
|
||||
aria-expanded={open}
|
||||
className='relative w-full justify-between'
|
||||
disabled={disabled || !credential}
|
||||
title={isForeignCredential ? 'Using a shared account' : undefined}
|
||||
>
|
||||
<div className='flex max-w-[calc(100%-20px)] items-center gap-2 overflow-hidden'>
|
||||
<SlackIcon className='h-4 w-4 text-[#611f69]' />
|
||||
@@ -133,6 +138,11 @@ export function SlackChannelSelector({
|
||||
{getChannelIcon(selectedChannel)}
|
||||
<span className='truncate font-normal'>{formatChannelName(selectedChannel)}</span>
|
||||
</>
|
||||
) : value ? (
|
||||
<>
|
||||
<Hash className='h-1.5 w-1.5' />
|
||||
<span className='truncate font-normal'>{value}</span>
|
||||
</>
|
||||
) : (
|
||||
<span className='truncate text-muted-foreground'>{label}</span>
|
||||
)}
|
||||
|
||||
@@ -876,44 +876,6 @@ export function ToolInput({
|
||||
return result
|
||||
}
|
||||
|
||||
// Helper function to get credential for channel selector
|
||||
const getCredentialForChannelSelector = (paramId: string): string => {
|
||||
// Look for the tool that contains this parameter
|
||||
const currentToolIndex = selectedTools.findIndex((tool) => {
|
||||
const toolParams = getToolParametersConfig(tool.toolId)
|
||||
return toolParams?.userInputParameters.some((p) => p.id === paramId)
|
||||
})
|
||||
|
||||
if (currentToolIndex === -1) return ''
|
||||
|
||||
const currentTool = selectedTools[currentToolIndex]
|
||||
|
||||
// Enhanced credential detection logic from legacy implementation
|
||||
// Check for bot token first, then OAuth credential
|
||||
const botToken =
|
||||
currentTool.params.botToken || (subBlockStore.getValue(blockId, 'botToken') as string)
|
||||
const oauthCredential =
|
||||
currentTool.params.credential || (subBlockStore.getValue(blockId, 'credential') as string)
|
||||
|
||||
if (botToken?.trim()) {
|
||||
return botToken
|
||||
}
|
||||
if (oauthCredential?.trim()) {
|
||||
return oauthCredential
|
||||
}
|
||||
|
||||
// Fallback: check for other common credential parameter names
|
||||
const credentialKeys = ['accessToken', 'token', 'apiKey', 'authToken']
|
||||
for (const key of credentialKeys) {
|
||||
const value = currentTool.params[key] || (subBlockStore.getValue(blockId, key) as string)
|
||||
if (value?.trim()) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
// Render the appropriate UI component based on parameter configuration
|
||||
const renderParameterInput = (
|
||||
param: ToolParameterConfig,
|
||||
@@ -1023,8 +985,9 @@ export function ToolInput({
|
||||
placeholder: uiComponent.placeholder,
|
||||
}}
|
||||
onChannelSelect={onChange}
|
||||
credential={getCredentialForChannelSelector(param.id)}
|
||||
disabled={disabled}
|
||||
isPreview={true}
|
||||
previewValue={value}
|
||||
/>
|
||||
)
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ export const SlackBlock: BlockConfig<SlackResponse> = {
|
||||
provider: 'slack',
|
||||
placeholder: 'Select Slack channel',
|
||||
mode: 'basic',
|
||||
dependsOn: ['credential', 'authMethod'],
|
||||
},
|
||||
// Manual channel ID input (advanced mode)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user