mirror of
https://github.com/langgenius/dify.git
synced 2026-05-04 09:28:04 +08:00
chore: remove frontend changes
This commit is contained in:
@ -1,17 +1,18 @@
|
||||
import React, { useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiBracesLine, RiEyeLine } from '@remixicon/react'
|
||||
import Textarea from '@/app/components/base/textarea'
|
||||
import { Markdown } from '@/app/components/base/markdown'
|
||||
import SchemaEditor from '@/app/components/workflow/nodes/llm/components/json-schema-config-modal/schema-editor'
|
||||
import { SegmentedControl } from '@/app/components/base/segmented-control'
|
||||
import cn from '@/utils/classnames'
|
||||
import { ChunkCardList } from '@/app/components/rag-pipeline/components/chunk-card-list'
|
||||
import type { VarType } from '../types'
|
||||
import type { ChunkInfo } from '@/app/components/rag-pipeline/components/chunk-card-list/types'
|
||||
import type { ParentMode } from '@/models/datasets'
|
||||
import { RiBracesLine, RiEyeLine } from '@remixicon/react'
|
||||
import * as React from 'react'
|
||||
import { useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Markdown } from '@/app/components/base/markdown'
|
||||
import { SegmentedControl } from '@/app/components/base/segmented-control'
|
||||
import Textarea from '@/app/components/base/textarea'
|
||||
import { ChunkCardList } from '@/app/components/rag-pipeline/components/chunk-card-list'
|
||||
import SchemaEditor from '@/app/components/workflow/nodes/llm/components/json-schema-config-modal/schema-editor'
|
||||
import { ChunkingMode } from '@/models/datasets'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { PreviewType, ViewMode } from './types'
|
||||
import type { VarType } from '../types'
|
||||
|
||||
type DisplayContentProps = {
|
||||
previewType: PreviewType
|
||||
@ -52,61 +53,68 @@ const DisplayContent = (props: DisplayContentProps) => {
|
||||
|
||||
return (
|
||||
<div className={cn('flex h-full flex-col rounded-[10px] bg-components-input-bg-normal', isFocused && 'bg-components-input-bg-active outline outline-1 outline-components-input-border-active', className)}>
|
||||
<div className='flex shrink-0 items-center justify-end p-1'>
|
||||
<div className="flex shrink-0 items-center justify-end p-1">
|
||||
{previewType === PreviewType.Markdown && (
|
||||
<div className='system-xs-semibold-uppercase flex grow items-center px-2 py-0.5 text-text-secondary'>
|
||||
<div className="system-xs-semibold-uppercase flex grow items-center px-2 py-0.5 text-text-secondary">
|
||||
{previewType.toUpperCase()}
|
||||
</div>
|
||||
)}
|
||||
{previewType === PreviewType.Chunks && (
|
||||
<div className='system-xs-semibold-uppercase flex grow items-center px-2 py-0.5 text-text-secondary'>
|
||||
{varType.toUpperCase()}{schemaType ? `(${schemaType})` : ''}
|
||||
<div className="system-xs-semibold-uppercase flex grow items-center px-2 py-0.5 text-text-secondary">
|
||||
{varType.toUpperCase()}
|
||||
{schemaType ? `(${schemaType})` : ''}
|
||||
</div>
|
||||
)}
|
||||
<SegmentedControl
|
||||
options={[
|
||||
{ value: ViewMode.Code, text: t('workflow.nodes.templateTransform.code'), Icon: RiBracesLine },
|
||||
{ value: ViewMode.Preview, text: t('workflow.common.preview'), Icon: RiEyeLine },
|
||||
{ value: ViewMode.Code, text: t('nodes.templateTransform.code', { ns: 'workflow' }), Icon: RiBracesLine },
|
||||
{ value: ViewMode.Preview, text: t('common.preview', { ns: 'workflow' }), Icon: RiEyeLine },
|
||||
]}
|
||||
value={viewMode}
|
||||
onChange={setViewMode}
|
||||
size='small'
|
||||
padding='with'
|
||||
activeClassName='!text-text-accent-light-mode-only'
|
||||
btnClassName='!pl-1.5 !pr-0.5 gap-[3px]'
|
||||
className='shrink-0'
|
||||
size="small"
|
||||
padding="with"
|
||||
activeClassName="!text-text-accent-light-mode-only"
|
||||
btnClassName="!pl-1.5 !pr-0.5 gap-[3px]"
|
||||
className="shrink-0"
|
||||
/>
|
||||
</div>
|
||||
<div className='flex flex-1 overflow-auto rounded-b-[10px] pl-3 pr-1'>
|
||||
<div className="flex flex-1 overflow-auto rounded-b-[10px] pl-3 pr-1">
|
||||
{viewMode === ViewMode.Code && (
|
||||
previewType === PreviewType.Markdown
|
||||
? <Textarea
|
||||
readOnly={readonly}
|
||||
disabled={readonly}
|
||||
className='h-full border-none bg-transparent p-0 text-text-secondary hover:bg-transparent focus:bg-transparent focus:shadow-none'
|
||||
value={mdString as any}
|
||||
onChange={e => handleTextChange?.(e.target.value)}
|
||||
onFocus={() => setIsFocused(true)}
|
||||
onBlur={() => setIsFocused(false)}
|
||||
/>
|
||||
: <SchemaEditor
|
||||
readonly={readonly}
|
||||
className='overflow-y-auto bg-transparent'
|
||||
hideTopMenu
|
||||
schema={jsonString!}
|
||||
onUpdate={handleEditorChange!}
|
||||
onFocus={() => setIsFocused(true)}
|
||||
onBlur={() => setIsFocused(false)}
|
||||
/>
|
||||
? (
|
||||
<Textarea
|
||||
readOnly={readonly}
|
||||
disabled={readonly}
|
||||
className="h-full border-none bg-transparent p-0 text-text-secondary hover:bg-transparent focus:bg-transparent focus:shadow-none"
|
||||
value={mdString as any}
|
||||
onChange={e => handleTextChange?.(e.target.value)}
|
||||
onFocus={() => setIsFocused(true)}
|
||||
onBlur={() => setIsFocused(false)}
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<SchemaEditor
|
||||
readonly={readonly}
|
||||
className="overflow-y-auto bg-transparent"
|
||||
hideTopMenu
|
||||
schema={jsonString!}
|
||||
onUpdate={handleEditorChange!}
|
||||
onFocus={() => setIsFocused(true)}
|
||||
onBlur={() => setIsFocused(false)}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
{viewMode === ViewMode.Preview && (
|
||||
previewType === PreviewType.Markdown
|
||||
? <Markdown className='grow overflow-auto rounded-lg px-4 py-3' content={(mdString ?? '') as string} />
|
||||
: <ChunkCardList
|
||||
chunkType={chunkType!}
|
||||
parentMode={parentMode}
|
||||
chunkInfo={JSON.parse(jsonString!) as ChunkInfo}
|
||||
/>
|
||||
? <Markdown className="grow overflow-auto rounded-lg px-4 py-3" content={(mdString ?? '') as string} />
|
||||
: (
|
||||
<ChunkCardList
|
||||
chunkType={chunkType!}
|
||||
parentMode={parentMode}
|
||||
chunkInfo={JSON.parse(jsonString!) as ChunkInfo}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -6,19 +6,20 @@ const Empty: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className='flex h-full flex-col gap-3 rounded-xl bg-background-section p-8'>
|
||||
<div className='flex h-10 w-10 items-center justify-center rounded-[10px] border-[0.5px] border-components-card-border bg-components-card-bg shadow-lg backdrop-blur-sm'>
|
||||
<Variable02 className='h-5 w-5 text-text-accent' />
|
||||
<div className="flex h-full flex-col gap-3 rounded-xl bg-background-section p-8">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-[10px] border-[0.5px] border-components-card-border bg-components-card-bg shadow-lg backdrop-blur-sm">
|
||||
<Variable02 className="h-5 w-5 text-text-accent" />
|
||||
</div>
|
||||
<div className='flex flex-col gap-1'>
|
||||
<div className='system-sm-semibold text-text-secondary'>{t('workflow.debug.variableInspect.title')}</div>
|
||||
<div className='system-xs-regular text-text-tertiary'>{t('workflow.debug.variableInspect.emptyTip')}</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="system-sm-semibold text-text-secondary">{t('debug.variableInspect.title', { ns: 'workflow' })}</div>
|
||||
<div className="system-xs-regular text-text-tertiary">{t('debug.variableInspect.emptyTip', { ns: 'workflow' })}</div>
|
||||
<a
|
||||
className='system-xs-regular cursor-pointer text-text-accent'
|
||||
href='https://docs.dify.ai/en/guides/workflow/debug-and-preview/variable-inspect'
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'>
|
||||
{t('workflow.debug.variableInspect.emptyLink')}
|
||||
className="system-xs-regular cursor-pointer text-text-accent"
|
||||
href="https://docs.dify.ai/en/guides/workflow/debug-and-preview/variable-inspect"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{t('debug.variableInspect.emptyLink', { ns: 'workflow' })}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { currentVarType } from './panel'
|
||||
import type { NodeWithVar, VarInInspect } from '@/types/workflow'
|
||||
import {
|
||||
RiArrowRightSLine,
|
||||
RiDeleteBinLine,
|
||||
@ -7,16 +7,16 @@ import {
|
||||
RiLoader2Line,
|
||||
// RiErrorWarningFill,
|
||||
} from '@remixicon/react'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
// import Button from '@/app/components/base/button'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import BlockIcon from '@/app/components/workflow/block-icon'
|
||||
import type { currentVarType } from './panel'
|
||||
import { VarInInspectType } from '@/types/workflow'
|
||||
import type { NodeWithVar, VarInInspect } from '@/types/workflow'
|
||||
import cn from '@/utils/classnames'
|
||||
import { useToolIcon } from '../hooks'
|
||||
import { VariableIconWithColor } from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
|
||||
import { VarInInspectType } from '@/types/workflow'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { useToolIcon } from '../hooks'
|
||||
|
||||
type Props = {
|
||||
nodeData?: NodeWithVar
|
||||
@ -86,7 +86,8 @@ const Group = ({
|
||||
})
|
||||
return
|
||||
}
|
||||
if (!nodeData) return
|
||||
if (!nodeData)
|
||||
return
|
||||
handleSelect({
|
||||
nodeId: nodeData.nodeId,
|
||||
nodeType: nodeData.nodeType,
|
||||
@ -96,47 +97,47 @@ const Group = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='p-0.5'>
|
||||
<div className="p-0.5">
|
||||
{/* node item */}
|
||||
<div className='group flex h-6 items-center gap-0.5'>
|
||||
<div className='h-3 w-3 shrink-0'>
|
||||
<div className="group flex h-6 items-center gap-0.5">
|
||||
<div className="h-3 w-3 shrink-0">
|
||||
{nodeData?.isSingRunRunning && (
|
||||
<RiLoader2Line className='h-3 w-3 animate-spin text-text-accent' />
|
||||
<RiLoader2Line className="h-3 w-3 animate-spin text-text-accent" />
|
||||
)}
|
||||
{(!nodeData || !nodeData.isSingRunRunning) && visibleVarList.length > 0 && (
|
||||
<RiArrowRightSLine className={cn('h-3 w-3 text-text-tertiary', !isCollapsed && 'rotate-90')} onClick={() => setIsCollapsed(!isCollapsed)} />
|
||||
)}
|
||||
</div>
|
||||
<div className='flex grow cursor-pointer items-center gap-1' onClick={() => setIsCollapsed(!isCollapsed)}>
|
||||
<div className="flex grow cursor-pointer items-center gap-1" onClick={() => setIsCollapsed(!isCollapsed)}>
|
||||
{nodeData && (
|
||||
<>
|
||||
<BlockIcon
|
||||
className='shrink-0'
|
||||
className="shrink-0"
|
||||
type={nodeData.nodeType}
|
||||
toolIcon={toolIcon || ''}
|
||||
size='xs'
|
||||
size="xs"
|
||||
/>
|
||||
<div className='system-xs-medium-uppercase truncate text-text-tertiary'>{nodeData.title}</div>
|
||||
<div className="system-xs-medium-uppercase truncate text-text-tertiary">{nodeData.title}</div>
|
||||
</>
|
||||
)}
|
||||
{!nodeData && (
|
||||
<div className='system-xs-medium-uppercase truncate text-text-tertiary'>
|
||||
{isEnv && t('workflow.debug.variableInspect.envNode')}
|
||||
{isChatVar && t('workflow.debug.variableInspect.chatNode')}
|
||||
{isSystem && t('workflow.debug.variableInspect.systemNode')}
|
||||
<div className="system-xs-medium-uppercase truncate text-text-tertiary">
|
||||
{isEnv && t('debug.variableInspect.envNode', { ns: 'workflow' })}
|
||||
{isChatVar && t('debug.variableInspect.chatNode', { ns: 'workflow' })}
|
||||
{isSystem && t('debug.variableInspect.systemNode', { ns: 'workflow' })}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{nodeData && !nodeData.isSingRunRunning && (
|
||||
<div className='hidden shrink-0 items-center group-hover:flex'>
|
||||
<Tooltip popupContent={t('workflow.debug.variableInspect.view')}>
|
||||
<div className="hidden shrink-0 items-center group-hover:flex">
|
||||
<Tooltip popupContent={t('debug.variableInspect.view', { ns: 'workflow' })}>
|
||||
<ActionButton onClick={handleView}>
|
||||
<RiFileList3Line className='h-4 w-4' />
|
||||
<RiFileList3Line className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
<Tooltip popupContent={t('workflow.debug.variableInspect.clearNode')}>
|
||||
<Tooltip popupContent={t('debug.variableInspect.clearNode', { ns: 'workflow' })}>
|
||||
<ActionButton onClick={handleClear}>
|
||||
<RiDeleteBinLine className='h-4 w-4' />
|
||||
<RiDeleteBinLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
</div>
|
||||
@ -144,7 +145,7 @@ const Group = ({
|
||||
</div>
|
||||
{/* var item list */}
|
||||
{!isCollapsed && !nodeData?.isSingRunRunning && (
|
||||
<div className='px-0.5'>
|
||||
<div className="px-0.5">
|
||||
{visibleVarList.length > 0 && visibleVarList.map(varItem => (
|
||||
<div
|
||||
key={varItem.id}
|
||||
@ -157,10 +158,10 @@ const Group = ({
|
||||
<VariableIconWithColor
|
||||
variableCategory={varType}
|
||||
isExceptionVariable={['error_type', 'error_message'].includes(varItem.name)}
|
||||
className='size-4'
|
||||
className="size-4"
|
||||
/>
|
||||
<div className='system-sm-medium grow truncate text-text-secondary'>{varItem.name}</div>
|
||||
<div className='system-xs-regular shrink-0 text-text-tertiary'>{varItem.value_type}</div>
|
||||
<div className="system-sm-medium grow truncate text-text-secondary">{varItem.name}</div>
|
||||
<div className="system-xs-regular shrink-0 text-text-tertiary">{varItem.value_type}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import type { FC } from 'react'
|
||||
import { debounce } from 'es-toolkit/compat'
|
||||
import {
|
||||
useCallback,
|
||||
useMemo,
|
||||
} from 'react'
|
||||
import { debounce } from 'lodash-es'
|
||||
import { useStore } from '../store'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { useResizePanel } from '../nodes/_base/hooks/use-resize-panel'
|
||||
import { useStore } from '../store'
|
||||
import Panel from './panel'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
const VariableInspectPanel: FC = () => {
|
||||
const showVariableInspectPanel = useStore(s => s.showVariableInspectPanel)
|
||||
@ -44,8 +44,9 @@ const VariableInspectPanel: FC = () => {
|
||||
<div className={cn('relative pb-1')}>
|
||||
<div
|
||||
ref={triggerRef}
|
||||
className='absolute -top-1 left-0 flex h-1 w-full cursor-row-resize resize-y items-center justify-center'>
|
||||
<div className='h-0.5 w-10 rounded-sm bg-state-base-handle hover:w-full hover:bg-state-accent-solid active:w-full active:bg-state-accent-solid'></div>
|
||||
className="absolute -top-1 left-0 flex h-1 w-full cursor-row-resize resize-y items-center justify-center"
|
||||
>
|
||||
<div className="h-0.5 w-10 rounded-sm bg-state-base-handle hover:w-full hover:bg-state-accent-solid active:w-full active:bg-state-accent-solid"></div>
|
||||
</div>
|
||||
<div
|
||||
ref={containerRef}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
'use client'
|
||||
import { RiInformation2Fill } from '@remixicon/react'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import cn from '@/utils/classnames'
|
||||
import { RiInformation2Fill } from '@remixicon/react'
|
||||
import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { cn } from '@/utils/classnames'
|
||||
|
||||
type Props = {
|
||||
textHasNoExport?: boolean
|
||||
@ -17,15 +17,15 @@ const LargeDataAlert: FC<Props> = ({
|
||||
className,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const text = textHasNoExport ? t('workflow.debug.variableInspect.largeDataNoExport') : t('workflow.debug.variableInspect.largeData')
|
||||
const text = textHasNoExport ? t('debug.variableInspect.largeDataNoExport', { ns: 'workflow' }) : t('debug.variableInspect.largeData', { ns: 'workflow' })
|
||||
return (
|
||||
<div className={cn('flex h-8 items-center justify-between rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur px-2 shadow-xs', className)}>
|
||||
<div className='flex h-full w-0 grow items-center space-x-1'>
|
||||
<RiInformation2Fill className='size-4 shrink-0 text-text-accent' />
|
||||
<div className='system-xs-regular w-0 grow truncate text-text-primary'>{text}</div>
|
||||
<div className="flex h-full w-0 grow items-center space-x-1">
|
||||
<RiInformation2Fill className="size-4 shrink-0 text-text-accent" />
|
||||
<div className="system-xs-regular w-0 grow truncate text-text-primary">{text}</div>
|
||||
</div>
|
||||
{downloadUrl && (
|
||||
<div className='system-xs-medium-uppercase ml-1 shrink-0 cursor-pointer text-text-accent'>{t('workflow.debug.variableInspect.export')}</div>
|
||||
<div className="system-xs-medium-uppercase ml-1 shrink-0 cursor-pointer text-text-accent">{t('debug.variableInspect.export', { ns: 'workflow' })}</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
import type { currentVarType } from './panel'
|
||||
|
||||
import type { VarInInspect } from '@/types/workflow'
|
||||
// import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { useStore } from '../store'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { VarInInspectType } from '@/types/workflow'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import useCurrentVars from '../hooks/use-inspect-vars-crud'
|
||||
import { useNodesInteractions } from '../hooks/use-nodes-interactions'
|
||||
import { useStore } from '../store'
|
||||
// import ActionButton from '@/app/components/base/action-button'
|
||||
// import Tooltip from '@/app/components/base/tooltip'
|
||||
import Group from './group'
|
||||
import useCurrentVars from '../hooks/use-inspect-vars-crud'
|
||||
import { useNodesInteractions } from '../hooks/use-nodes-interactions'
|
||||
import type { currentVarType } from './panel'
|
||||
import type { VarInInspect } from '@/types/workflow'
|
||||
import { VarInInspectType } from '@/types/workflow'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type Props = {
|
||||
currentNodeVar?: currentVarType
|
||||
@ -51,12 +51,12 @@ const Left = ({
|
||||
return (
|
||||
<div className={cn('flex h-full flex-col')}>
|
||||
{/* header */}
|
||||
<div className='flex shrink-0 items-center justify-between gap-1 pl-4 pr-1 pt-2'>
|
||||
<div className='system-sm-semibold-uppercase truncate text-text-primary'>{t('workflow.debug.variableInspect.title')}</div>
|
||||
<Button variant='ghost' size='small' className='shrink-0' onClick={handleClearAll}>{t('workflow.debug.variableInspect.clearAll')}</Button>
|
||||
<div className="flex shrink-0 items-center justify-between gap-1 pl-4 pr-1 pt-2">
|
||||
<div className="system-sm-semibold-uppercase truncate text-text-primary">{t('debug.variableInspect.title', { ns: 'workflow' })}</div>
|
||||
<Button variant="ghost" size="small" className="shrink-0" onClick={handleClearAll}>{t('debug.variableInspect.clearAll', { ns: 'workflow' })}</Button>
|
||||
</div>
|
||||
{/* content */}
|
||||
<div className='grow overflow-y-auto py-1'>
|
||||
<div className="grow overflow-y-auto py-1">
|
||||
{/* group ENV */}
|
||||
{environmentVariables.length > 0 && (
|
||||
<Group
|
||||
@ -86,8 +86,8 @@ const Left = ({
|
||||
)}
|
||||
{/* divider */}
|
||||
{showDivider && (
|
||||
<div className='px-4 py-1'>
|
||||
<div className='h-px bg-divider-subtle'></div>
|
||||
<div className="px-4 py-1">
|
||||
<div className="h-px bg-divider-subtle"></div>
|
||||
</div>
|
||||
)}
|
||||
{/* group nodes */}
|
||||
|
||||
@ -1,18 +1,20 @@
|
||||
import { type FC, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { type Node, useStoreApi } from 'reactflow'
|
||||
import Button from '@/app/components/base/button'
|
||||
import BlockIcon from '@/app/components/workflow/block-icon'
|
||||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
import { StopCircle } from '@/app/components/base/icons/src/vender/line/mediaAndDevices'
|
||||
import { useStore } from '../store'
|
||||
import { useGetToolIcon } from '@/app/components/workflow/hooks/use-tool-icon'
|
||||
import type { TFunction } from 'i18next'
|
||||
import { getNextExecutionTime } from '@/app/components/workflow/nodes/trigger-schedule/utils/execution-time-calculator'
|
||||
import type { FC } from 'react'
|
||||
import type { Node } from 'reactflow'
|
||||
import type { ScheduleTriggerNodeType } from '@/app/components/workflow/nodes/trigger-schedule/types'
|
||||
import type { WebhookTriggerNodeType } from '@/app/components/workflow/nodes/trigger-webhook/types'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import copy from 'copy-to-clipboard'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useStoreApi } from 'reactflow'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { StopCircle } from '@/app/components/base/icons/src/vender/line/mediaAndDevices'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import BlockIcon from '@/app/components/workflow/block-icon'
|
||||
import { useGetToolIcon } from '@/app/components/workflow/hooks/use-tool-icon'
|
||||
import { getNextExecutionTime } from '@/app/components/workflow/nodes/trigger-schedule/utils/execution-time-calculator'
|
||||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
import { useStore } from '../store'
|
||||
|
||||
const resolveListeningDescription = (
|
||||
message: string | undefined,
|
||||
@ -26,28 +28,29 @@ const resolveListeningDescription = (
|
||||
if (triggerType === BlockEnum.TriggerSchedule) {
|
||||
const scheduleData = triggerNode?.data as ScheduleTriggerNodeType | undefined
|
||||
const nextTriggerTime = scheduleData ? getNextExecutionTime(scheduleData) : ''
|
||||
return t('workflow.debug.variableInspect.listening.tipSchedule', {
|
||||
nextTriggerTime: nextTriggerTime || t('workflow.debug.variableInspect.listening.defaultScheduleTime'),
|
||||
return t('debug.variableInspect.listening.tipSchedule', {
|
||||
ns: 'workflow',
|
||||
nextTriggerTime: nextTriggerTime || t('debug.variableInspect.listening.defaultScheduleTime', { ns: 'workflow' }),
|
||||
})
|
||||
}
|
||||
|
||||
if (triggerType === BlockEnum.TriggerPlugin) {
|
||||
const pluginName = (triggerNode?.data as { provider_name?: string; title?: string })?.provider_name
|
||||
const pluginName = (triggerNode?.data as { provider_name?: string, title?: string })?.provider_name
|
||||
|| (triggerNode?.data as { title?: string })?.title
|
||||
|| t('workflow.debug.variableInspect.listening.defaultPluginName')
|
||||
return t('workflow.debug.variableInspect.listening.tipPlugin', { pluginName })
|
||||
|| t('debug.variableInspect.listening.defaultPluginName', { ns: 'workflow' })
|
||||
return t('debug.variableInspect.listening.tipPlugin', { ns: 'workflow', pluginName })
|
||||
}
|
||||
|
||||
if (triggerType === BlockEnum.TriggerWebhook) {
|
||||
const nodeName = (triggerNode?.data as { title?: string })?.title || t('workflow.debug.variableInspect.listening.defaultNodeName')
|
||||
return t('workflow.debug.variableInspect.listening.tip', { nodeName })
|
||||
const nodeName = (triggerNode?.data as { title?: string })?.title || t('debug.variableInspect.listening.defaultNodeName', { ns: 'workflow' })
|
||||
return t('debug.variableInspect.listening.tip', { ns: 'workflow', nodeName })
|
||||
}
|
||||
|
||||
const nodeDescription = (triggerNode?.data as { desc?: string })?.desc
|
||||
if (nodeDescription)
|
||||
return nodeDescription
|
||||
|
||||
return t('workflow.debug.variableInspect.listening.tipFallback')
|
||||
return t('debug.variableInspect.listening.tipFallback', { ns: 'workflow' })
|
||||
}
|
||||
|
||||
const resolveMultipleListeningDescription = (
|
||||
@ -55,16 +58,16 @@ const resolveMultipleListeningDescription = (
|
||||
t: TFunction,
|
||||
): string => {
|
||||
if (!nodes.length)
|
||||
return t('workflow.debug.variableInspect.listening.tipFallback')
|
||||
return t('debug.variableInspect.listening.tipFallback', { ns: 'workflow' })
|
||||
|
||||
const titles = nodes
|
||||
.map(node => (node.data as { title?: string })?.title)
|
||||
.filter((title): title is string => Boolean(title))
|
||||
|
||||
if (titles.length)
|
||||
return t('workflow.debug.variableInspect.listening.tip', { nodeName: titles.join(', ') })
|
||||
return t('debug.variableInspect.listening.tip', { ns: 'workflow', nodeName: titles.join(', ') })
|
||||
|
||||
return t('workflow.debug.variableInspect.listening.tipFallback')
|
||||
return t('debug.variableInspect.listening.tipFallback', { ns: 'workflow' })
|
||||
}
|
||||
|
||||
export type ListeningProps = {
|
||||
@ -155,8 +158,8 @@ const Listening: FC<ListeningProps> = ({
|
||||
: resolveListeningDescription(message, triggerNode, triggerType, t)
|
||||
|
||||
return (
|
||||
<div className='flex h-full flex-col gap-4 rounded-xl bg-background-section p-8'>
|
||||
<div className='flex flex-row flex-wrap items-center gap-3'>
|
||||
<div className="flex h-full flex-col gap-4 rounded-xl bg-background-section p-8">
|
||||
<div className="flex flex-row flex-wrap items-center gap-3">
|
||||
{iconsToRender.map(icon => (
|
||||
<BlockIcon
|
||||
key={icon.key}
|
||||
@ -167,34 +170,34 @@ const Listening: FC<ListeningProps> = ({
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className='flex flex-col gap-1'>
|
||||
<div className='system-sm-semibold text-text-secondary'>{t('workflow.debug.variableInspect.listening.title')}</div>
|
||||
<div className='system-xs-regular whitespace-pre-line text-text-tertiary'>{description}</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="system-sm-semibold text-text-secondary">{t('debug.variableInspect.listening.title', { ns: 'workflow' })}</div>
|
||||
<div className="system-xs-regular whitespace-pre-line text-text-tertiary">{description}</div>
|
||||
</div>
|
||||
{webhookDebugUrl && (
|
||||
<div className='flex items-center gap-2'>
|
||||
<div className='system-xs-regular shrink-0 whitespace-pre-line text-text-tertiary'>
|
||||
{t('workflow.nodes.triggerWebhook.debugUrlTitle')}
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="system-xs-regular shrink-0 whitespace-pre-line text-text-tertiary">
|
||||
{t('nodes.triggerWebhook.debugUrlTitle', { ns: 'workflow' })}
|
||||
</div>
|
||||
<Tooltip
|
||||
popupContent={debugUrlCopied
|
||||
? t('workflow.nodes.triggerWebhook.debugUrlCopied')
|
||||
: t('workflow.nodes.triggerWebhook.debugUrlCopy')}
|
||||
? t('nodes.triggerWebhook.debugUrlCopied', { ns: 'workflow' })
|
||||
: t('nodes.triggerWebhook.debugUrlCopy', { ns: 'workflow' })}
|
||||
popupClassName="system-xs-regular text-text-primary bg-components-tooltip-bg border border-components-panel-border shadow-lg backdrop-blur-sm rounded-md px-1.5 py-1"
|
||||
position="top"
|
||||
offset={{ mainAxis: -4 }}
|
||||
needsDelay={true}
|
||||
>
|
||||
<button
|
||||
type='button'
|
||||
aria-label={t('workflow.nodes.triggerWebhook.debugUrlCopy') || ''}
|
||||
type="button"
|
||||
aria-label={t('nodes.triggerWebhook.debugUrlCopy', { ns: 'workflow' }) || ''}
|
||||
className={`inline-flex items-center rounded-[6px] border border-divider-regular bg-components-badge-white-to-dark px-1.5 py-[2px] font-mono text-[13px] leading-[18px] text-text-secondary transition-colors hover:bg-components-panel-on-panel-item-bg-hover focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-components-panel-border ${debugUrlCopied ? 'bg-components-panel-on-panel-item-bg-hover text-text-primary' : ''}`}
|
||||
onClick={() => {
|
||||
copy(webhookDebugUrl)
|
||||
setDebugUrlCopied(true)
|
||||
}}
|
||||
>
|
||||
<span className='whitespace-nowrap text-text-primary'>
|
||||
<span className="whitespace-nowrap text-text-primary">
|
||||
{webhookDebugUrl}
|
||||
</span>
|
||||
</button>
|
||||
@ -203,13 +206,13 @@ const Listening: FC<ListeningProps> = ({
|
||||
)}
|
||||
<div>
|
||||
<Button
|
||||
size='medium'
|
||||
className='px-3'
|
||||
variant='primary'
|
||||
size="medium"
|
||||
className="px-3"
|
||||
variant="primary"
|
||||
onClick={onStop}
|
||||
>
|
||||
<StopCircle className='mr-1 size-4' />
|
||||
{t('workflow.debug.variableInspect.listening.stopButton')}
|
||||
<StopCircle className="mr-1 size-4" />
|
||||
{t('debug.variableInspect.listening.stopButton', { ns: 'workflow' })}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,24 +1,24 @@
|
||||
import type { FC } from 'react'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { NodeProps } from '../types'
|
||||
import type { VarInInspect } from '@/types/workflow'
|
||||
import {
|
||||
RiCloseLine,
|
||||
} from '@remixicon/react'
|
||||
import { useStore } from '../store'
|
||||
import useCurrentVars from '../hooks/use-inspect-vars-crud'
|
||||
import Empty from './empty'
|
||||
import Listening from './listening'
|
||||
import Left from './left'
|
||||
import Right from './right'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import type { VarInInspect } from '@/types/workflow'
|
||||
import { VarInInspectType } from '@/types/workflow'
|
||||
|
||||
import cn from '@/utils/classnames'
|
||||
import type { NodeProps } from '../types'
|
||||
import useMatchSchemaType from '../nodes/_base/components/variable/use-match-schema-type'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import { EVENT_WORKFLOW_STOP } from '@/app/components/workflow/variable-inspect/types'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import { VarInInspectType } from '@/types/workflow'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import useCurrentVars from '../hooks/use-inspect-vars-crud'
|
||||
import useMatchSchemaType from '../nodes/_base/components/variable/use-match-schema-type'
|
||||
|
||||
import { useStore } from '../store'
|
||||
import Empty from './empty'
|
||||
import Left from './left'
|
||||
import Listening from './listening'
|
||||
import Right from './right'
|
||||
|
||||
export type currentVarType = {
|
||||
nodeId: string
|
||||
@ -55,7 +55,8 @@ const Panel: FC = () => {
|
||||
}, [environmentVariables, conversationVars, systemVars, nodesWithInspectVars])
|
||||
|
||||
const currentNodeInfo = useMemo(() => {
|
||||
if (!currentFocusNodeId) return
|
||||
if (!currentFocusNodeId)
|
||||
return
|
||||
if (currentFocusNodeId === VarInInspectType.environment) {
|
||||
const currentVar = environmentVariables.find(v => v.id === currentVarId)
|
||||
const res = {
|
||||
@ -113,7 +114,8 @@ const Panel: FC = () => {
|
||||
return res
|
||||
}
|
||||
const targetNode = nodesWithInspectVars.find(node => node.nodeId === currentFocusNodeId)
|
||||
if (!targetNode) return
|
||||
if (!targetNode)
|
||||
return
|
||||
const currentVar = targetNode.vars.find(v => v.id === currentVarId)
|
||||
return {
|
||||
nodeId: targetNode.nodeId,
|
||||
@ -127,9 +129,11 @@ const Panel: FC = () => {
|
||||
}, [currentFocusNodeId, currentVarId, environmentVariables, conversationVars, systemVars, nodesWithInspectVars])
|
||||
|
||||
const isCurrentNodeVarValueFetching = useMemo(() => {
|
||||
if (!currentNodeInfo) return false
|
||||
if (!currentNodeInfo)
|
||||
return false
|
||||
const targetNode = nodesWithInspectVars.find(node => node.nodeId === currentNodeInfo.nodeId)
|
||||
if (!targetNode) return false
|
||||
if (!targetNode)
|
||||
return false
|
||||
return !targetNode.isValueFetched
|
||||
}, [currentNodeInfo, nodesWithInspectVars])
|
||||
|
||||
@ -156,13 +160,13 @@ const Panel: FC = () => {
|
||||
if (isListening) {
|
||||
return (
|
||||
<div className={cn('flex h-full flex-col')}>
|
||||
<div className='flex shrink-0 items-center justify-between pl-4 pr-2 pt-2'>
|
||||
<div className='system-sm-semibold-uppercase text-text-primary'>{t('workflow.debug.variableInspect.title')}</div>
|
||||
<div className="flex shrink-0 items-center justify-between pl-4 pr-2 pt-2">
|
||||
<div className="system-sm-semibold-uppercase text-text-primary">{t('debug.variableInspect.title', { ns: 'workflow' })}</div>
|
||||
<ActionButton onClick={() => setShowVariableInspectPanel(false)}>
|
||||
<RiCloseLine className='h-4 w-4' />
|
||||
<RiCloseLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
</div>
|
||||
<div className='grow p-2'>
|
||||
<div className="grow p-2">
|
||||
<Listening
|
||||
onStop={handleStopListening}
|
||||
/>
|
||||
@ -174,13 +178,13 @@ const Panel: FC = () => {
|
||||
if (isEmpty) {
|
||||
return (
|
||||
<div className={cn('flex h-full flex-col')}>
|
||||
<div className='flex shrink-0 items-center justify-between pl-4 pr-2 pt-2'>
|
||||
<div className='system-sm-semibold-uppercase text-text-primary'>{t('workflow.debug.variableInspect.title')}</div>
|
||||
<div className="flex shrink-0 items-center justify-between pl-4 pr-2 pt-2">
|
||||
<div className="system-sm-semibold-uppercase text-text-primary">{t('debug.variableInspect.title', { ns: 'workflow' })}</div>
|
||||
<ActionButton onClick={() => setShowVariableInspectPanel(false)}>
|
||||
<RiCloseLine className='h-4 w-4' />
|
||||
<RiCloseLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
</div>
|
||||
<div className='grow p-2'>
|
||||
<div className="grow p-2">
|
||||
<Empty />
|
||||
</div>
|
||||
</div>
|
||||
@ -190,7 +194,7 @@ const Panel: FC = () => {
|
||||
return (
|
||||
<div className={cn('relative flex h-full')}>
|
||||
{/* left */}
|
||||
{bottomPanelWidth < 488 && showLeftPanel && <div className='absolute left-0 top-0 h-full w-full' onClick={() => setShowLeftPanel(false)}></div>}
|
||||
{bottomPanelWidth < 488 && showLeftPanel && <div className="absolute left-0 top-0 h-full w-full" onClick={() => setShowLeftPanel(false)}></div>}
|
||||
<div
|
||||
className={cn(
|
||||
'w-60 shrink-0 border-r border-divider-burn',
|
||||
@ -207,7 +211,7 @@ const Panel: FC = () => {
|
||||
/>
|
||||
</div>
|
||||
{/* right */}
|
||||
<div className='w-0 grow'>
|
||||
<div className="w-0 grow">
|
||||
<Right
|
||||
nodeId={currentFocusNodeId!}
|
||||
isValueFetching={isCurrentNodeVarValueFetching}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { currentVarType } from './panel'
|
||||
import type { GenRes } from '@/service/debug'
|
||||
import {
|
||||
RiArrowGoBackLine,
|
||||
RiCloseLine,
|
||||
@ -6,35 +7,34 @@ import {
|
||||
RiMenuLine,
|
||||
RiSparklingFill,
|
||||
} from '@remixicon/react'
|
||||
import { useStore } from '../store'
|
||||
import { BlockEnum } from '../types'
|
||||
import useCurrentVars from '../hooks/use-inspect-vars-crud'
|
||||
import Empty from './empty'
|
||||
import ValueContent from './value-content'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import { produce } from 'immer'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import GetAutomaticResModal from '@/app/components/app/configuration/config/automatic/get-automatic-res'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
import CopyFeedback from '@/app/components/base/copy-feedback'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import BlockIcon from '@/app/components/workflow/block-icon'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import type { currentVarType } from './panel'
|
||||
import { VarInInspectType } from '@/types/workflow'
|
||||
import cn from '@/utils/classnames'
|
||||
import useNodeInfo from '../nodes/_base/hooks/use-node-info'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import GetAutomaticResModal from '@/app/components/app/configuration/config/automatic/get-automatic-res'
|
||||
import GetCodeGeneratorResModal from '../../app/configuration/config/code-generator/get-code-generator-res'
|
||||
import { AppModeEnum } from '@/types/app'
|
||||
import { useHooksStore } from '../hooks-store'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useNodesInteractions, useToolIcon } from '../hooks'
|
||||
import { CodeLanguage } from '../nodes/code/types'
|
||||
import useNodeCrud from '../nodes/_base/hooks/use-node-crud'
|
||||
import type { GenRes } from '@/service/debug'
|
||||
import { produce } from 'immer'
|
||||
import { PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER } from '../../base/prompt-editor/plugins/update-block'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import { VariableIconWithColor } from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import { AppModeEnum } from '@/types/app'
|
||||
import { VarInInspectType } from '@/types/workflow'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import GetCodeGeneratorResModal from '../../app/configuration/config/code-generator/get-code-generator-res'
|
||||
import { PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER } from '../../base/prompt-editor/plugins/update-block'
|
||||
import { useNodesInteractions, useToolIcon } from '../hooks'
|
||||
import { useHooksStore } from '../hooks-store'
|
||||
import useCurrentVars from '../hooks/use-inspect-vars-crud'
|
||||
import useNodeCrud from '../nodes/_base/hooks/use-node-crud'
|
||||
import useNodeInfo from '../nodes/_base/hooks/use-node-info'
|
||||
import { CodeLanguage } from '../nodes/code/types'
|
||||
import { useStore } from '../store'
|
||||
import { BlockEnum } from '../types'
|
||||
import Empty from './empty'
|
||||
import ValueContent from './value-content'
|
||||
|
||||
type Props = {
|
||||
nodeId: string
|
||||
@ -64,12 +64,14 @@ const Right = ({
|
||||
} = useCurrentVars()
|
||||
|
||||
const handleValueChange = (varId: string, value: any) => {
|
||||
if (!currentNodeVar) return
|
||||
if (!currentNodeVar)
|
||||
return
|
||||
editInspectVarValue(currentNodeVar.nodeId, varId, value)
|
||||
}
|
||||
|
||||
const resetValue = () => {
|
||||
if (!currentNodeVar) return
|
||||
if (!currentNodeVar)
|
||||
return
|
||||
resetToLastRunVar(currentNodeVar.nodeId, currentNodeVar.var.id)
|
||||
}
|
||||
|
||||
@ -79,7 +81,8 @@ const Right = ({
|
||||
}
|
||||
|
||||
const handleClear = () => {
|
||||
if (!currentNodeVar) return
|
||||
if (!currentNodeVar)
|
||||
return
|
||||
resetConversationVar(currentNodeVar.var.id)
|
||||
}
|
||||
|
||||
@ -161,20 +164,20 @@ const Right = ({
|
||||
return (
|
||||
<div className={cn('flex h-full flex-col')}>
|
||||
{/* header */}
|
||||
<div className='flex shrink-0 items-center justify-between gap-1 px-2 pt-2'>
|
||||
<div className="flex shrink-0 items-center justify-between gap-1 px-2 pt-2">
|
||||
{bottomPanelWidth < 488 && (
|
||||
<ActionButton className='shrink-0' onClick={handleOpenMenu}>
|
||||
<RiMenuLine className='h-4 w-4' />
|
||||
<ActionButton className="shrink-0" onClick={handleOpenMenu}>
|
||||
<RiMenuLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
)}
|
||||
<div className='flex w-0 grow items-center gap-1'>
|
||||
<div className="flex w-0 grow items-center gap-1">
|
||||
{currentNodeVar?.var && (
|
||||
<>
|
||||
{
|
||||
[VarInInspectType.environment, VarInInspectType.conversation, VarInInspectType.system].includes(currentNodeVar.nodeType as VarInInspectType) && (
|
||||
<VariableIconWithColor
|
||||
variableCategory={currentNodeVar.nodeType as VarInInspectType}
|
||||
className='size-4'
|
||||
className="size-4"
|
||||
/>
|
||||
)
|
||||
}
|
||||
@ -184,22 +187,25 @@ const Right = ({
|
||||
&& (
|
||||
<>
|
||||
<BlockIcon
|
||||
className='shrink-0'
|
||||
className="shrink-0"
|
||||
type={currentNodeVar.nodeType as BlockEnum}
|
||||
size='xs'
|
||||
size="xs"
|
||||
toolIcon={toolIcon}
|
||||
/>
|
||||
<div className='system-sm-regular shrink-0 text-text-secondary'>{currentNodeVar.title}</div>
|
||||
<div className='system-sm-regular shrink-0 text-text-quaternary'>/</div>
|
||||
<div className="system-sm-regular shrink-0 text-text-secondary">{currentNodeVar.title}</div>
|
||||
<div className="system-sm-regular shrink-0 text-text-quaternary">/</div>
|
||||
</>
|
||||
)}
|
||||
<div title={currentNodeVar.var.name} className='system-sm-semibold truncate text-text-secondary'>{currentNodeVar.var.name}</div>
|
||||
<div className='system-xs-medium ml-1 shrink-0 space-x-2 text-text-tertiary'>
|
||||
<div title={currentNodeVar.var.name} className="system-sm-semibold truncate text-text-secondary">{currentNodeVar.var.name}</div>
|
||||
<div className="system-xs-medium ml-1 shrink-0 space-x-2 text-text-tertiary">
|
||||
<span>{`${currentNodeVar.var.value_type}${displaySchemaType}`}</span>
|
||||
{isTruncated && (
|
||||
<>
|
||||
<span>·</span>
|
||||
<span>{((fullContent?.size_bytes || 0) / 1024 / 1024).toFixed(1)}MB</span>
|
||||
<span>
|
||||
{((fullContent?.size_bytes || 0) / 1024 / 1024).toFixed(1)}
|
||||
MB
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
@ -207,48 +213,48 @@ const Right = ({
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className='flex shrink-0 items-center gap-1'>
|
||||
<div className="flex shrink-0 items-center gap-1">
|
||||
{currentNodeVar && (
|
||||
<>
|
||||
{canShowPromptGenerator && (
|
||||
<Tooltip popupContent={t('appDebug.generate.optimizePromptTooltip')}>
|
||||
<Tooltip popupContent={t('generate.optimizePromptTooltip', { ns: 'appDebug' })}>
|
||||
<div
|
||||
className='cursor-pointer rounded-md p-1 hover:bg-state-accent-active'
|
||||
className="cursor-pointer rounded-md p-1 hover:bg-state-accent-active"
|
||||
onClick={handleShowPromptGenerator}
|
||||
>
|
||||
<RiSparklingFill className='size-4 text-components-input-border-active-prompt-1' />
|
||||
<RiSparklingFill className="size-4 text-components-input-border-active-prompt-1" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
{isTruncated && (
|
||||
<Tooltip popupContent={t('workflow.debug.variableInspect.exportToolTip')}>
|
||||
<Tooltip popupContent={t('debug.variableInspect.exportToolTip', { ns: 'workflow' })}>
|
||||
<ActionButton>
|
||||
<a
|
||||
href={fullContent?.download_url}
|
||||
target='_blank'
|
||||
target="_blank"
|
||||
>
|
||||
<RiFileDownloadFill className='size-4' />
|
||||
<RiFileDownloadFill className="size-4" />
|
||||
</a>
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
{!isTruncated && currentNodeVar.var.edited && (
|
||||
<Badge>
|
||||
<span className='ml-[2.5px] mr-[4.5px] h-[3px] w-[3px] rounded bg-text-accent-secondary'></span>
|
||||
<span className='system-2xs-semibold-uupercase'>{t('workflow.debug.variableInspect.edited')}</span>
|
||||
<span className="ml-[2.5px] mr-[4.5px] h-[3px] w-[3px] rounded bg-text-accent-secondary"></span>
|
||||
<span className="system-2xs-semibold-uupercase">{t('debug.variableInspect.edited', { ns: 'workflow' })}</span>
|
||||
</Badge>
|
||||
)}
|
||||
{!isTruncated && currentNodeVar.var.edited && currentNodeVar.var.type !== VarInInspectType.conversation && (
|
||||
<Tooltip popupContent={t('workflow.debug.variableInspect.reset')}>
|
||||
<Tooltip popupContent={t('debug.variableInspect.reset', { ns: 'workflow' })}>
|
||||
<ActionButton onClick={resetValue}>
|
||||
<RiArrowGoBackLine className='h-4 w-4' />
|
||||
<RiArrowGoBackLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
{!isTruncated && currentNodeVar.var.edited && currentNodeVar.var.type === VarInInspectType.conversation && (
|
||||
<Tooltip popupContent={t('workflow.debug.variableInspect.resetConversationVar')}>
|
||||
<Tooltip popupContent={t('debug.variableInspect.resetConversationVar', { ns: 'workflow' })}>
|
||||
<ActionButton onClick={handleClear}>
|
||||
<RiArrowGoBackLine className='h-4 w-4' />
|
||||
<RiArrowGoBackLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
@ -258,15 +264,15 @@ const Right = ({
|
||||
</>
|
||||
)}
|
||||
<ActionButton onClick={handleClose}>
|
||||
<RiCloseLine className='h-4 w-4' />
|
||||
<RiCloseLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
</div>
|
||||
</div>
|
||||
{/* content */}
|
||||
<div className='grow p-2'>
|
||||
<div className="grow p-2">
|
||||
{!currentNodeVar?.var && <Empty />}
|
||||
{isValueFetching && (
|
||||
<div className='flex h-full items-center justify-center'>
|
||||
<div className="flex h-full items-center justify-center">
|
||||
<Loading />
|
||||
</div>
|
||||
)}
|
||||
@ -281,25 +287,29 @@ const Right = ({
|
||||
</div>
|
||||
{isShowPromptGenerator && (
|
||||
isCodeBlock
|
||||
? <GetCodeGeneratorResModal
|
||||
isShow
|
||||
mode={AppModeEnum.CHAT}
|
||||
onClose={handleHidePromptGenerator}
|
||||
flowId={configsMap?.flowId || ''}
|
||||
nodeId={nodeId}
|
||||
currentCode={currentPrompt}
|
||||
codeLanguages={node?.data?.code_languages || CodeLanguage.python3}
|
||||
onFinished={handleUpdatePrompt}
|
||||
/>
|
||||
: <GetAutomaticResModal
|
||||
mode={AppModeEnum.CHAT}
|
||||
isShow
|
||||
onClose={handleHidePromptGenerator}
|
||||
onFinished={handleUpdatePrompt}
|
||||
flowId={configsMap?.flowId || ''}
|
||||
nodeId={nodeId}
|
||||
currentPrompt={currentPrompt}
|
||||
/>
|
||||
? (
|
||||
<GetCodeGeneratorResModal
|
||||
isShow
|
||||
mode={AppModeEnum.CHAT}
|
||||
onClose={handleHidePromptGenerator}
|
||||
flowId={configsMap?.flowId || ''}
|
||||
nodeId={nodeId}
|
||||
currentCode={currentPrompt}
|
||||
codeLanguages={node?.data?.code_languages || CodeLanguage.python3}
|
||||
onFinished={handleUpdatePrompt}
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<GetAutomaticResModal
|
||||
mode={AppModeEnum.CHAT}
|
||||
isShow
|
||||
onClose={handleHidePromptGenerator}
|
||||
onFinished={handleUpdatePrompt}
|
||||
flowId={configsMap?.flowId || ''}
|
||||
nodeId={nodeId}
|
||||
currentPrompt={currentPrompt}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -1,18 +1,17 @@
|
||||
import type { FC } from 'react'
|
||||
import { useMemo } from 'react'
|
||||
import { useNodes } from 'reactflow'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiLoader2Line, RiStopCircleFill } from '@remixicon/react'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { useStore } from '../store'
|
||||
import useCurrentVars from '../hooks/use-inspect-vars-crud'
|
||||
import { WorkflowRunningStatus } from '@/app/components/workflow/types'
|
||||
import { NodeRunningStatus } from '@/app/components/workflow/types'
|
||||
import type { CommonNodeType } from '@/app/components/workflow/types'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import { RiLoader2Line, RiStopCircleFill } from '@remixicon/react'
|
||||
import { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNodes } from 'reactflow'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { NodeRunningStatus, WorkflowRunningStatus } from '@/app/components/workflow/types'
|
||||
import { EVENT_WORKFLOW_STOP } from '@/app/components/workflow/variable-inspect/types'
|
||||
import cn from '@/utils/classnames'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import useCurrentVars from '../hooks/use-inspect-vars-crud'
|
||||
import { useNodesReadOnly } from '../hooks/use-workflow'
|
||||
import { useStore } from '../store'
|
||||
|
||||
const VariableInspectTrigger: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
@ -65,64 +64,58 @@ const VariableInspectTrigger: FC = () => {
|
||||
<div className={cn('flex items-center gap-1')}>
|
||||
{!isRunning && !currentVars.length && (
|
||||
<div
|
||||
className={cn('system-2xs-semibold-uppercase flex h-5 cursor-pointer items-center gap-1 rounded-md border-[0.5px] border-effects-highlight bg-components-actionbar-bg px-2 text-text-tertiary shadow-lg backdrop-blur-sm hover:bg-background-default-hover',
|
||||
nodesReadOnly && 'cursor-not-allowed text-text-disabled hover:bg-transparent hover:text-text-disabled',
|
||||
)}
|
||||
className={cn('system-2xs-semibold-uppercase flex h-5 cursor-pointer items-center gap-1 rounded-md border-[0.5px] border-effects-highlight bg-components-actionbar-bg px-2 text-text-tertiary shadow-lg backdrop-blur-sm hover:bg-background-default-hover', nodesReadOnly && 'cursor-not-allowed text-text-disabled hover:bg-transparent hover:text-text-disabled')}
|
||||
onClick={() => {
|
||||
if (getNodesReadOnly())
|
||||
return
|
||||
setShowVariableInspectPanel(true)
|
||||
}}
|
||||
>
|
||||
{t('workflow.debug.variableInspect.trigger.normal')}
|
||||
{t('debug.variableInspect.trigger.normal', { ns: 'workflow' })}
|
||||
</div>
|
||||
)}
|
||||
{!isRunning && currentVars.length > 0 && (
|
||||
<>
|
||||
<div
|
||||
className={cn('system-xs-medium flex h-6 cursor-pointer items-center gap-1 rounded-md border-[0.5px] border-effects-highlight bg-components-actionbar-bg px-2 text-text-accent shadow-lg backdrop-blur-sm hover:bg-components-actionbar-bg-accent',
|
||||
nodesReadOnly && 'cursor-not-allowed text-text-disabled hover:bg-transparent hover:text-text-disabled',
|
||||
)}
|
||||
className={cn('system-xs-medium flex h-6 cursor-pointer items-center gap-1 rounded-md border-[0.5px] border-effects-highlight bg-components-actionbar-bg px-2 text-text-accent shadow-lg backdrop-blur-sm hover:bg-components-actionbar-bg-accent', nodesReadOnly && 'cursor-not-allowed text-text-disabled hover:bg-transparent hover:text-text-disabled')}
|
||||
onClick={() => {
|
||||
if (getNodesReadOnly())
|
||||
return
|
||||
setShowVariableInspectPanel(true)
|
||||
}}
|
||||
>
|
||||
{t('workflow.debug.variableInspect.trigger.cached')}
|
||||
{t('debug.variableInspect.trigger.cached', { ns: 'workflow' })}
|
||||
</div>
|
||||
<div
|
||||
className={cn('system-xs-medium flex h-6 cursor-pointer items-center rounded-md border-[0.5px] border-effects-highlight bg-components-actionbar-bg px-1 text-text-tertiary shadow-lg backdrop-blur-sm hover:bg-components-actionbar-bg-accent hover:text-text-accent',
|
||||
nodesReadOnly && 'cursor-not-allowed text-text-disabled hover:bg-transparent hover:text-text-disabled',
|
||||
)}
|
||||
className={cn('system-xs-medium flex h-6 cursor-pointer items-center rounded-md border-[0.5px] border-effects-highlight bg-components-actionbar-bg px-1 text-text-tertiary shadow-lg backdrop-blur-sm hover:bg-components-actionbar-bg-accent hover:text-text-accent', nodesReadOnly && 'cursor-not-allowed text-text-disabled hover:bg-transparent hover:text-text-disabled')}
|
||||
onClick={() => {
|
||||
if (getNodesReadOnly())
|
||||
return
|
||||
handleClearAll()
|
||||
}}
|
||||
>
|
||||
{t('workflow.debug.variableInspect.trigger.clear')}
|
||||
{t('debug.variableInspect.trigger.clear', { ns: 'workflow' })}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{isRunning && (
|
||||
<>
|
||||
<div
|
||||
className='system-xs-medium flex h-6 cursor-pointer items-center gap-1 rounded-md border-[0.5px] border-effects-highlight bg-components-actionbar-bg px-2 text-text-accent shadow-lg backdrop-blur-sm hover:bg-components-actionbar-bg-accent'
|
||||
className="system-xs-medium flex h-6 cursor-pointer items-center gap-1 rounded-md border-[0.5px] border-effects-highlight bg-components-actionbar-bg px-2 text-text-accent shadow-lg backdrop-blur-sm hover:bg-components-actionbar-bg-accent"
|
||||
onClick={() => setShowVariableInspectPanel(true)}
|
||||
>
|
||||
<RiLoader2Line className='h-4 w-4 animate-spin' />
|
||||
<span className='text-text-accent'>{t('workflow.debug.variableInspect.trigger.running')}</span>
|
||||
<RiLoader2Line className="h-4 w-4 animate-spin" />
|
||||
<span className="text-text-accent">{t('debug.variableInspect.trigger.running', { ns: 'workflow' })}</span>
|
||||
</div>
|
||||
{isPreviewRunning && (
|
||||
<Tooltip
|
||||
popupContent={t('workflow.debug.variableInspect.trigger.stop')}
|
||||
popupContent={t('debug.variableInspect.trigger.stop', { ns: 'workflow' })}
|
||||
>
|
||||
<div
|
||||
className='flex h-6 cursor-pointer items-center rounded-md border-[0.5px] border-effects-highlight bg-components-actionbar-bg px-1 shadow-lg backdrop-blur-sm hover:bg-components-actionbar-bg-accent'
|
||||
className="flex h-6 cursor-pointer items-center rounded-md border-[0.5px] border-effects-highlight bg-components-actionbar-bg px-1 shadow-lg backdrop-blur-sm hover:bg-components-actionbar-bg-accent"
|
||||
onClick={handleStop}
|
||||
>
|
||||
<RiStopCircleFill className='h-4 w-4 text-text-accent' />
|
||||
<RiStopCircleFill className="h-4 w-4 text-text-accent" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
@ -1,30 +1,31 @@
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import type { VarInInspect } from '@/types/workflow'
|
||||
import { useDebounceFn } from 'ahooks'
|
||||
import Textarea from '@/app/components/base/textarea'
|
||||
import SchemaEditor from '@/app/components/workflow/nodes/llm/components/json-schema-config-modal/schema-editor'
|
||||
import * as React from 'react'
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { FileUploaderInAttachmentWrapper } from '@/app/components/base/file-uploader'
|
||||
import { getProcessedFiles, getProcessedFilesFromResponse } from '@/app/components/base/file-uploader/utils'
|
||||
import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants'
|
||||
import Textarea from '@/app/components/base/textarea'
|
||||
import ErrorMessage from '@/app/components/workflow/nodes/llm/components/json-schema-config-modal/error-message'
|
||||
import SchemaEditor from '@/app/components/workflow/nodes/llm/components/json-schema-config-modal/schema-editor'
|
||||
import {
|
||||
checkJsonSchemaDepth,
|
||||
getValidationErrorMessage,
|
||||
validateSchemaAgainstDraft7,
|
||||
} from '@/app/components/workflow/nodes/llm/utils'
|
||||
import { useStore } from '@/app/components/workflow/store'
|
||||
import { SupportUploadFileTypes } from '@/app/components/workflow/types'
|
||||
import {
|
||||
validateJSONSchema,
|
||||
} from '@/app/components/workflow/variable-inspect/utils'
|
||||
import { getProcessedFiles, getProcessedFilesFromResponse } from '@/app/components/base/file-uploader/utils'
|
||||
import { JSON_SCHEMA_MAX_DEPTH } from '@/config'
|
||||
import { TransferMethod } from '@/types/app'
|
||||
import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants'
|
||||
import { SupportUploadFileTypes } from '@/app/components/workflow/types'
|
||||
import type { VarInInspect } from '@/types/workflow'
|
||||
import { VarInInspectType } from '@/types/workflow'
|
||||
import cn from '@/utils/classnames'
|
||||
import LargeDataAlert from './large-data-alert'
|
||||
import BoolValue from '../panel/chat-variable-panel/components/bool-value'
|
||||
import { useStore } from '@/app/components/workflow/store'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { PreviewMode } from '../../base/features/types'
|
||||
import BoolValue from '../panel/chat-variable-panel/components/bool-value'
|
||||
import DisplayContent from './display-content'
|
||||
import LargeDataAlert from './large-data-alert'
|
||||
import { CHUNK_SCHEMA_TYPES, PreviewType } from './types'
|
||||
|
||||
type Props = {
|
||||
@ -184,36 +185,38 @@ const ValueContent = ({
|
||||
return (
|
||||
<div
|
||||
ref={contentContainerRef}
|
||||
className='flex h-full flex-col'
|
||||
className="flex h-full flex-col"
|
||||
>
|
||||
<div className={cn('relative grow')} style={{ height: `${editorHeight}px` }}>
|
||||
{showTextEditor && (
|
||||
<>
|
||||
{isTruncated && <LargeDataAlert className='absolute left-3 right-3 top-1' />}
|
||||
{isTruncated && <LargeDataAlert className="absolute left-3 right-3 top-1" />}
|
||||
{
|
||||
currentVar.value_type === 'string' ? (
|
||||
<DisplayContent
|
||||
previewType={PreviewType.Markdown}
|
||||
varType={currentVar.value_type}
|
||||
mdString={value as any}
|
||||
readonly={textEditorDisabled}
|
||||
handleTextChange={handleTextChange}
|
||||
className={cn(isTruncated && 'pt-[36px]')}
|
||||
/>
|
||||
) : (
|
||||
<Textarea
|
||||
readOnly={textEditorDisabled}
|
||||
disabled={textEditorDisabled || isTruncated}
|
||||
className={cn('h-full', isTruncated && 'pt-[48px]')}
|
||||
value={value as any}
|
||||
onChange={e => handleTextChange(e.target.value)}
|
||||
/>
|
||||
)
|
||||
currentVar.value_type === 'string'
|
||||
? (
|
||||
<DisplayContent
|
||||
previewType={PreviewType.Markdown}
|
||||
varType={currentVar.value_type}
|
||||
mdString={value as any}
|
||||
readonly={textEditorDisabled}
|
||||
handleTextChange={handleTextChange}
|
||||
className={cn(isTruncated && 'pt-[36px]')}
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<Textarea
|
||||
readOnly={textEditorDisabled}
|
||||
disabled={textEditorDisabled || isTruncated}
|
||||
className={cn('h-full', isTruncated && 'pt-[48px]')}
|
||||
value={value as any}
|
||||
onChange={e => handleTextChange(e.target.value)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</>
|
||||
)}
|
||||
{showBoolEditor && (
|
||||
<div className='w-[295px]'>
|
||||
<div className="w-[295px]">
|
||||
<BoolValue
|
||||
value={currentVar.value as boolean}
|
||||
onChange={(newValue) => {
|
||||
@ -225,7 +228,7 @@ const ValueContent = ({
|
||||
)}
|
||||
{
|
||||
showBoolArrayEditor && (
|
||||
<div className='w-[295px] space-y-1'>
|
||||
<div className="w-[295px] space-y-1">
|
||||
{currentVar.value.map((v: boolean, i: number) => (
|
||||
<BoolValue
|
||||
key={i}
|
||||
@ -244,28 +247,28 @@ const ValueContent = ({
|
||||
{showJSONEditor && (
|
||||
hasChunks
|
||||
? (
|
||||
<DisplayContent
|
||||
previewType={PreviewType.Chunks}
|
||||
varType={currentVar.value_type}
|
||||
schemaType={currentVar.schemaType ?? ''}
|
||||
jsonString={json ?? '{}'}
|
||||
readonly={JSONEditorDisabled}
|
||||
handleEditorChange={handleEditorChange}
|
||||
/>
|
||||
)
|
||||
<DisplayContent
|
||||
previewType={PreviewType.Chunks}
|
||||
varType={currentVar.value_type}
|
||||
schemaType={currentVar.schemaType ?? ''}
|
||||
jsonString={json ?? '{}'}
|
||||
readonly={JSONEditorDisabled}
|
||||
handleEditorChange={handleEditorChange}
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<SchemaEditor
|
||||
readonly={JSONEditorDisabled || isTruncated}
|
||||
className='overflow-y-auto'
|
||||
hideTopMenu
|
||||
schema={json}
|
||||
onUpdate={handleEditorChange}
|
||||
isTruncated={isTruncated}
|
||||
/>
|
||||
)
|
||||
<SchemaEditor
|
||||
readonly={JSONEditorDisabled || isTruncated}
|
||||
className="overflow-y-auto"
|
||||
hideTopMenu
|
||||
schema={json}
|
||||
onUpdate={handleEditorChange}
|
||||
isTruncated={isTruncated}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
{showFileEditor && (
|
||||
<div className='max-w-[460px]'>
|
||||
<div className="max-w-[460px]">
|
||||
<FileUploaderInAttachmentWrapper
|
||||
value={fileValue}
|
||||
onChange={files => handleFileChange(getProcessedFiles(files))}
|
||||
@ -295,11 +298,11 @@ const ValueContent = ({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div ref={errorMessageRef} className='shrink-0'>
|
||||
{parseError && <ErrorMessage className='mt-1' message={parseError.message} />}
|
||||
{validationError && <ErrorMessage className='mt-1' message={validationError} />}
|
||||
<div ref={errorMessageRef} className="shrink-0">
|
||||
{parseError && <ErrorMessage className="mt-1" message={parseError.message} />}
|
||||
{validationError && <ErrorMessage className="mt-1" message={validationError} />}
|
||||
</div>
|
||||
</div >
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user