Commit 6e2611c8 authored by StyleZhang's avatar StyleZhang

node title desc

parent 7574107d
......@@ -8,7 +8,9 @@ import {
getConnectedEdges,
useStoreApi,
} from 'reactflow'
import type { SelectedNode } from './types'
import type {
SelectedNode,
} from './types'
import { useStore } from './store'
export const useWorkflow = () => {
......@@ -113,6 +115,19 @@ export const useWorkflow = () => {
setNodes(newNodes)
}
}, [setSelectedNode, store])
const handleUpdateNodeData = useCallback(({ id, data }: SelectedNode) => {
const {
getNodes,
setNodes,
} = store.getState()
const newNodes = produce(getNodes(), (draft) => {
const currentNode = draft.find(n => n.id === id)
if (currentNode)
currentNode.data = { ...currentNode.data, ...data }
})
setNodes(newNodes)
setSelectedNode({ id, data })
}, [store, setSelectedNode])
return {
handleEnterNode,
......@@ -120,5 +135,6 @@ export const useWorkflow = () => {
handleEnterEdge,
handleLeaveEdge,
handleSelectNode,
handleUpdateNodeData,
}
}
import {
memo,
useCallback,
useState,
} from 'react'
import Textarea from 'rc-textarea'
type InputProps = {
value: string
onChange: (value: string) => void
}
export const TitleInput = memo(({
value,
onChange,
}: InputProps) => {
return (
<input
value={value}
onChange={e => onChange(e.target.value)}
className={`
grow mr-2 px-1 h-6 text-base text-gray-900 font-semibold rounded-lg border border-transparent appearance-none outline-none
hover:bg-gray-50
focus:border-gray-300 focus:shadow-xs focus:bg-white
`}
placeholder='Add title...'
/>
)
})
TitleInput.displayName = 'TitleInput'
export const DescriptionInput = memo(({
value,
onChange,
}: InputProps) => {
const [focus, setFocus] = useState(false)
const handleFocus = useCallback(() => {
setFocus(true)
}, [])
const handleBlur = useCallback(() => {
setFocus(false)
}, [])
return (
<div
className={`
group flex px-2 py-[5px] max-h-[60px] rounded-lg overflow-y-auto
border border-transparent hover:bg-gray-50 leading-0
${focus && '!border-gray-300 shadow-xs !bg-gray-50'}
`}
>
<Textarea
value={value}
onChange={e => onChange(e.target.value)}
rows={1}
onFocus={handleFocus}
onBlur={handleBlur}
className={`
w-full text-xs text-gray-900 leading-[18px] bg-transparent
appearance-none outline-none resize-none
placeholder:text-gray-400
`}
placeholder='Add description...'
autoSize
/>
</div>
)
})
DescriptionInput.displayName = 'DescriptionInput'
......@@ -26,7 +26,7 @@ const BaseNode: FC<BaseNodeProps> = ({
return (
<div
className={`
group relative pb-2 w-[240px] bg-[#fcfdff] rounded-2xl shadow-xs
group relative w-[240px] bg-[#fcfdff] rounded-2xl shadow-xs
hover:shadow-lg
${(data.selected && selected) ? 'border-[2px] border-primary-600' : 'border border-white'}
`}
......@@ -35,17 +35,26 @@ const BaseNode: FC<BaseNodeProps> = ({
<NodeControl />
<div className='flex items-center px-3 pt-3 pb-2'>
<BlockIcon
className='mr-2'
className='shrink-0 mr-2'
type={data.type}
size='md'
/>
<div className='text-[13px] font-semibold text-gray-700'>
<div
title={data.title}
className='text-[13px] font-semibold text-gray-700 truncate'
>
{data.title}
</div>
</div>
{cloneElement(children, { id: nodeId, data })}
<div className='px-3 pt-1 pb-1 text-xs text-gray-500'>
Define the initial parameters for launching a workflow
<div className='mt-1 pb-1'>
{
data.desc && (
<div className='px-3 pt-1 pb-2 text-xs leading-[18px] text-gray-500 whitespace-pre-line break-words'>
{data.desc}
</div>
)
}
</div>
</div>
)
......
......@@ -5,11 +5,16 @@ import type {
import {
cloneElement,
memo,
useCallback,
} from 'react'
import type { SelectedNode } from '../../types'
import BlockIcon from '../../block-icon'
import { useWorkflow } from '../../hooks'
import NextStep from './components/next-step'
import {
DescriptionInput,
TitleInput,
} from './components/title-description-input'
import {
DotsHorizontal,
XClose,
......@@ -25,18 +30,30 @@ const BasePanel: FC<BasePanelProps> = ({
data,
children,
}) => {
const { handleSelectNode } = useWorkflow()
const {
handleSelectNode,
handleUpdateNodeData,
} = useWorkflow()
const handleTitleChange = useCallback((title: string) => {
handleUpdateNodeData({ id, data: { ...data, title } })
}, [handleUpdateNodeData, id, data])
const handleDescriptionChange = useCallback((desc: string) => {
handleUpdateNodeData({ id, data: { ...data, desc } })
}, [handleUpdateNodeData, id, data])
return (
<div className='mr-2 w-[420px] h-full bg-white shadow-lg border-[0.5px] border-gray-200 rounded-2xl z-10 overflow-y-auto'>
<div className='sticky top-0 bg-white border-b-[0.5px] border-black/5'>
<div className='flex items-center px-4 pt-3'>
<div className='flex items-center px-4 pt-4 pb-1'>
<BlockIcon
className='shrink-0 mr-2'
className='shrink-0 mr-1'
type={data.type}
size='md'
/>
<div className='grow py-1 text-base text-gray-900 font-semibold '>{data.title}</div>
<TitleInput
value={data.title || ''}
onChange={handleTitleChange}
/>
<div className='shrink-0 flex items-center text-gray-500'>
<div className='flex items-center justify-center w-6 h-6 cursor-pointer'>
<DotsHorizontal className='w-4 h-4' />
......@@ -51,9 +68,10 @@ const BasePanel: FC<BasePanelProps> = ({
</div>
</div>
<div className='p-2'>
<div className='py-[5px] pl-1.5 pr-2 text-xs text-gray-400'>
Add description...
</div>
<DescriptionInput
value={data.desc || ''}
onChange={handleDescriptionChange}
/>
</div>
</div>
<div className='py-2 border-b-[0.5px] border-black/5'>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment