mirror of
https://github.com/langgenius/dify.git
synced 2026-05-12 07:37:09 +08:00
fix: improve workflow checklist semantics (#36006)
This commit is contained in:
parent
153064bbd4
commit
2162ea6a68
@ -54,6 +54,8 @@ vi.mock('@langgenius/dify-ui/popover', () => ({
|
||||
},
|
||||
PopoverTrigger: ({ render }: { render: ReactNode }) => <>{render}</>,
|
||||
PopoverContent: ({ children }: { children: ReactNode }) => <div>{children}</div>,
|
||||
PopoverTitle: ({ children, className }: { children: ReactNode, className?: string }) => <h2 className={className}>{children}</h2>,
|
||||
PopoverDescription: ({ children, className }: { children: ReactNode, className?: string }) => <p className={className}>{children}</p>,
|
||||
PopoverClose: ({ children, className }: { children: ReactNode, className?: string }) => <button className={className}>{children}</button>,
|
||||
}))
|
||||
|
||||
|
||||
@ -36,6 +36,7 @@ describe('ChecklistNodeGroup', () => {
|
||||
expect(screen.getByText('Needs configuration')).toBeInTheDocument()
|
||||
expect(screen.getByText(/needConnectTip/i)).toBeInTheDocument()
|
||||
expect(screen.getAllByText(/goToFix/i)).toHaveLength(2)
|
||||
expect(screen.getByRole('button', { name: /Needs configuration/i })).toHaveAttribute('title', 'Needs configuration')
|
||||
|
||||
fireEvent.click(screen.getByText('Needs configuration'))
|
||||
|
||||
@ -57,5 +58,7 @@ describe('ChecklistNodeGroup', () => {
|
||||
|
||||
expect(onItemClick).not.toHaveBeenCalled()
|
||||
expect(screen.queryByText(/goToFix/i)).not.toBeInTheDocument()
|
||||
expect(screen.queryByRole('button', { name: /Needs configuration/i })).not.toBeInTheDocument()
|
||||
expect(screen.getByText('Needs configuration').parentElement).toHaveAttribute('title', 'Needs configuration')
|
||||
})
|
||||
})
|
||||
|
||||
@ -7,6 +7,8 @@ import {
|
||||
Popover,
|
||||
PopoverClose,
|
||||
PopoverContent,
|
||||
PopoverDescription,
|
||||
PopoverTitle,
|
||||
PopoverTrigger,
|
||||
} from '@langgenius/dify-ui/popover'
|
||||
import {
|
||||
@ -43,6 +45,7 @@ const WorkflowChecklist = ({
|
||||
const nodes = useNodes()
|
||||
const needWarningNodes = useChecklist(nodes, edges)
|
||||
const { handleNodeSelect } = useNodesInteractions()
|
||||
const checklistLabel = t('panel.checklist', { ns: 'workflow' })
|
||||
|
||||
const { pluginItems, nodeItems } = useMemo(() => {
|
||||
const plugins: ChecklistItem[] = []
|
||||
@ -75,12 +78,14 @@ const WorkflowChecklist = ({
|
||||
disabled && 'cursor-not-allowed opacity-50',
|
||||
)}
|
||||
disabled={disabled || undefined}
|
||||
aria-label={checklistLabel}
|
||||
>
|
||||
<span
|
||||
className={cn('group flex h-full w-full items-center justify-center rounded-md hover:bg-state-accent-hover', open && 'bg-state-accent-hover')}
|
||||
>
|
||||
<span
|
||||
className={cn('i-ri-list-check-3 h-4 w-4 group-hover:text-components-button-secondary-accent-text', open ? 'text-components-button-secondary-accent-text' : 'text-components-button-ghost-text')}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</span>
|
||||
{!!needWarningNodes.length && (
|
||||
@ -104,19 +109,22 @@ const WorkflowChecklist = ({
|
||||
<div className="flex flex-col gap-0.5 px-3 pt-3.5 pb-1">
|
||||
<div className="flex items-start px-1">
|
||||
<div className="min-w-0 grow pr-8">
|
||||
<h2 className="text-base leading-6 font-semibold text-text-primary">
|
||||
{t('panel.checklist', { ns: 'workflow' })}
|
||||
<PopoverTitle className="text-base leading-6 font-semibold text-text-primary">
|
||||
{checklistLabel}
|
||||
{needWarningNodes.length > 0 && `(${needWarningNodes.length})`}
|
||||
</h2>
|
||||
</PopoverTitle>
|
||||
</div>
|
||||
<PopoverClose className="-mt-0.5 -mr-0.5 flex size-7 shrink-0 items-center justify-center rounded-lg">
|
||||
<span className="i-ri-close-line size-4 text-text-tertiary" />
|
||||
<PopoverClose
|
||||
className="-mt-0.5 -mr-0.5 flex size-7 shrink-0 items-center justify-center rounded-lg"
|
||||
aria-label={t('operation.close', { ns: 'common' })}
|
||||
>
|
||||
<span className="i-ri-close-line size-4 text-text-tertiary" aria-hidden="true" />
|
||||
</PopoverClose>
|
||||
</div>
|
||||
{needWarningNodes.length > 0 && (
|
||||
<p className="px-1 text-xs leading-4 text-text-tertiary">
|
||||
<PopoverDescription className="px-1 text-xs leading-4 text-text-tertiary">
|
||||
{t('panel.checklistDescription', { ns: 'workflow' })}
|
||||
</p>
|
||||
</PopoverDescription>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
@ -45,29 +45,48 @@ export const ChecklistNodeGroup = memo(({
|
||||
</span>
|
||||
</div>
|
||||
<div className="p-1">
|
||||
{subItems.map(sub => (
|
||||
<div
|
||||
key={sub.key}
|
||||
className={cn(
|
||||
'group/item flex items-start gap-2 rounded-lg px-1',
|
||||
goToEnabled && 'cursor-pointer hover:bg-state-base-hover',
|
||||
)}
|
||||
onClick={() => goToEnabled && onItemClick(item)}
|
||||
>
|
||||
<ItemIndicator />
|
||||
<span className="min-w-0 grow py-1 text-xs leading-4 text-text-warning">
|
||||
{sub.message}
|
||||
</span>
|
||||
{goToEnabled && (
|
||||
<div className="flex shrink-0 items-center gap-0.5 pt-1 pr-0.5 opacity-0 transition-opacity duration-150 group-hover/item:opacity-100">
|
||||
<span className="text-xs leading-4 font-medium whitespace-nowrap text-text-accent">
|
||||
{t('panel.goToFix', { ns: 'workflow' })}
|
||||
</span>
|
||||
<span className="i-ri-arrow-right-line size-3.5 text-text-accent" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{subItems.map((sub) => {
|
||||
const content = (
|
||||
<>
|
||||
<ItemIndicator />
|
||||
<span className="min-w-0 grow truncate text-xs leading-4 text-text-warning">
|
||||
{sub.message}
|
||||
</span>
|
||||
{goToEnabled && (
|
||||
<div className="flex shrink-0 items-center gap-0.5 pr-0.5 opacity-0 transition-opacity duration-150 group-hover/item:opacity-100">
|
||||
<span className="text-xs leading-4 font-medium whitespace-nowrap text-text-accent">
|
||||
{t('panel.goToFix', { ns: 'workflow' })}
|
||||
</span>
|
||||
<span className="i-ri-arrow-right-line size-3.5 text-text-accent" aria-hidden="true" />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
const className = cn(
|
||||
'group/item flex w-full items-center gap-2 rounded-lg px-1 text-left',
|
||||
goToEnabled && 'cursor-pointer hover:bg-state-base-hover',
|
||||
)
|
||||
|
||||
if (goToEnabled) {
|
||||
return (
|
||||
<button
|
||||
key={sub.key}
|
||||
type="button"
|
||||
className={cn(className, 'border-none bg-transparent')}
|
||||
title={sub.message}
|
||||
onClick={() => onItemClick(item)}
|
||||
>
|
||||
{content}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div key={sub.key} className={className} title={sub.message}>
|
||||
{content}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user