mirror of
https://github.com/langgenius/dify.git
synced 2026-03-22 14:57:58 +08:00
feat(web): add warning dot indicator on LLM panel field labels synced with checklist
Store checklist items in zustand WorkflowStore so both the checklist UI and node panels share a single source of truth. The LLM panel reads from the store to show a Figma-aligned warning dot (absolute-positioned, no layout shift) on the MODEL field label when the node has checklist warnings.
This commit is contained in:
@ -104,6 +104,7 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => {
|
||||
const appMode = useAppStore.getState().appDetail?.mode
|
||||
const shouldCheckStartNode = appMode === AppModeEnum.WORKFLOW || appMode === AppModeEnum.ADVANCED_CHAT
|
||||
const modelProviders = useProviderContextSelector(s => s.modelProviders)
|
||||
const workflowStore = useWorkflowStore()
|
||||
|
||||
const map = useNodesAvailableVarList(nodes)
|
||||
const { data: embeddingModelList } = useModelList(ModelTypeEnum.textEmbedding)
|
||||
@ -261,8 +262,9 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => {
|
||||
}
|
||||
})
|
||||
|
||||
workflowStore.setState({ checklistItems: list })
|
||||
return list
|
||||
}, [nodes, edges, shouldCheckStartNode, nodesExtraData, buildInTools, customTools, workflowTools, language, dataSourceList, triggerPlugins, getToolIcon, strategyProviders, getCheckData, t, map, modelProviders])
|
||||
}, [nodes, edges, shouldCheckStartNode, nodesExtraData, buildInTools, customTools, workflowTools, language, dataSourceList, triggerPlugins, getToolIcon, strategyProviders, getCheckData, t, map, modelProviders, workflowStore])
|
||||
|
||||
return needWarningNodes
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@ type Props = {
|
||||
operations?: React.JSX.Element
|
||||
inline?: boolean
|
||||
required?: boolean
|
||||
warningDot?: boolean
|
||||
}
|
||||
|
||||
const Field: FC<Props> = ({
|
||||
@ -30,6 +31,7 @@ const Field: FC<Props> = ({
|
||||
inline,
|
||||
supportFold,
|
||||
required,
|
||||
warningDot,
|
||||
}) => {
|
||||
const [fold, {
|
||||
toggle: toggleFold,
|
||||
@ -41,7 +43,10 @@ const Field: FC<Props> = ({
|
||||
className={cn('flex items-center justify-between', supportFold && 'cursor-pointer')}
|
||||
>
|
||||
<div className="flex h-6 items-center">
|
||||
<div className={cn(isSubTitle ? 'system-xs-medium-uppercase text-text-tertiary' : 'system-sm-semibold-uppercase text-text-secondary')}>
|
||||
<div className={cn('relative', isSubTitle ? 'text-text-tertiary system-xs-medium-uppercase' : 'text-text-secondary system-sm-semibold-uppercase')}>
|
||||
{warningDot && (
|
||||
<span className="absolute -left-[9px] top-1/2 size-[5px] -translate-y-1/2 rounded-full bg-text-warning-secondary" />
|
||||
)}
|
||||
{title}
|
||||
{' '}
|
||||
{required && <span className="text-text-destructive">*</span>}
|
||||
|
||||
@ -15,6 +15,7 @@ import OutputVars, { VarItem } from '@/app/components/workflow/nodes/_base/compo
|
||||
import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor'
|
||||
import Split from '@/app/components/workflow/nodes/_base/components/split'
|
||||
import VarList from '@/app/components/workflow/nodes/_base/components/variable/var-list'
|
||||
import { useStore } from '@/app/components/workflow/store'
|
||||
import { fetchAndMergeValidCompletionParams } from '@/utils/completion-params'
|
||||
import ConfigVision from '../_base/components/config-vision'
|
||||
import MemoryConfig from '../_base/components/memory-config'
|
||||
@ -31,6 +32,7 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
|
||||
data,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const hasChecklistWarning = useStore(s => s.checklistItems.some(item => item.id === id))
|
||||
const {
|
||||
readOnly,
|
||||
inputs,
|
||||
@ -102,6 +104,7 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
|
||||
<Field
|
||||
title={t(`${i18nPrefix}.model`, { ns: 'workflow' })}
|
||||
required
|
||||
warningDot={hasChecklistWarning}
|
||||
>
|
||||
<ModelParameterModal
|
||||
popupClassName="!w-[387px]"
|
||||
@ -264,8 +267,8 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
|
||||
noDecoration
|
||||
popupContent={(
|
||||
<div className="w-[232px] rounded-xl border-[0.5px] border-components-panel-border bg-components-tooltip-bg px-4 py-3.5 shadow-lg backdrop-blur-[5px]">
|
||||
<div className="title-xs-semi-bold text-text-primary">{t('structOutput.modelNotSupported', { ns: 'app' })}</div>
|
||||
<div className="body-xs-regular mt-1 text-text-secondary">{t('structOutput.modelNotSupportedTip', { ns: 'app' })}</div>
|
||||
<div className="text-text-primary title-xs-semi-bold">{t('structOutput.modelNotSupported', { ns: 'app' })}</div>
|
||||
<div className="mt-1 text-text-secondary body-xs-regular">{t('structOutput.modelNotSupportedTip', { ns: 'app' })}</div>
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
@ -274,7 +277,7 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
<div className="system-xs-medium-uppercase mr-0.5 text-text-tertiary">{t('structOutput.structured', { ns: 'app' })}</div>
|
||||
<div className="mr-0.5 text-text-tertiary system-xs-medium-uppercase">{t('structOutput.structured', { ns: 'app' })}</div>
|
||||
<Tooltip popupContent={
|
||||
<div className="max-w-[150px]">{t('structOutput.structuredTip', { ns: 'app' })}</div>
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import type { StateCreator } from 'zustand'
|
||||
import type { ChecklistItem } from '@/app/components/workflow/hooks/use-checklist'
|
||||
import type {
|
||||
VariableAssignerNodeType,
|
||||
} from '@/app/components/workflow/nodes/variable-assigner/types'
|
||||
@ -10,6 +11,7 @@ import type {
|
||||
} from '@/types/workflow'
|
||||
|
||||
export type NodeSliceShape = {
|
||||
checklistItems: ChecklistItem[]
|
||||
showSingleRunPanel: boolean
|
||||
setShowSingleRunPanel: (showSingleRunPanel: boolean) => void
|
||||
nodeAnimation: boolean
|
||||
@ -56,6 +58,7 @@ export type NodeSliceShape = {
|
||||
}
|
||||
|
||||
export const createNodeSlice: StateCreator<NodeSliceShape> = set => ({
|
||||
checklistItems: [],
|
||||
showSingleRunPanel: false,
|
||||
setShowSingleRunPanel: showSingleRunPanel => set(() => ({ showSingleRunPanel })),
|
||||
nodeAnimation: false,
|
||||
|
||||
@ -6678,9 +6678,6 @@
|
||||
"app/components/workflow/nodes/_base/components/field.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"tailwindcss/enforce-consistent-class-order": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/_base/components/file-type-item.tsx": {
|
||||
@ -7937,9 +7934,6 @@
|
||||
"app/components/workflow/nodes/llm/panel.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"tailwindcss/enforce-consistent-class-order": {
|
||||
"count": 3
|
||||
}
|
||||
},
|
||||
"app/components/workflow/nodes/llm/use-config.ts": {
|
||||
|
||||
Reference in New Issue
Block a user