Commit 240e0dfa authored by StyleZhang's avatar StyleZhang

next-step

parent ab6a01b4
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="git-branch-01">
<path id="Icon" d="M2 2V8.8C2 9.92011 2 10.4802 2.21799 10.908C2.40973 11.2843 2.71569 11.5903 3.09202 11.782C3.51984 12 4.0799 12 5.2 12H10M10 12C10 13.1046 10.8954 14 12 14C13.1046 14 14 13.1046 14 12C14 10.8954 13.1046 10 12 10C10.8954 10 10 10.8954 10 12ZM2 5.33333L10 5.33333M10 5.33333C10 6.4379 10.8954 7.33333 12 7.33333C13.1046 7.33333 14 6.4379 14 5.33333C14 4.22876 13.1046 3.33333 12 3.33333C10.8954 3.33333 10 4.22876 10 5.33333Z" stroke="#344054" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="log-in-04">
<g id="Solid">
<path d="M8.00016 1.99984C5.78015 1.99984 3.84088 3.20518 2.80244 5.00032C2.61808 5.31903 2.21026 5.42794 1.89155 5.24357C1.57285 5.05921 1.46394 4.65139 1.6483 4.33269C2.91526 2.14249 5.28495 0.666504 8.00016 0.666504C12.0502 0.666504 15.3335 3.94975 15.3335 7.99984C15.3335 12.0499 12.0502 15.3332 8.00016 15.3332C5.28495 15.3332 2.91526 13.8572 1.6483 11.667C1.46394 11.3483 1.57285 10.9405 1.89155 10.7561C2.21026 10.5717 2.61808 10.6806 2.80244 10.9994C3.84088 12.7945 5.78015 13.9998 8.00016 13.9998C11.3139 13.9998 14.0002 11.3135 14.0002 7.99984C14.0002 4.68613 11.3139 1.99984 8.00016 1.99984Z" fill="#344054"/>
<path d="M7.52876 4.86177C7.78911 4.60142 8.21122 4.60142 8.47157 4.86177L11.1382 7.52843C11.3986 7.78878 11.3986 8.21089 11.1382 8.47124L8.47157 11.1379C8.21122 11.3983 7.78911 11.3983 7.52876 11.1379C7.26841 10.8776 7.26841 10.4554 7.52876 10.1951L9.05735 8.6665H2.00016C1.63197 8.6665 1.3335 8.36803 1.3335 7.99984C1.3335 7.63165 1.63197 7.33317 2.00016 7.33317H9.05735L7.52876 5.80457C7.26841 5.54423 7.26841 5.12212 7.52876 4.86177Z" fill="#344054"/>
</g>
</g>
</svg>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="log-out-04">
<g id="Solid">
<path d="M0.666504 8.00016C0.666504 4.3422 3.52829 1.3335 7.11095 1.3335C8.28872 1.3335 9.3935 1.66091 10.3431 2.23137C10.6588 2.42097 10.7609 2.83053 10.5713 3.14615C10.3817 3.46177 9.97216 3.56394 9.65654 3.37434C8.90651 2.92378 8.03794 2.66683 7.11095 2.66683C4.31165 2.66683 1.99984 5.03071 1.99984 8.00016C1.99984 10.9696 4.31165 13.3335 7.11095 13.3335C8.03794 13.3335 8.90651 13.0765 9.65654 12.626C9.97216 12.4364 10.3817 12.5386 10.5713 12.8542C10.7609 13.1698 10.6588 13.5794 10.3431 13.769C9.3935 14.3394 8.28872 14.6668 7.11095 14.6668C3.52829 14.6668 0.666504 11.6581 0.666504 8.00016Z" fill="#98A2B3"/>
<path d="M11.5284 4.86209C11.7888 4.60174 12.2109 4.60174 12.4712 4.86209L15.1379 7.52876C15.3983 7.78911 15.3983 8.21122 15.1379 8.47157L12.4712 11.1382C12.2109 11.3986 11.7888 11.3986 11.5284 11.1382C11.2681 10.8779 11.2681 10.4558 11.5284 10.1954L13.057 8.66683H5.99984C5.63165 8.66683 5.33317 8.36835 5.33317 8.00016C5.33317 7.63197 5.63165 7.3335 5.99984 7.3335H13.057L11.5284 5.8049C11.2681 5.54455 11.2681 5.12244 11.5284 4.86209Z" fill="#98A2B3"/>
</g>
</g>
</svg>
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "16",
"height": "16",
"viewBox": "0 0 16 16",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "git-branch-01"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"id": "Icon",
"d": "M2 2V8.8C2 9.92011 2 10.4802 2.21799 10.908C2.40973 11.2843 2.71569 11.5903 3.09202 11.782C3.51984 12 4.0799 12 5.2 12H10M10 12C10 13.1046 10.8954 14 12 14C13.1046 14 14 13.1046 14 12C14 10.8954 13.1046 10 12 10C10.8954 10 10 10.8954 10 12ZM2 5.33333L10 5.33333M10 5.33333C10 6.4379 10.8954 7.33333 12 7.33333C13.1046 7.33333 14 6.4379 14 5.33333C14 4.22876 13.1046 3.33333 12 3.33333C10.8954 3.33333 10 4.22876 10 5.33333Z",
"stroke": "currentColor",
"stroke-width": "1.25",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
}
]
}
]
},
"name": "GitBranch01"
}
\ No newline at end of file
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './GitBranch01.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
Icon.displayName = 'GitBranch01'
export default Icon
......@@ -3,6 +3,7 @@ export { default as BracketsX } from './BracketsX'
export { default as Container } from './Container'
export { default as Database01 } from './Database01'
export { default as Database03 } from './Database03'
export { default as GitBranch01 } from './GitBranch01'
export { default as PuzzlePiece01 } from './PuzzlePiece01'
export { default as Variable } from './Variable'
export { default as Webhooks } from './Webhooks'
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "16",
"height": "16",
"viewBox": "0 0 16 16",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "log-in-04"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "Solid"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"d": "M8.00016 1.99984C5.78015 1.99984 3.84088 3.20518 2.80244 5.00032C2.61808 5.31903 2.21026 5.42794 1.89155 5.24357C1.57285 5.05921 1.46394 4.65139 1.6483 4.33269C2.91526 2.14249 5.28495 0.666504 8.00016 0.666504C12.0502 0.666504 15.3335 3.94975 15.3335 7.99984C15.3335 12.0499 12.0502 15.3332 8.00016 15.3332C5.28495 15.3332 2.91526 13.8572 1.6483 11.667C1.46394 11.3483 1.57285 10.9405 1.89155 10.7561C2.21026 10.5717 2.61808 10.6806 2.80244 10.9994C3.84088 12.7945 5.78015 13.9998 8.00016 13.9998C11.3139 13.9998 14.0002 11.3135 14.0002 7.99984C14.0002 4.68613 11.3139 1.99984 8.00016 1.99984Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M7.52876 4.86177C7.78911 4.60142 8.21122 4.60142 8.47157 4.86177L11.1382 7.52843C11.3986 7.78878 11.3986 8.21089 11.1382 8.47124L8.47157 11.1379C8.21122 11.3983 7.78911 11.3983 7.52876 11.1379C7.26841 10.8776 7.26841 10.4554 7.52876 10.1951L9.05735 8.6665H2.00016C1.63197 8.6665 1.3335 8.36803 1.3335 7.99984C1.3335 7.63165 1.63197 7.33317 2.00016 7.33317H9.05735L7.52876 5.80457C7.26841 5.54423 7.26841 5.12212 7.52876 4.86177Z",
"fill": "currentColor"
},
"children": []
}
]
}
]
}
]
},
"name": "LogIn04"
}
\ No newline at end of file
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './LogIn04.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
Icon.displayName = 'LogIn04'
export default Icon
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "16",
"height": "16",
"viewBox": "0 0 16 16",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "log-out-04"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "Solid"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"d": "M0.666504 8.00016C0.666504 4.3422 3.52829 1.3335 7.11095 1.3335C8.28872 1.3335 9.3935 1.66091 10.3431 2.23137C10.6588 2.42097 10.7609 2.83053 10.5713 3.14615C10.3817 3.46177 9.97216 3.56394 9.65654 3.37434C8.90651 2.92378 8.03794 2.66683 7.11095 2.66683C4.31165 2.66683 1.99984 5.03071 1.99984 8.00016C1.99984 10.9696 4.31165 13.3335 7.11095 13.3335C8.03794 13.3335 8.90651 13.0765 9.65654 12.626C9.97216 12.4364 10.3817 12.5386 10.5713 12.8542C10.7609 13.1698 10.6588 13.5794 10.3431 13.769C9.3935 14.3394 8.28872 14.6668 7.11095 14.6668C3.52829 14.6668 0.666504 11.6581 0.666504 8.00016Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M11.5284 4.86209C11.7888 4.60174 12.2109 4.60174 12.4712 4.86209L15.1379 7.52876C15.3983 7.78911 15.3983 8.21122 15.1379 8.47157L12.4712 11.1382C12.2109 11.3986 11.7888 11.3986 11.5284 11.1382C11.2681 10.8779 11.2681 10.4558 11.5284 10.1954L13.057 8.66683H5.99984C5.63165 8.66683 5.33317 8.36835 5.33317 8.00016C5.33317 7.63197 5.63165 7.3335 5.99984 7.3335H13.057L11.5284 5.8049C11.2681 5.54455 11.2681 5.12244 11.5284 4.86209Z",
"fill": "currentColor"
},
"children": []
}
]
}
]
}
]
},
"name": "LogOut04"
}
\ No newline at end of file
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './LogOut04.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
Icon.displayName = 'LogOut04'
export default Icon
......@@ -13,7 +13,9 @@ export { default as Link03 } from './Link03'
export { default as LinkExternal01 } from './LinkExternal01'
export { default as LinkExternal02 } from './LinkExternal02'
export { default as Loading02 } from './Loading02'
export { default as LogIn04 } from './LogIn04'
export { default as LogOut01 } from './LogOut01'
export { default as LogOut04 } from './LogOut04'
export { default as Menu01 } from './Menu01'
export { default as Pin01 } from './Pin01'
export { default as Pin02 } from './Pin02'
......
import type { FC } from 'react'
import { memo } from 'react'
import { BlockEnum } from './types'
import {
Code,
......@@ -67,4 +68,4 @@ const BlockIcon: FC<BlockIconProps> = ({
)
}
export default BlockIcon
export default memo(BlockIcon)
import { groupBy } from 'lodash-es'
import type { Block } from '../types'
import { BlockEnum } from '../types'
......@@ -16,57 +17,79 @@ export const TABS = [
},
]
export enum BlockClassificationEnum {
Default = '-',
QuestionUnderstand = 'question-understand',
Logic = 'logic',
Transform = 'transform',
Utilities = 'utilities',
}
export const BLOCKS: Block[] = [
{
classification: BlockClassificationEnum.Default,
type: BlockEnum.Start,
title: 'Start',
description: '',
},
{
classification: BlockClassificationEnum.Default,
type: BlockEnum.LLM,
title: 'LLM',
},
{
classification: BlockClassificationEnum.Default,
type: BlockEnum.End,
title: 'End',
},
{
classification: BlockClassificationEnum.Default,
type: BlockEnum.DirectAnswer,
title: 'Direct Answer',
},
{
classification: 'Question Understand',
classification: BlockClassificationEnum.QuestionUnderstand,
type: BlockEnum.KnowledgeRetrieval,
title: 'Knowledge Retrieval',
},
{
classification: 'Question Understand',
classification: BlockClassificationEnum.QuestionUnderstand,
type: BlockEnum.QuestionClassifier,
title: 'Question Classifier',
},
{
classification: 'Logic',
classification: BlockClassificationEnum.Logic,
type: BlockEnum.IfElse,
title: 'IF/ELSE',
},
{
classification: 'Transform',
classification: BlockClassificationEnum.Transform,
type: BlockEnum.Code,
title: 'Code',
},
{
classification: 'Transform',
classification: BlockClassificationEnum.Transform,
type: BlockEnum.TemplateTransform,
title: 'Templating Transform',
},
{
classification: 'Transform',
classification: BlockClassificationEnum.Transform,
type: BlockEnum.VariableAssigner,
title: 'Variable Assigner',
},
{
classification: 'Utilities',
classification: BlockClassificationEnum.Utilities,
type: BlockEnum.HttpRequest,
title: 'HTTP Request',
},
]
export const BLOCK_CLASSIFICATIONS: string[] = [
BlockClassificationEnum.Default,
BlockClassificationEnum.QuestionUnderstand,
BlockClassificationEnum.Logic,
BlockClassificationEnum.Transform,
BlockClassificationEnum.Utilities,
]
export const BLOCK_GROUP_BY_CLASSIFICATION = groupBy(BLOCKS, 'classification')
......@@ -33,7 +33,7 @@ const NodeSelector: FC<NodeSelectorProps> = ({
<PortalToFollowElemTrigger onClick={handleTrigger}>
{children}
</PortalToFollowElemTrigger>
<PortalToFollowElemContent>
<PortalToFollowElemContent className='z-50'>
<div className='w-[256px] rounded-lg border-[0.5px] border-gray-200 bg-white shadow-lg'>
<div className='px-2 pt-2'>
<div className='flex items-center px-2 rounded-lg bg-gray-100'>
......
import { useState } from 'react'
import BlockIcon from '../block-icon'
import {
BLOCKS,
BLOCK_CLASSIFICATIONS,
BLOCK_GROUP_BY_CLASSIFICATION,
TABS,
} from './constants'
......@@ -28,16 +29,32 @@ const Tabs = () => {
</div>
<div className='p-1'>
{
BLOCKS.map(block => (
BLOCK_CLASSIFICATIONS.map(classification => (
<div
key={block.type}
className='flex items-center px-3 h-8 rounded-lg hover:bg-gray-50 cursor-pointer'
key={classification}
className='mb-1 last-of-type:mb-0'
>
<BlockIcon
className='mr-2'
type={block.type}
/>
<div className='text-sm text-gray-900'>{block.title}</div>
{
classification !== '-' && (
<div className='flex items-start px-3 h-[22px] text-xs font-medium text-gray-500'>
{classification}
</div>
)
}
{
BLOCK_GROUP_BY_CLASSIFICATION[classification].map(block => (
<div
key={block.type}
className='flex items-center px-3 h-8 rounded-lg hover:bg-gray-50 cursor-pointer'
>
<BlockIcon
className='mr-2'
type={block.type}
/>
<div className='text-sm text-gray-900'>{block.title}</div>
</div>
))
}
</div>
))
}
......
import type { BlockEnum } from '../types'
import { BLOCKS } from './constants'
export const getBlockByType = (type: BlockEnum) => {
return BLOCKS.find(block => block.type === type)
}
import type { FC } from 'react'
import {
memo,
useMemo,
} from 'react'
import { getOutgoers } from 'reactflow'
import BlockIcon from '../../../block-icon'
import type { Node } from '../../../types'
import { useWorkflowContext } from '../../../context'
import BlockSelector from '../../../block-selector'
import { Plus } from '@/app/components/base/icons/src/vender/line/general'
import Button from '@/app/components/base/button'
type NextStepProps = {
selectedNode: Node
}
const NextStep: FC<NextStepProps> = ({
selectedNode,
}) => {
const {
nodes,
edges,
} = useWorkflowContext()
const outgoers = useMemo(() => {
return getOutgoers(selectedNode, nodes, edges)
}, [selectedNode, nodes, edges])
return (
<div className='flex py-1'>
<div className='shrink-0 relative flex items-center justify-center w-9 h-9 bg-white rounded-lg border-[0.5px] border-gray-200 shadow-xs'>
<BlockIcon type={selectedNode.data.type} />
</div>
<div className='shrink-0 w-6'></div>
<div className='grow'>
{
!outgoers.length && (
<BlockSelector>
<div className='flex items-center px-2 w-[328px] h-9 rounded-lg border border-dashed border-gray-200 bg-gray-50 hover:bg-gray-100 text-xs text-gray-500 cursor-pointer'>
<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
</div>
</BlockSelector>
)
}
{
!!outgoers.length && outgoers.map(outgoer => (
<div
key={outgoer.id}
className='group flex items-center mb-3 last-of-type:mb-0 px-2 h-9 rounded-lg border-[0.5px] border-gray-200 bg-white hover:bg-gray-50 shadow-xs text-xs text-gray-700 cursor-pointer'
>
<BlockIcon
type={outgoer.data.type}
className='shrink-0 mr-1.5'
/>
<div className='grow'>{outgoer.data.name}</div>
<BlockSelector>
<Button className='hidden group-hover:flex px-2 py-0 h-6 bg-white text-xs text-gray-700 font-medium rounded-md'>
Change
</Button>
</BlockSelector>
</div>
))
}
</div>
</div>
)
}
export default memo(NextStep)
......@@ -9,6 +9,7 @@ import {
} from 'reactflow'
import { useWorkflowContext } from '../../context'
import BlockSelector from '../../block-selector'
import { getBlockByType } from '../../block-selector/utils'
import BlockIcon from '../../block-icon'
import { Plus } from '@/app/components/base/icons/src/vender/line/general'
......@@ -48,7 +49,9 @@ const BaseNode: FC<BaseNodeProps> = ({
type={currentNode!.data.type}
size='md'
/>
<div className='text-[13px] font-semibold text-gray-700'>START</div>
<div className='text-[13px] font-semibold text-gray-700'>
{getBlockByType(currentNode!.data.type)?.title}
</div>
</div>
{children}
<div className='px-3 pt-1 pb-1 text-xs text-gray-500'>
......
......@@ -5,7 +5,14 @@ import type {
import { useState } from 'react'
import { useWorkflowContext } from '../../context'
import BlockIcon from '../../block-icon'
import { XClose } from '@/app/components/base/icons/src/vender/line/general'
import { getBlockByType } from '../../block-selector/utils'
import NextStep from './components/next-step'
import {
LogIn04,
LogOut04,
XClose,
} from '@/app/components/base/icons/src/vender/line/general'
import { GitBranch01 } from '@/app/components/base/icons/src/vender/line/development'
enum TabEnum {
Inputs = 'inputs',
......@@ -32,17 +39,17 @@ const BasePanel: FC<BasePanelProps> = ({
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='sticky top-0 bg-white'>
<div className='sticky top-0 bg-white border-b-[0.5px] border-black/5'>
<div className='flex items-center px-4 pt-3'>
<BlockIcon
className='shrink-0 mr-2'
type={selectedNode!.data.type}
size='md'
/>
<div className='grow py-1 text-base text-gray-900 font-semibold '>LLM</div>
<div className='grow py-1 text-base text-gray-900 font-semibold '>{getBlockByType(selectedNode!.data.type)?.title}</div>
<div className='shrink-0 flex items-center'>
<div
className='w-6 h-6 cursor-pointer'
className='flex items-center justify-center w-6 h-6 cursor-pointer'
onClick={() => handleSelectedNodeIdChange('')}
>
<XClose className='w-4 h-4 text-gray-500' />
......@@ -56,24 +63,32 @@ const BasePanel: FC<BasePanelProps> = ({
</div>
{
(inputsElement || outputsElement) && (
<div className='flex items-center px-4 h-[42px]'>
<div className='flex items-center px-4 h-[42px] text-[13px] font-semibold text-gray-400'>
{
inputsElement && (
<div
className='cursor-pointer'
className={`relative flex items-center h-full cursor-pointer ${activeTab === TabEnum.Inputs && 'text-gray-700'}`}
onClick={() => setActiveTab(TabEnum.Inputs)}
>
inputs
<LogIn04 className='mr-1 w-4 h-4' />
INPUTS
{
activeTab === TabEnum.Inputs && <div className='absolute left-0 bottom-0 w-full h-0.5 bg-primary-600' />
}
</div>
)
}
{
outputsElement && (
<div
className='ml-4 cursor-pointer'
className={`relative flex items-center ml-4 h-full cursor-pointer ${activeTab === TabEnum.Outputs && 'text-gray-700'}`}
onClick={() => setActiveTab(TabEnum.Outputs)}
>
outpus
<LogOut04 className='mr-1 w-4 h-4' />
OUTPUTS
{
activeTab === TabEnum.Outputs && <div className='absolute left-0 bottom-0 w-full h-0.5 bg-primary-600' />
}
</div>
)
}
......@@ -81,13 +96,20 @@ const BasePanel: FC<BasePanelProps> = ({
)
}
</div>
<div className='py-2 border-t-[0.5px] border-b-[0.5px] border-black/5'>
<div className='py-2 border-b-[0.5px] border-black/5'>
{defaultElement}
{activeTab === TabEnum.Inputs && inputsElement}
{activeTab === TabEnum.Outputs && outputsElement}
</div>
<div className='p-4'>
next step
<div className='flex items-center mb-1 text-gray-700 text-[13px] font-semibold'>
<GitBranch01 className='mr-1 w-4 h-4' />
NEXT STEP
</div>
<div className='mb-2 text-xs text-gray-400'>
Add the next block in this workflow
</div>
<NextStep selectedNode={selectedNode!} />
</div>
</div>
)
......
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