mirror of
https://github.com/langgenius/dify.git
synced 2026-05-05 18:08:07 +08:00
Merge remote-tracking branch 'origin/main' into feat/collaboration
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiDeleteBinLine, RiEditFill, RiEditLine } from '@remixicon/react'
|
||||
import { Robot, User } from '@/app/components/base/icons/src/public/avatar'
|
||||
@ -16,7 +16,7 @@ type Props = {
|
||||
type: EditItemType
|
||||
content: string
|
||||
readonly?: boolean
|
||||
onSave: (content: string) => void
|
||||
onSave: (content: string) => Promise<void>
|
||||
}
|
||||
|
||||
export const EditTitle: FC<{ className?: string; title: string }> = ({ className, title }) => (
|
||||
@ -46,8 +46,13 @@ const EditItem: FC<Props> = ({
|
||||
const placeholder = type === EditItemType.Query ? t('appAnnotation.editModal.queryPlaceholder') : t('appAnnotation.editModal.answerPlaceholder')
|
||||
const [isEdit, setIsEdit] = useState(false)
|
||||
|
||||
const handleSave = () => {
|
||||
onSave(newContent)
|
||||
// Reset newContent when content prop changes
|
||||
useEffect(() => {
|
||||
setNewContent('')
|
||||
}, [content])
|
||||
|
||||
const handleSave = async () => {
|
||||
await onSave(newContent)
|
||||
setIsEdit(false)
|
||||
}
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ type Props = {
|
||||
isShow: boolean
|
||||
onHide: () => void
|
||||
item: AnnotationItem
|
||||
onSave: (editedQuery: string, editedAnswer: string) => void
|
||||
onSave: (editedQuery: string, editedAnswer: string) => Promise<void>
|
||||
onRemove: () => void
|
||||
}
|
||||
|
||||
@ -46,6 +46,16 @@ const ViewAnnotationModal: FC<Props> = ({
|
||||
const [currPage, setCurrPage] = React.useState<number>(0)
|
||||
const [total, setTotal] = useState(0)
|
||||
const [hitHistoryList, setHitHistoryList] = useState<HitHistoryItem[]>([])
|
||||
|
||||
// Update local state when item prop changes (e.g., when modal is reopened with updated data)
|
||||
useEffect(() => {
|
||||
setNewQuery(question)
|
||||
setNewAnswer(answer)
|
||||
setCurrPage(0)
|
||||
setTotal(0)
|
||||
setHitHistoryList([])
|
||||
}, [question, answer, id])
|
||||
|
||||
const fetchHitHistory = async (page = 1) => {
|
||||
try {
|
||||
const { data, total }: any = await fetchHitHistoryList(appId, id, {
|
||||
@ -63,6 +73,12 @@ const ViewAnnotationModal: FC<Props> = ({
|
||||
fetchHitHistory(currPage + 1)
|
||||
}, [currPage])
|
||||
|
||||
// Fetch hit history when item changes
|
||||
useEffect(() => {
|
||||
if (isShow && id)
|
||||
fetchHitHistory(1)
|
||||
}, [id, isShow])
|
||||
|
||||
const tabs = [
|
||||
{ value: TabType.annotation, text: t('appAnnotation.viewModal.annotatedResponse') },
|
||||
{
|
||||
@ -82,14 +98,20 @@ const ViewAnnotationModal: FC<Props> = ({
|
||||
},
|
||||
]
|
||||
const [activeTab, setActiveTab] = useState(TabType.annotation)
|
||||
const handleSave = (type: EditItemType, editedContent: string) => {
|
||||
if (type === EditItemType.Query) {
|
||||
setNewQuery(editedContent)
|
||||
onSave(editedContent, newAnswer)
|
||||
const handleSave = async (type: EditItemType, editedContent: string) => {
|
||||
try {
|
||||
if (type === EditItemType.Query) {
|
||||
await onSave(editedContent, newAnswer)
|
||||
setNewQuery(editedContent)
|
||||
}
|
||||
else {
|
||||
await onSave(newQuestion, editedContent)
|
||||
setNewAnswer(editedContent)
|
||||
}
|
||||
}
|
||||
else {
|
||||
setNewAnswer(editedContent)
|
||||
onSave(newQuestion, editedContent)
|
||||
catch (error) {
|
||||
// If save fails, don't update local state
|
||||
console.error('Failed to save annotation:', error)
|
||||
}
|
||||
}
|
||||
const [showModal, setShowModal] = useState(false)
|
||||
|
||||
@ -22,7 +22,7 @@ const AccessControlDialog = ({
|
||||
}, [onClose])
|
||||
return (
|
||||
<Transition appear show={show} as={Fragment}>
|
||||
<Dialog as="div" open={true} className="relative z-20" onClose={() => null}>
|
||||
<Dialog as="div" open={true} className="relative z-[99]" onClose={() => null}>
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
@ -32,7 +32,7 @@ const AccessControlDialog = ({
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="bg-background-overlay/25 fixed inset-0" />
|
||||
<div className="fixed inset-0 bg-background-overlay" />
|
||||
</Transition.Child>
|
||||
|
||||
<div className="fixed inset-0 flex items-center justify-center">
|
||||
|
||||
@ -52,7 +52,7 @@ export default function AddMemberOrGroupDialog() {
|
||||
</Button>
|
||||
</PortalToFollowElemTrigger>
|
||||
{open && <FloatingOverlay />}
|
||||
<PortalToFollowElemContent className='z-[25]'>
|
||||
<PortalToFollowElemContent className='z-[100]'>
|
||||
<div className='relative flex max-h-[400px] w-[400px] flex-col overflow-y-auto rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg backdrop-blur-[5px]'>
|
||||
<div className='sticky top-0 z-10 bg-components-panel-bg-blur p-2 pb-0.5 backdrop-blur-[5px]'>
|
||||
<Input value={keyword} onChange={handleKeywordChange} showLeftIcon placeholder={t('app.accessControlDialog.operateGroupAndMember.searchPlaceholder') as string} />
|
||||
|
||||
@ -4,7 +4,6 @@ import {
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useAsyncEffect } from 'ahooks'
|
||||
import { useThemeContext } from '../embedded-chatbot/theme/theme-context'
|
||||
import {
|
||||
ChatWithHistoryContext,
|
||||
@ -18,8 +17,6 @@ import ChatWrapper from './chat-wrapper'
|
||||
import type { InstalledApp } from '@/models/explore'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import { checkOrSetAccessToken } from '@/app/components/share/utils'
|
||||
import AppUnavailable from '@/app/components/base/app-unavailable'
|
||||
import cn from '@/utils/classnames'
|
||||
import useDocumentTitle from '@/hooks/use-document-title'
|
||||
|
||||
@ -201,36 +198,6 @@ const ChatWithHistoryWrapWithCheckToken: FC<ChatWithHistoryWrapProps> = ({
|
||||
installedAppInfo,
|
||||
className,
|
||||
}) => {
|
||||
const [initialized, setInitialized] = useState(false)
|
||||
const [appUnavailable, setAppUnavailable] = useState<boolean>(false)
|
||||
const [isUnknownReason, setIsUnknownReason] = useState<boolean>(false)
|
||||
|
||||
useAsyncEffect(async () => {
|
||||
if (!initialized) {
|
||||
if (!installedAppInfo) {
|
||||
try {
|
||||
await checkOrSetAccessToken()
|
||||
}
|
||||
catch (e: any) {
|
||||
if (e.status === 404) {
|
||||
setAppUnavailable(true)
|
||||
}
|
||||
else {
|
||||
setIsUnknownReason(true)
|
||||
setAppUnavailable(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
setInitialized(true)
|
||||
}
|
||||
}, [])
|
||||
|
||||
if (!initialized)
|
||||
return null
|
||||
|
||||
if (appUnavailable)
|
||||
return <AppUnavailable isUnknownReason={isUnknownReason} />
|
||||
|
||||
return (
|
||||
<ChatWithHistoryWrap
|
||||
installedAppInfo={installedAppInfo}
|
||||
|
||||
@ -25,7 +25,6 @@ import Compliance from './compliance'
|
||||
import PremiumBadge from '@/app/components/base/premium-badge'
|
||||
import Avatar from '@/app/components/base/avatar'
|
||||
import ThemeSwitcher from '@/app/components/base/theme-switcher'
|
||||
import { logout } from '@/service/common'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { useModalContext } from '@/context/modal-context'
|
||||
@ -33,6 +32,7 @@ import { IS_CLOUD_EDITION } from '@/config'
|
||||
import cn from '@/utils/classnames'
|
||||
import { useGlobalPublicStore } from '@/context/global-public-context'
|
||||
import { useDocLink } from '@/context/i18n'
|
||||
import { useLogout } from '@/service/use-common'
|
||||
|
||||
export default function AppSelector() {
|
||||
const itemClassName = `
|
||||
@ -49,15 +49,12 @@ export default function AppSelector() {
|
||||
const { isEducationAccount } = useProviderContext()
|
||||
const { setShowAccountSettingModal } = useModalContext()
|
||||
|
||||
const { mutateAsync: logout } = useLogout()
|
||||
const handleLogout = async () => {
|
||||
await logout({
|
||||
url: '/logout',
|
||||
params: {},
|
||||
})
|
||||
await logout()
|
||||
|
||||
localStorage.removeItem('setup_status')
|
||||
localStorage.removeItem('console_token')
|
||||
localStorage.removeItem('refresh_token')
|
||||
// Tokens are now stored in cookies and cleared by backend
|
||||
|
||||
// To avoid use other account's education notice info
|
||||
localStorage.removeItem('education-reverify-prev-expire-at')
|
||||
|
||||
@ -77,7 +77,7 @@ export const useNodesSyncDraft = () => {
|
||||
|
||||
if (postParams) {
|
||||
navigator.sendBeacon(
|
||||
`${API_PREFIX}${postParams.url}?_token=${localStorage.getItem('console_token')}`,
|
||||
`${API_PREFIX}${postParams.url}`,
|
||||
JSON.stringify(postParams.params),
|
||||
)
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ import type { SiteInfo } from '@/models/share'
|
||||
import cn from '@/utils/classnames'
|
||||
import { AccessMode } from '@/models/access-control'
|
||||
import { useWebAppStore } from '@/context/web-app-context'
|
||||
import { webAppLogout } from '@/service/webapp-auth'
|
||||
|
||||
type Props = {
|
||||
data?: SiteInfo
|
||||
@ -49,11 +50,11 @@ const MenuDropdown: FC<Props> = ({
|
||||
setOpen(!openRef.current)
|
||||
}, [setOpen])
|
||||
|
||||
const handleLogout = useCallback(() => {
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('webapp_access_token')
|
||||
const shareCode = useWebAppStore(s => s.shareCode)
|
||||
const handleLogout = useCallback(async () => {
|
||||
await webAppLogout(shareCode!)
|
||||
router.replace(`/webapp-signin?redirect_url=${pathname}`)
|
||||
}, [router, pathname])
|
||||
}, [router, pathname, webAppLogout, shareCode])
|
||||
|
||||
const [show, setShow] = useState(false)
|
||||
|
||||
|
||||
@ -1,7 +1,3 @@
|
||||
import { CONVERSATION_ID_INFO } from '../base/chat/constants'
|
||||
import { fetchAccessToken } from '@/service/share'
|
||||
import { getProcessedSystemVariablesFromUrlParams } from '../base/chat/utils'
|
||||
|
||||
export const isTokenV1 = (token: Record<string, any>) => {
|
||||
return !token.version
|
||||
}
|
||||
@ -9,55 +5,3 @@ export const isTokenV1 = (token: Record<string, any>) => {
|
||||
export const getInitialTokenV2 = (): Record<string, any> => ({
|
||||
version: 2,
|
||||
})
|
||||
|
||||
export const checkOrSetAccessToken = async (appCode?: string | null) => {
|
||||
const sharedToken = appCode || globalThis.location.pathname.split('/').slice(-1)[0]
|
||||
const userId = (await getProcessedSystemVariablesFromUrlParams()).user_id
|
||||
const accessToken = localStorage.getItem('token') || JSON.stringify(getInitialTokenV2())
|
||||
let accessTokenJson = getInitialTokenV2()
|
||||
try {
|
||||
accessTokenJson = JSON.parse(accessToken)
|
||||
if (isTokenV1(accessTokenJson))
|
||||
accessTokenJson = getInitialTokenV2()
|
||||
}
|
||||
catch {
|
||||
|
||||
}
|
||||
|
||||
if (!accessTokenJson[sharedToken]?.[userId || 'DEFAULT']) {
|
||||
const webAppAccessToken = localStorage.getItem('webapp_access_token')
|
||||
const res = await fetchAccessToken({ appCode: sharedToken, userId, webAppAccessToken })
|
||||
accessTokenJson[sharedToken] = {
|
||||
...accessTokenJson[sharedToken],
|
||||
[userId || 'DEFAULT']: res.access_token,
|
||||
}
|
||||
localStorage.setItem('token', JSON.stringify(accessTokenJson))
|
||||
localStorage.removeItem(CONVERSATION_ID_INFO)
|
||||
}
|
||||
}
|
||||
|
||||
export const setAccessToken = (sharedToken: string, token: string, user_id?: string) => {
|
||||
const accessToken = localStorage.getItem('token') || JSON.stringify(getInitialTokenV2())
|
||||
let accessTokenJson = getInitialTokenV2()
|
||||
try {
|
||||
accessTokenJson = JSON.parse(accessToken)
|
||||
if (isTokenV1(accessTokenJson))
|
||||
accessTokenJson = getInitialTokenV2()
|
||||
}
|
||||
catch {
|
||||
|
||||
}
|
||||
|
||||
localStorage.removeItem(CONVERSATION_ID_INFO)
|
||||
|
||||
accessTokenJson[sharedToken] = {
|
||||
...accessTokenJson[sharedToken],
|
||||
[user_id || 'DEFAULT']: token,
|
||||
}
|
||||
localStorage.setItem('token', JSON.stringify(accessTokenJson))
|
||||
}
|
||||
|
||||
export const removeAccessToken = () => {
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('webapp_access_token')
|
||||
}
|
||||
|
||||
@ -19,10 +19,7 @@ const SwrInitializer = ({
|
||||
}: SwrInitializerProps) => {
|
||||
const router = useRouter()
|
||||
const searchParams = useSearchParams()
|
||||
const consoleToken = decodeURIComponent(searchParams.get('access_token') || '')
|
||||
const refreshToken = decodeURIComponent(searchParams.get('refresh_token') || '')
|
||||
const consoleTokenFromLocalStorage = localStorage?.getItem('console_token')
|
||||
const refreshTokenFromLocalStorage = localStorage?.getItem('refresh_token')
|
||||
// Tokens are now stored in cookies, no need to check localStorage
|
||||
const pathname = usePathname()
|
||||
const [init, setInit] = useState(false)
|
||||
|
||||
@ -57,21 +54,12 @@ const SwrInitializer = ({
|
||||
router.replace('/install')
|
||||
return
|
||||
}
|
||||
if (!((consoleToken && refreshToken) || (consoleTokenFromLocalStorage && refreshTokenFromLocalStorage))) {
|
||||
router.replace('/signin')
|
||||
return
|
||||
}
|
||||
if (searchParams.has('access_token') || searchParams.has('refresh_token')) {
|
||||
if (consoleToken)
|
||||
localStorage.setItem('console_token', consoleToken)
|
||||
if (refreshToken)
|
||||
localStorage.setItem('refresh_token', refreshToken)
|
||||
const redirectUrl = resolvePostLoginRedirect(searchParams)
|
||||
if (redirectUrl)
|
||||
location.replace(redirectUrl)
|
||||
else
|
||||
router.replace(pathname)
|
||||
}
|
||||
|
||||
const redirectUrl = resolvePostLoginRedirect(searchParams)
|
||||
if (redirectUrl)
|
||||
location.replace(redirectUrl)
|
||||
else
|
||||
router.replace(pathname)
|
||||
|
||||
setInit(true)
|
||||
}
|
||||
@ -79,7 +67,7 @@ const SwrInitializer = ({
|
||||
router.replace('/signin')
|
||||
}
|
||||
})()
|
||||
}, [isSetupFinished, router, pathname, searchParams, consoleToken, refreshToken, consoleTokenFromLocalStorage, refreshTokenFromLocalStorage])
|
||||
}, [isSetupFinished, router, pathname, searchParams])
|
||||
|
||||
return init
|
||||
? (
|
||||
|
||||
@ -110,7 +110,7 @@ export const useNodesSyncDraft = () => {
|
||||
if (postParams) {
|
||||
console.log('Leader syncing workflow draft on page close')
|
||||
navigator.sendBeacon(
|
||||
`${API_PREFIX}/apps/${params.appId}/workflows/draft?_token=${localStorage.getItem('console_token')}`,
|
||||
`${API_PREFIX}/apps/${params.appId}/workflows/draft`,
|
||||
JSON.stringify(postParams.params),
|
||||
)
|
||||
}
|
||||
|
||||
@ -178,6 +178,7 @@ const ToolPicker: FC<Props> = ({
|
||||
mcpTools={mcpTools || []}
|
||||
selectedTools={selectedTools}
|
||||
canChooseMCPTool={canChooseMCPTool}
|
||||
onTagsChange={setTags}
|
||||
/>
|
||||
</div>
|
||||
</PortalToFollowElemContent>
|
||||
|
||||
@ -39,7 +39,6 @@ const Item: FC<Props> = ({
|
||||
key={tool.id}
|
||||
payload={tool}
|
||||
viewType={ViewType.tree}
|
||||
isShowLetterIndex={false}
|
||||
hasSearchText={hasSearchText}
|
||||
onSelect={onSelect}
|
||||
canNotSelectMultiple={canNotSelectMultiple}
|
||||
|
||||
@ -37,6 +37,7 @@ export type ToolDefaultValue = {
|
||||
paramSchemas: Record<string, any>[]
|
||||
credential_id?: string
|
||||
meta?: PluginMeta
|
||||
output_schema?: Record<string, any>
|
||||
}
|
||||
|
||||
export type DataSourceDefaultValue = {
|
||||
|
||||
@ -8,8 +8,8 @@ export enum ScrollPosition {
|
||||
}
|
||||
|
||||
type Params = {
|
||||
wrapElemRef: React.RefObject<HTMLElement>
|
||||
nextToStickyELemRef: React.RefObject<HTMLElement>
|
||||
wrapElemRef: React.RefObject<HTMLElement | null>
|
||||
nextToStickyELemRef: React.RefObject<HTMLElement | null>
|
||||
}
|
||||
const useStickyScroll = ({
|
||||
wrapElemRef,
|
||||
|
||||
@ -21,7 +21,7 @@ const DatasetsDetailProvider: FC<DatasetsDetailProviderProps> = ({
|
||||
nodes,
|
||||
children,
|
||||
}) => {
|
||||
const storeRef = useRef<DatasetsDetailStoreApi>()
|
||||
const storeRef = useRef<DatasetsDetailStoreApi>(undefined)
|
||||
|
||||
if (!storeRef.current)
|
||||
storeRef.current = createDatasetsDetailStore()
|
||||
|
||||
@ -15,7 +15,7 @@ import {
|
||||
getOutgoers,
|
||||
useReactFlow,
|
||||
} from 'reactflow'
|
||||
import type { ToolDefaultValue } from '../block-selector/types'
|
||||
import type { DataSourceDefaultValue, ToolDefaultValue } from '../block-selector/types'
|
||||
import type { Edge, Node, OnNodeAdd } from '../types'
|
||||
import { BlockEnum } from '../types'
|
||||
import { useWorkflowStore } from '../store'
|
||||
@ -1264,7 +1264,7 @@ export const useNodesInteractions = () => {
|
||||
currentNodeId: string,
|
||||
nodeType: BlockEnum,
|
||||
sourceHandle: string,
|
||||
toolDefaultValue?: ToolDefaultValue,
|
||||
toolDefaultValue?: ToolDefaultValue | DataSourceDefaultValue,
|
||||
) => {
|
||||
if (getNodesReadOnly()) return
|
||||
|
||||
|
||||
@ -212,7 +212,7 @@ export const AgentStrategySelector = memo((props: AgentStrategySelectorProps) =>
|
||||
agent_strategy_name: tool!.tool_name,
|
||||
agent_strategy_provider_name: tool!.provider_name,
|
||||
agent_strategy_label: tool!.tool_label,
|
||||
agent_output_schema: tool!.output_schema,
|
||||
agent_output_schema: tool!.output_schema || {},
|
||||
plugin_unique_identifier: tool!.provider_id,
|
||||
meta: tool!.meta,
|
||||
})
|
||||
|
||||
@ -28,7 +28,6 @@ const getIcon = (type: InputVarType) => {
|
||||
[InputVarType.jsonObject]: RiBracesLine,
|
||||
[InputVarType.singleFile]: RiFileList2Line,
|
||||
[InputVarType.multiFiles]: RiFileCopy2Line,
|
||||
[InputVarType.checkbox]: RiCheckboxLine,
|
||||
} as any)[type] || RiTextSnippet
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ import {
|
||||
} from '../../../types'
|
||||
import type { Node } from '../../../types'
|
||||
import BlockSelector from '../../../block-selector'
|
||||
import type { ToolDefaultValue } from '../../../block-selector/types'
|
||||
import type { DataSourceDefaultValue, ToolDefaultValue } from '../../../block-selector/types'
|
||||
import {
|
||||
useAvailableBlocks,
|
||||
useIsChatMode,
|
||||
@ -57,7 +57,7 @@ export const NodeTargetHandle = memo(({
|
||||
if (!connected)
|
||||
setOpen(v => !v)
|
||||
}, [connected])
|
||||
const handleSelect = useCallback((type: BlockEnum, toolDefaultValue?: ToolDefaultValue) => {
|
||||
const handleSelect = useCallback((type: BlockEnum, toolDefaultValue?: ToolDefaultValue | DataSourceDefaultValue) => {
|
||||
handleNodeAdd(
|
||||
{
|
||||
nodeType: type,
|
||||
@ -140,7 +140,7 @@ export const NodeSourceHandle = memo(({
|
||||
e.stopPropagation()
|
||||
setOpen(v => !v)
|
||||
}, [])
|
||||
const handleSelect = useCallback((type: BlockEnum, toolDefaultValue?: ToolDefaultValue) => {
|
||||
const handleSelect = useCallback((type: BlockEnum, toolDefaultValue?: ToolDefaultValue | DataSourceDefaultValue) => {
|
||||
handleNodeAdd(
|
||||
{
|
||||
nodeType: type,
|
||||
|
||||
@ -42,17 +42,17 @@ export const useVarColor = (variables: string[], isExceptionVariable?: boolean,
|
||||
return 'text-util-colors-teal-teal-700'
|
||||
|
||||
return 'text-text-accent'
|
||||
}, [variables, isExceptionVariable])
|
||||
}, [variables, isExceptionVariable, variableCategory])
|
||||
}
|
||||
|
||||
export const useVarName = (variables: string[], notShowFullPath?: boolean) => {
|
||||
let variableFullPathName = variables.slice(1).join('.')
|
||||
|
||||
if (isRagVariableVar(variables))
|
||||
variableFullPathName = variables.slice(2).join('.')
|
||||
|
||||
const variablesLength = variables.length
|
||||
const varName = useMemo(() => {
|
||||
let variableFullPathName = variables.slice(1).join('.')
|
||||
|
||||
if (isRagVariableVar(variables))
|
||||
variableFullPathName = variables.slice(2).join('.')
|
||||
|
||||
const variablesLength = variables.length
|
||||
const isSystem = isSystemVar(variables)
|
||||
const varName = notShowFullPath ? variables[variablesLength - 1] : variableFullPathName
|
||||
return `${isSystem ? 'sys.' : ''}${varName}`
|
||||
|
||||
@ -53,8 +53,13 @@ import { useAppContext } from '@/context/app-context'
|
||||
import { useStore } from '@/app/components/workflow/store'
|
||||
import { useCollaboration } from '@/app/components/workflow/collaboration/hooks/use-collaboration'
|
||||
|
||||
type NodeChildProps = {
|
||||
id: string
|
||||
data: NodeProps['data']
|
||||
}
|
||||
|
||||
type BaseNodeProps = {
|
||||
children: ReactElement
|
||||
children: ReactElement<Partial<NodeChildProps>>
|
||||
id: NodeProps['id']
|
||||
data: NodeProps['data']
|
||||
}
|
||||
|
||||
@ -11,6 +11,11 @@ export type OutputVar = Record<string, {
|
||||
children: null // support nest in the future,
|
||||
}>
|
||||
|
||||
export type CodeDependency = {
|
||||
name: string
|
||||
version?: string
|
||||
}
|
||||
|
||||
export type CodeNodeType = CommonNodeType & {
|
||||
variables: Variable[]
|
||||
code_language: CodeLanguage
|
||||
|
||||
@ -16,7 +16,7 @@ import {
|
||||
const useConfig = (id: string, payload: HttpNodeType) => {
|
||||
const { nodesReadOnly: readOnly } = useNodesReadOnly()
|
||||
|
||||
const defaultConfig = useStore(s => s.nodesDefaultConfigs)[payload.type]
|
||||
const defaultConfig = useStore(s => s.nodesDefaultConfigs?.[payload.type])
|
||||
|
||||
const { inputs, setInputs } = useNodeCrud<HttpNodeType>(id, payload)
|
||||
|
||||
|
||||
@ -209,7 +209,7 @@ const ConditionItem = ({
|
||||
onRemoveCondition?.(caseId, condition.id)
|
||||
}, [caseId, condition, conditionId, isSubVariableKey, onRemoveCondition, onRemoveSubVariableCondition])
|
||||
|
||||
const { getMatchedSchemaType } = useMatchSchemaType()
|
||||
const { schemaTypeDefinitions } = useMatchSchemaType()
|
||||
const handleVarChange = useCallback((valueSelector: ValueSelector, _varItem: Var) => {
|
||||
const {
|
||||
conversationVariables,
|
||||
@ -226,7 +226,7 @@ const ConditionItem = ({
|
||||
workflowTools,
|
||||
dataSourceList: dataSourceList ?? [],
|
||||
},
|
||||
getMatchedSchemaType,
|
||||
schemaTypeDefinitions,
|
||||
})
|
||||
|
||||
const newCondition = produce(condition, (draft) => {
|
||||
@ -241,7 +241,7 @@ const ConditionItem = ({
|
||||
})
|
||||
doUpdateCondition(newCondition)
|
||||
setOpen(false)
|
||||
}, [condition, doUpdateCondition, availableNodes, isChatMode, setControlPromptEditorRerenderKey])
|
||||
}, [condition, doUpdateCondition, availableNodes, isChatMode, setControlPromptEditorRerenderKey, schemaTypeDefinitions])
|
||||
|
||||
const showBooleanInput = useMemo(() => {
|
||||
if(condition.varType === VarType.boolean)
|
||||
|
||||
Reference in New Issue
Block a user