mirror of https://github.com/langgenius/dify.git
panel
This commit is contained in:
parent
344e30bef4
commit
8f3d9d0149
|
|
@ -66,6 +66,7 @@ const BlockIcon: FC<BlockIconProps> = ({
|
|||
flex items-center justify-center border-[0.5px] border-white/[0.02] text-white
|
||||
${ICON_CONTAINER_CLASSNAME_SIZE_MAP[size]}
|
||||
${ICON_CONTAINER_BG_COLOR_MAP[type]}
|
||||
${icon && '!shadow-none'}
|
||||
${className}
|
||||
`}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import {
|
|||
useCallback,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type {
|
||||
OffsetOptions,
|
||||
Placement,
|
||||
|
|
@ -47,6 +48,7 @@ const NodeSelector: FC<NodeSelectorProps> = ({
|
|||
popupClassName,
|
||||
asChild,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const [localOpen, setLocalOpen] = useState(false)
|
||||
const open = openFromProps === undefined ? localOpen : openFromProps
|
||||
const handleOpenChange = useCallback((newOpen: boolean) => {
|
||||
|
|
@ -95,11 +97,14 @@ const NodeSelector: FC<NodeSelectorProps> = ({
|
|||
<PortalToFollowElemContent className='z-[1000]'>
|
||||
<div className={`w-[256px] rounded-lg border-[0.5px] border-gray-200 bg-white shadow-lg ${popupClassName}`}>
|
||||
<div className='px-2 pt-2'>
|
||||
<div className='flex items-center px-2 rounded-lg bg-gray-100'>
|
||||
<div
|
||||
className='flex items-center px-2 rounded-lg bg-gray-100'
|
||||
onClick={e => e.stopPropagation()}
|
||||
>
|
||||
<SearchLg className='shrink-0 ml-[1px] mr-[5px] w-3.5 h-3.5 text-gray-400' />
|
||||
<input
|
||||
className='grow px-0.5 py-[7px] text-[13px] bg-transparent appearance-none outline-none'
|
||||
placeholder='Search block'
|
||||
placeholder={t('workflow.tabs.searchBlock') || ''}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@ import {
|
|||
memo,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { groupBy } from 'lodash-es'
|
||||
import BlockIcon from '../block-icon'
|
||||
import type { BlockEnum } from '../types'
|
||||
import { BlockEnum } from '../types'
|
||||
import { BLOCK_CLASSIFICATIONS } from './constants'
|
||||
import {
|
||||
useBlocks,
|
||||
|
|
@ -14,6 +15,7 @@ import {
|
|||
import type { ToolDefaultValue } from './types'
|
||||
import { TabsEnum } from './types'
|
||||
import Tools from './tools'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
|
||||
export type TabsProps = {
|
||||
onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void
|
||||
|
|
@ -21,6 +23,8 @@ export type TabsProps = {
|
|||
const Tabs: FC<TabsProps> = ({
|
||||
onSelect,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const appDetail = useAppStore(state => state.appDetail)
|
||||
const blocks = useBlocks()
|
||||
const tabs = useTabs()
|
||||
const [activeTab, setActiveTab] = useState(tabs[0].key)
|
||||
|
|
@ -55,12 +59,17 @@ const Tabs: FC<TabsProps> = ({
|
|||
{
|
||||
classification !== '-' && (
|
||||
<div className='flex items-start px-3 h-[22px] text-xs font-medium text-gray-500'>
|
||||
{classification}
|
||||
{t(`workflow.tabs.${classification}`)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
groupBy(blocks, 'classification')[classification].map(block => (
|
||||
groupBy(blocks, 'classification')[classification].filter((block) => {
|
||||
if (block.type === BlockEnum.DirectAnswer && appDetail?.mode === 'workflow')
|
||||
return false
|
||||
|
||||
return true
|
||||
}).map(block => (
|
||||
<div
|
||||
key={block.type}
|
||||
className='flex items-center px-3 h-8 rounded-lg hover:bg-gray-50 cursor-pointer'
|
||||
|
|
|
|||
|
|
@ -85,9 +85,9 @@ const Item = ({
|
|||
}
|
||||
<div
|
||||
className='grow mr-2 truncate text-sm text-gray-900'
|
||||
title={data.name}
|
||||
title={data.label[language]}
|
||||
>
|
||||
{data.name}
|
||||
{data.label[language]}
|
||||
</div>
|
||||
{
|
||||
data.expanded
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import {
|
|||
memo,
|
||||
useCallback,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useWorkflow } from '@/app/components/workflow/hooks'
|
||||
import BlockSelector from '@/app/components/workflow/block-selector'
|
||||
import { Plus } from '@/app/components/base/icons/src/vender/line/general'
|
||||
|
|
@ -17,6 +18,7 @@ const Add = ({
|
|||
sourceHandle,
|
||||
branchName,
|
||||
}: AddProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { handleNodeAddNext } = useWorkflow()
|
||||
|
||||
const handleSelect = useCallback<OnSelectBlock>((type, toolDefaultValue) => {
|
||||
|
|
@ -42,10 +44,10 @@ const Add = ({
|
|||
<div className='flex items-center justify-center mr-1.5 w-5 h-5 rounded-[5px] bg-gray-200'>
|
||||
<Plus className='w-3 h-3' />
|
||||
</div>
|
||||
SELECT NEXT BLOCK
|
||||
{t('workflow.panel.selectNextStep')}
|
||||
</div>
|
||||
)
|
||||
}, [branchName])
|
||||
}, [branchName, t])
|
||||
|
||||
return (
|
||||
<BlockSelector
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import {
|
|||
memo,
|
||||
useCallback,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import BlockSelector from '@/app/components/workflow/block-selector'
|
||||
import { useWorkflow } from '@/app/components/workflow/hooks'
|
||||
import type { OnSelectBlock } from '@/app/components/workflow/types'
|
||||
|
|
@ -14,6 +15,7 @@ const ChangeBlock = ({
|
|||
nodeId,
|
||||
sourceHandle,
|
||||
}: ChangeBlockProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { handleNodeChange } = useWorkflow()
|
||||
|
||||
const handleSelect = useCallback<OnSelectBlock>((type, toolDefaultValue) => {
|
||||
|
|
@ -23,10 +25,10 @@ const ChangeBlock = ({
|
|||
const renderTrigger = useCallback(() => {
|
||||
return (
|
||||
<div className='flex items-center px-3 w-[232px] h-8 text-sm text-gray-700 rounded-lg cursor-pointer hover:bg-gray-50'>
|
||||
Change Block
|
||||
{t('workflow.panel.changeBlock')}
|
||||
</div>
|
||||
)
|
||||
}, [])
|
||||
}, [t])
|
||||
|
||||
return (
|
||||
<BlockSelector
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import {
|
|||
memo,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useEdges } from 'reactflow'
|
||||
import ChangeBlock from './change-block'
|
||||
import { useWorkflow } from '@/app/components/workflow/hooks'
|
||||
|
|
@ -21,6 +22,7 @@ const PanelOperator = ({
|
|||
id,
|
||||
data,
|
||||
}: PanelOperatorProps) => {
|
||||
const { t } = useTranslation()
|
||||
const edges = useEdges()
|
||||
const { handleNodeDelete } = useWorkflow()
|
||||
const [open, setOpen] = useState(false)
|
||||
|
|
@ -55,7 +57,9 @@ const PanelOperator = ({
|
|||
nodeId={id}
|
||||
sourceHandle={edge?.sourceHandle || 'source'}
|
||||
/>
|
||||
<div className='flex items-center px-3 h-8 text-sm text-gray-700 rounded-lg cursor-pointer hover:bg-gray-50'>Help Link</div>
|
||||
<div className='flex items-center px-3 h-8 text-sm text-gray-700 rounded-lg cursor-pointer hover:bg-gray-50'>
|
||||
{t('workflow.panel.helpLink')}
|
||||
</div>
|
||||
</div>
|
||||
<div className='h-[1px] bg-gray-100'></div>
|
||||
<div className='p-1'>
|
||||
|
|
@ -63,19 +67,19 @@ const PanelOperator = ({
|
|||
className='flex items-center px-3 h-8 text-sm text-gray-700 rounded-lg cursor-pointer hover:bg-gray-50'
|
||||
onClick={() => handleNodeDelete(id)}
|
||||
>
|
||||
Delete
|
||||
{t('common.operation.delete')}
|
||||
</div>
|
||||
</div>
|
||||
<div className='h-[1px] bg-gray-100'></div>
|
||||
<div className='p-1'>
|
||||
<div className='px-3 py-2 text-xs text-gray-500'>
|
||||
<div className='flex items-center mb-1 h-[22px] font-medium'>
|
||||
ABOUT
|
||||
{t('workflow.panel.about')}
|
||||
</div>
|
||||
<div className='text-gray-500 leading-[18px]'>{data._about}</div>
|
||||
<div className='my-2 h-[0.5px] bg-black/5'></div>
|
||||
<div className='leading-[18px]'>
|
||||
Created By {data._author}
|
||||
{t('workflow.panel.createdBy')} {data._author}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import {
|
|||
memo,
|
||||
useCallback,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import NextStep from './components/next-step'
|
||||
import PanelOperator from './components/panel-operator'
|
||||
import {
|
||||
|
|
@ -34,6 +35,7 @@ const BasePanel: FC<BasePanelProps> = ({
|
|||
data,
|
||||
children,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const {
|
||||
handleNodeSelect,
|
||||
handleNodeDataUpdate,
|
||||
|
|
@ -63,7 +65,7 @@ const BasePanel: FC<BasePanelProps> = ({
|
|||
{
|
||||
canRunBySingle(data.type) && (
|
||||
<TooltipPlus
|
||||
popupContent='Run this step'
|
||||
popupContent={t('workflow.panel.runThisStep')}
|
||||
>
|
||||
<div
|
||||
className='flex items-center justify-center mr-1 w-6 h-6 rounded-md hover:bg-black/5 cursor-pointer'
|
||||
|
|
@ -99,10 +101,10 @@ const BasePanel: FC<BasePanelProps> = ({
|
|||
<div className='p-4 border-t-[0.5px] border-t-black/5'>
|
||||
<div className='flex items-center mb-1 text-gray-700 text-[13px] font-semibold'>
|
||||
<GitBranch01 className='mr-1 w-4 h-4' />
|
||||
NEXT STEP
|
||||
{t('workflow.panel.nextStep').toLocaleUpperCase()}
|
||||
</div>
|
||||
<div className='mb-2 text-xs text-gray-400'>
|
||||
Add the next block in this workflow
|
||||
{t('workflow.panel.addNextStep')}
|
||||
</div>
|
||||
<NextStep selectedNode={{ id, data } as Node} />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import type { FC } from 'react'
|
||||
import { memo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import BlockIcon from '../block-icon'
|
||||
import { BlockEnum } from '../types'
|
||||
import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback'
|
||||
|
|
@ -8,6 +9,7 @@ import { useStore as useAppStore } from '@/app/components/app/store'
|
|||
import AppIcon from '@/app/components/base/app-icon'
|
||||
|
||||
const WorkflowInfo: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const appDetail = useAppStore(state => state.appDetail)
|
||||
|
||||
if (!appDetail)
|
||||
|
|
@ -32,12 +34,12 @@ const WorkflowInfo: FC = () => {
|
|||
</div>
|
||||
<div className='flex items-center px-4 h-[42px] text-[13px] font-semibold text-gray-700'>
|
||||
<FileCheck02 className='mr-1 w-4 h-4' />
|
||||
Checklist(2)
|
||||
{t('workflow.panel.checklist')}(2)
|
||||
</div>
|
||||
</div>
|
||||
<div className='py-2'>
|
||||
<div className='px-4 py-2 text-xs text-gray-400'>
|
||||
Make sure all issues are resolved before publishing
|
||||
{t('workflow.panel.checklistTip')}
|
||||
</div>
|
||||
<div className='px-4 py-2'>
|
||||
<div className='border-[0.5px] border-gray-200 bg-white shadow-xs rounded-lg'>
|
||||
|
|
|
|||
|
|
@ -23,9 +23,14 @@ const translation = {
|
|||
restore: 'Restore',
|
||||
},
|
||||
tabs: {
|
||||
blocks: 'Blocks',
|
||||
builtInTool: 'Built-in Tool',
|
||||
customTool: 'Custom Tool',
|
||||
'searchBlock': 'Search block',
|
||||
'blocks': 'Blocks',
|
||||
'builtInTool': 'Built-in Tool',
|
||||
'customTool': 'Custom Tool',
|
||||
'question-understand': 'Question Understand',
|
||||
'logic': 'Logic',
|
||||
'transform': 'Transform',
|
||||
'utilities': 'Utilities',
|
||||
},
|
||||
blocks: {
|
||||
'start': 'Start',
|
||||
|
|
@ -49,6 +54,16 @@ const translation = {
|
|||
},
|
||||
panel: {
|
||||
userInputField: 'User Input Field',
|
||||
changeBlock: 'Change Block',
|
||||
helpLink: 'Help Link',
|
||||
about: 'About',
|
||||
createdBy: 'Created By ',
|
||||
nextStep: 'Next Step',
|
||||
addNextStep: 'Add the next block in this workflow',
|
||||
selectNextStep: 'Select Next Block',
|
||||
runThisStep: 'Run this step',
|
||||
checklist: 'Checklist',
|
||||
checklistTip: 'Make sure all issues are resolved before publishing',
|
||||
},
|
||||
nodes: {
|
||||
common: {
|
||||
|
|
|
|||
|
|
@ -23,9 +23,14 @@ const translation = {
|
|||
restore: '恢复',
|
||||
},
|
||||
tabs: {
|
||||
blocks: 'Blocks',
|
||||
builtInTool: '内置工具',
|
||||
customTool: '自定义工具',
|
||||
'searchBlock': '搜索节点',
|
||||
'blocks': '节点',
|
||||
'builtInTool': '内置工具',
|
||||
'customTool': '自定义工具',
|
||||
'question-understand': '问题理解',
|
||||
'logic': '逻辑',
|
||||
'transform': '转换',
|
||||
'utilities': '工具',
|
||||
},
|
||||
blocks: {
|
||||
'start': '开始',
|
||||
|
|
@ -49,6 +54,16 @@ const translation = {
|
|||
},
|
||||
panel: {
|
||||
userInputField: '用户输入字段',
|
||||
changeBlock: '更改节点',
|
||||
helpLink: '帮助链接',
|
||||
about: '关于',
|
||||
createdBy: '作者',
|
||||
nextStep: '下一步',
|
||||
addNextStep: '添加此工作流程中的下一个节点',
|
||||
selectNextStep: '选择下一个节点',
|
||||
runThisStep: '运行此步骤',
|
||||
checklist: '检查清单',
|
||||
checklistTip: '发布前确保所有问题均已解决',
|
||||
},
|
||||
nodes: {
|
||||
common: {
|
||||
|
|
|
|||
Loading…
Reference in New Issue