add app-info-panel

This commit is contained in:
StyleZhang
2024-02-19 19:06:21 +08:00
parent 2386eed703
commit c7ee8ac1c7
10 changed files with 224 additions and 3 deletions

View File

@ -0,0 +1,58 @@
import type { FC } from 'react'
import { memo } from 'react'
import BlockIcon from './block-icon'
import { BlockEnum } from './types'
import { useWorkflowContext } from './context'
import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback'
import { FileCheck02 } from '@/app/components/base/icons/src/vender/line/files'
const AppInfoPanel: FC = () => {
const { selectedNode } = useWorkflowContext()
if (selectedNode)
return null
return (
<div className='absolute top-14 right-2 bottom-2 w-[420px] 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 pt-4 px-4 pb-1'>
<div className='mr-3 w-10 h-10'></div>
<div className='mt-2 text-base font-semibold text-gray-900'>
Fitness and Nutrition Expert
</div>
</div>
<div className='px-4 py-[13px] text-xs leading-[18px] text-gray-500'>
A Fitness and Nutrition Expert specializes in guiding individuals towards healthier lifestyles through exercise and diet.
</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)
</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
</div>
<div className='px-4 py-2'>
<div className='border-[0.5px] border-gray-200 bg-white shadow-xs rounded-lg'>
<div className='flex items-center p-2 h-9 text-xs font-medium text-gray-700'>
<BlockIcon
type={BlockEnum.Start}
className='mr-1.5'
/>
Start
</div>
<div className='px-3 py-2 border-t-[0.5px] border-t-black/[0.02] bg-gray-25 rounded-b-lg'>
<div className='flex text-xs leading-[18px] text-gray-500'>
<AlertTriangle className='mt-[3px] mr-2 w-3 h-3 text-[#F79009]' />
This step is not connected to anything
</div>
</div>
</div>
</div>
</div>
</div>
)
}
export default memo(AppInfoPanel)

View File

@ -37,6 +37,7 @@ const getIcon = (type: BlockEnum, className: string) => {
[BlockEnum.QuestionClassifier]: <QuestionClassifier className={className} />,
[BlockEnum.TemplateTransform]: <TemplatingTransform className={className} />,
[BlockEnum.VariableAssigner]: <VariableX className={className} />,
[BlockEnum.Tool]: <VariableX className={className} />,
}[type]
}
const ICON_CONTAINER_BG_COLOR_MAP: Record<string, string> = {

View File

@ -17,6 +17,8 @@ import Header from './header'
import CustomNode, {
Panel,
} from './nodes'
import AppInfoPanel from './app-info-panel'
import ZoomInOut from './zoom-in-out'
import CustomEdge from './custom-edge'
import type { Node } from './types'
@ -36,7 +38,9 @@ const Workflow = () => {
return (
<div className='relative w-full h-full'>
<Header />
<AppInfoPanel />
<Panel />
<ZoomInOut />
<ReactFlow
nodeTypes={nodeTypes}
edgeTypes={edgeTypes}

View File

@ -22,7 +22,7 @@ const BasePanel: FC<BasePanelProps> = ({
} = useWorkflowContext()
return (
<div className='absolute top-2 right-2 bottom-2 w-[420px] bg-white shadow-lg border-[0.5px] border-gray-200 rounded-2xl z-20 overflow-y-auto'>
<div className='absolute top-14 right-2 bottom-2 w-[420px] 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'>
<BlockIcon

View File

@ -34,11 +34,12 @@ const CustomNode = ({
export const Panel = () => {
const { selectedNode } = useWorkflowContext()
const PanelComponent = PanelMap[selectedNode?.data.type || '']
if (!PanelComponent)
if (!selectedNode)
return null
const PanelComponent = PanelMap[selectedNode.data.type]
return (
<PanelComponent />
)

View File

@ -0,0 +1,96 @@
import type { FC } from 'react'
import {
Fragment,
memo,
useState,
} from 'react'
import {
PortalToFollowElem,
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import { SearchLg } from '@/app/components/base/icons/src/vender/line/general'
import { ChevronDown } from '@/app/components/base/icons/src/vender/line/arrows'
const ZOOM_IN_OUT_OPTIONS = [
[
{
key: 'in',
text: 'Zoom In',
},
{
key: 'out',
text: 'Zoom Out',
},
],
[
{
key: 'to50',
text: 'Zoom to 50%',
},
{
key: 'to100',
text: 'Zoom to 100%',
},
],
[
{
key: 'fit',
text: 'Zoom to Fit',
},
],
]
const ZoomInOut: FC = () => {
const [open, setOpen] = useState(false)
return (
<PortalToFollowElem
placement='top-start'
open={open}
onOpenChange={setOpen}
offset={4}
>
<PortalToFollowElemTrigger asChild onClick={() => setOpen(v => !v)}>
<div className={`
absolute left-6 bottom-6
flex items-center px-2.5 h-9 cursor-pointer rounded-lg border-[0.5px] border-gray-100 bg-white shadow-lg
text-[13px] text-gray-500 z-10
`}>
<SearchLg className='mr-1 w-4 h-4' />
100%
<ChevronDown className='ml-1 w-4 h-4' />
</div>
</PortalToFollowElemTrigger>
<PortalToFollowElemContent>
<div className='w-[168px] rounded-lg border-[0.5px] border-gray-200 bg-white shadow-lg'>
{
ZOOM_IN_OUT_OPTIONS.map((options, i) => (
<Fragment key={i}>
{
i !== 0 && (
<div className='h-[1px] bg-gray-100' />
)
}
<div className='p-1'>
{
options.map(option => (
<div
key={option.key}
className='flex items-center px-3 h-8 rounded-lg hover:bg-gray-50 cursor-pointer text-sm text-gray-700'
>
{option.text}
</div>
))
}
</div>
</Fragment>
))
}
</div>
</PortalToFollowElemContent>
</PortalToFollowElem>
)
}
export default memo(ZoomInOut)