mirror of
https://github.com/langgenius/dify.git
synced 2026-05-09 21:28:25 +08:00
refactor(web): migrate legacy tooltip callers
This commit is contained in:
parent
140ad6ba4e
commit
02e51e3b4a
@ -1,14 +1,14 @@
|
||||
'use client'
|
||||
import type { AccessControlAccount, AccessControlGroup } from '@/models/access-control'
|
||||
import { Avatar } from '@langgenius/dify-ui/avatar'
|
||||
import { RiAlertFill, RiCloseCircleFill, RiLockLine, RiOrganizationChart } from '@remixicon/react'
|
||||
import { RiCloseCircleFill, RiLockLine, RiOrganizationChart } from '@remixicon/react'
|
||||
import { useCallback, useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { AccessMode } from '@/models/access-control'
|
||||
import { useAppWhiteListSubjects } from '@/service/access-control'
|
||||
import useAccessControlStore from '../../../../context/access-control-store'
|
||||
import { Infotip } from '../../base/infotip'
|
||||
import Loading from '../../base/loading'
|
||||
import Tooltip from '../../base/tooltip'
|
||||
import AddMemberOrGroupDialog from './add-member-or-group-pop'
|
||||
|
||||
export default function SpecificGroupsOrMembers() {
|
||||
@ -137,9 +137,14 @@ function BaseItem({ icon, onRemove, children }: BaseItemProps) {
|
||||
|
||||
export function WebAppSSONotEnabledTip() {
|
||||
const { t } = useTranslation()
|
||||
const tip = t('accessControlDialog.webAppSSONotEnabledTip', { ns: 'app' })
|
||||
|
||||
return (
|
||||
<Tooltip asChild={false} popupContent={t('accessControlDialog.webAppSSONotEnabledTip', { ns: 'app' })}>
|
||||
<RiAlertFill className="h-4 w-4 shrink-0 text-text-warning-secondary" />
|
||||
</Tooltip>
|
||||
<Infotip
|
||||
aria-label={tip}
|
||||
iconClassName="h-4 w-4 shrink-0 text-text-warning-secondary hover:text-text-warning-secondary"
|
||||
>
|
||||
{tip}
|
||||
</Infotip>
|
||||
)
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ import { useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { ReactSortable } from 'react-sortablejs'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import { InputVarType } from '@/app/components/workflow/types'
|
||||
import ConfigContext from '@/context/debug-configuration'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
@ -257,13 +257,9 @@ const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVar
|
||||
<div className="flex items-center">
|
||||
<div className="mr-1">{t('variableTitle', { ns: 'appDebug' })}</div>
|
||||
{!readonly && (
|
||||
<Tooltip
|
||||
popupContent={(
|
||||
<div className="w-[180px]">
|
||||
{t('variableTip', { ns: 'appDebug' })}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<Infotip aria-label={t('variableTip', { ns: 'appDebug' })} popupClassName="w-[180px]">
|
||||
{t('variableTip', { ns: 'appDebug' })}
|
||||
</Infotip>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
import type { FC } from 'react'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import * as React from 'react'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
|
||||
type Props = {
|
||||
className?: string
|
||||
@ -24,14 +24,9 @@ const ItemPanel: FC<Props> = ({
|
||||
<div className="flex items-center">
|
||||
{icon}
|
||||
<div className="mr-1 ml-3 text-sm leading-6 font-semibold text-text-secondary">{name}</div>
|
||||
<Tooltip
|
||||
popupContent={(
|
||||
<div className="w-[180px]">
|
||||
{description}
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
</Tooltip>
|
||||
<Infotip aria-label={description} popupClassName="w-[180px]">
|
||||
{description}
|
||||
</Infotip>
|
||||
</div>
|
||||
<div>
|
||||
{children}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { RiCloseLine, RiPlayLargeLine } from '@remixicon/react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useStore } from '@/app/components/app/store'
|
||||
import TooltipPlus from '@/app/components/base/tooltip'
|
||||
import { WorkflowContextProvider } from '@/app/components/workflow/context'
|
||||
import Run from '@/app/components/workflow/run'
|
||||
import { useRouter } from '@/next/navigation'
|
||||
@ -33,19 +33,23 @@ const DetailPanel: FC<ILogDetail> = ({ runID, onClose, canReplay = false }) => {
|
||||
<div className="flex items-center bg-components-panel-bg">
|
||||
<h1 className="shrink-0 px-4 py-1 system-xl-semibold text-text-primary">{t('runDetail.workflowTitle', { ns: 'appLog' })}</h1>
|
||||
{canReplay && (
|
||||
<TooltipPlus
|
||||
popupContent={t('runDetail.testWithParams', { ns: 'appLog' })}
|
||||
popupClassName="rounded-xl"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="mr-1 flex h-6 w-6 items-center justify-center rounded-md hover:bg-state-base-hover"
|
||||
aria-label={t('runDetail.testWithParams', { ns: 'appLog' })}
|
||||
onClick={handleReplay}
|
||||
>
|
||||
<RiPlayLargeLine className="h-4 w-4 text-text-tertiary" />
|
||||
</button>
|
||||
</TooltipPlus>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<button
|
||||
type="button"
|
||||
className="mr-1 flex h-6 w-6 items-center justify-center rounded-md hover:bg-state-base-hover"
|
||||
aria-label={t('runDetail.testWithParams', { ns: 'appLog' })}
|
||||
onClick={handleReplay}
|
||||
>
|
||||
<RiPlayLargeLine className="h-4 w-4 text-text-tertiary" />
|
||||
</button>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent className="rounded-xl">
|
||||
{t('runDetail.testWithParams', { ns: 'appLog' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
<WorkflowContextProvider>
|
||||
|
||||
@ -23,14 +23,10 @@ const ProgressTooltip: FC<ProgressTooltipProps> = ({
|
||||
onOpenChange={setOpen}
|
||||
>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div
|
||||
data-testid="progress-trigger-content"
|
||||
className="flex grow items-center"
|
||||
onMouseEnter={() => setOpen(true)}
|
||||
onMouseLeave={() => setOpen(false)}
|
||||
/>
|
||||
)}
|
||||
data-testid="progress-trigger-content"
|
||||
className="flex grow items-center border-0 bg-transparent p-0 text-left"
|
||||
onMouseEnter={() => setOpen(true)}
|
||||
onMouseLeave={() => setOpen(false)}
|
||||
>
|
||||
<div className="mr-1 h-1.5 w-16 overflow-hidden rounded-[3px] border border-components-progress-gray-border">
|
||||
<div
|
||||
@ -45,7 +41,6 @@ const ProgressTooltip: FC<ProgressTooltipProps> = ({
|
||||
<TooltipContent
|
||||
data-testid="progress-tooltip-popup"
|
||||
placement="top-start"
|
||||
sideOffset={0}
|
||||
className="rounded-lg bg-components-tooltip-bg p-3 system-xs-medium text-text-quaternary shadow-lg"
|
||||
>
|
||||
{t('chat.citation.hitScore', { ns: 'common' })}
|
||||
|
||||
@ -26,14 +26,10 @@ const Tooltip: FC<TooltipProps> = ({
|
||||
onOpenChange={setOpen}
|
||||
>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div
|
||||
data-testid="tooltip-trigger-content"
|
||||
className="mr-6 flex items-center"
|
||||
onMouseEnter={() => setOpen(true)}
|
||||
onMouseLeave={() => setOpen(false)}
|
||||
/>
|
||||
)}
|
||||
data-testid="tooltip-trigger-content"
|
||||
className="mr-6 flex items-center border-0 bg-transparent p-0 text-left"
|
||||
onMouseEnter={() => setOpen(true)}
|
||||
onMouseLeave={() => setOpen(false)}
|
||||
>
|
||||
{icon}
|
||||
{data}
|
||||
@ -41,7 +37,6 @@ const Tooltip: FC<TooltipProps> = ({
|
||||
<TooltipContent
|
||||
data-testid="tooltip-popup"
|
||||
placement="top-start"
|
||||
sideOffset={0}
|
||||
className="rounded-lg bg-components-tooltip-bg p-3 system-xs-medium text-text-quaternary shadow-lg"
|
||||
>
|
||||
{text}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
'use client'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useClipboard } from '@/hooks/use-clipboard'
|
||||
import Tooltip from '../tooltip'
|
||||
|
||||
type Props = {
|
||||
content: string
|
||||
@ -25,14 +25,25 @@ const CopyIcon = ({ content }: Props) => {
|
||||
const safeTooltipText = tooltipText || ''
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
popupContent={safeTooltipText}
|
||||
>
|
||||
<div onMouseLeave={reset}>
|
||||
{!copied
|
||||
? (<span className="mx-1 i-custom-vender-line-files-copy h-3.5 w-3.5 cursor-pointer text-text-tertiary" onClick={handleCopy} data-testid="copy-icon" />)
|
||||
: (<span className="mx-1 i-custom-vender-line-files-copy-check h-3.5 w-3.5 text-text-tertiary" data-testid="copied-icon" />)}
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<button
|
||||
type="button"
|
||||
aria-label={safeTooltipText}
|
||||
className="mx-1 inline-flex h-3.5 w-3.5 cursor-pointer border-0 bg-transparent p-0 text-text-tertiary"
|
||||
onClick={handleCopy}
|
||||
onMouseLeave={reset}
|
||||
>
|
||||
{!copied
|
||||
? (<span aria-hidden className="i-custom-vender-line-files-copy h-3.5 w-3.5" data-testid="copy-icon" />)
|
||||
: (<span aria-hidden className="i-custom-vender-line-files-copy-check h-3.5 w-3.5" data-testid="copied-icon" />)}
|
||||
</button>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{safeTooltipText}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import * as React from 'react'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
|
||||
export const Item: FC<{ title: string, tooltip: string, children: React.JSX.Element }> = ({
|
||||
title,
|
||||
@ -12,11 +12,9 @@ export const Item: FC<{ title: string, tooltip: string, children: React.JSX.Elem
|
||||
<div>
|
||||
<div className="mb-1 flex items-center space-x-1">
|
||||
<div className="py-1 system-sm-semibold text-text-secondary">{title}</div>
|
||||
<Tooltip
|
||||
popupContent={
|
||||
<div className="max-w-[200px] system-sm-regular text-text-secondary">{tooltip}</div>
|
||||
}
|
||||
/>
|
||||
<Infotip aria-label={tooltip} popupClassName="max-w-[200px] system-sm-regular text-text-secondary">
|
||||
{tooltip}
|
||||
</Infotip>
|
||||
</div>
|
||||
<div>{children}</div>
|
||||
</div>
|
||||
|
||||
@ -10,7 +10,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import { replace } from 'string-ts'
|
||||
import AudioBtn from '@/app/components/base/audio-btn'
|
||||
import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import { languages } from '@/i18n-config/language'
|
||||
import { usePathname } from '@/next/navigation'
|
||||
import { useAppVoices } from '@/service/use-apps'
|
||||
@ -89,17 +89,16 @@ const VoiceParamConfig = ({
|
||||
<div className="mb-3">
|
||||
<div className="mb-1 flex items-center py-1 system-sm-semibold text-text-secondary">
|
||||
{t('voice.voiceSettings.language', { ns: 'appDebug' })}
|
||||
<Tooltip
|
||||
popupContent={(
|
||||
<div className="w-[180px]">
|
||||
{t('voice.voiceSettings.resolutionTooltip', { ns: 'appDebug' }).split('\n').map(item => (
|
||||
<div key={item}>
|
||||
{item}
|
||||
</div>
|
||||
))}
|
||||
<Infotip
|
||||
aria-label={t('voice.voiceSettings.resolutionTooltip', { ns: 'appDebug' })}
|
||||
popupClassName="w-[180px]"
|
||||
>
|
||||
{t('voice.voiceSettings.resolutionTooltip', { ns: 'appDebug' }).split('\n').map(item => (
|
||||
<div key={item}>
|
||||
{item}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
))}
|
||||
</Infotip>
|
||||
</div>
|
||||
<Listbox
|
||||
value={languageItem}
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import type { VariantProps } from 'class-variance-authority'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { cva } from 'class-variance-authority'
|
||||
import * as React from 'react'
|
||||
import { useCallback } from 'react'
|
||||
import { FileTypeIcon } from '../file-uploader'
|
||||
import { getFileAppearanceType } from '../file-uploader/utils'
|
||||
import Tooltip from '../tooltip'
|
||||
import ImageRender from './image-render'
|
||||
|
||||
const FileThumbVariants = cva(
|
||||
@ -46,43 +46,49 @@ const FileThumb = ({
|
||||
const { name, mimeType, sourceUrl } = file
|
||||
const isImage = mimeType.startsWith('image/')
|
||||
|
||||
const handleClick = useCallback((e: React.MouseEvent<HTMLDivElement>) => {
|
||||
const handleClick = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
onClick?.(file)
|
||||
}, [onClick, file])
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
popupContent={name}
|
||||
popupClassName="p-1.5 rounded-lg system-xs-medium text-text-secondary"
|
||||
position="top"
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
FileThumbVariants({ size, className }),
|
||||
isImage
|
||||
? 'p-px'
|
||||
: 'rounded-md border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg shadow-xs hover:bg-components-panel-on-panel-item-bg-alt',
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<button
|
||||
type="button"
|
||||
aria-label={name}
|
||||
className={cn(
|
||||
FileThumbVariants({ size, className }),
|
||||
'border-0 bg-transparent p-0',
|
||||
isImage
|
||||
? 'p-px'
|
||||
: 'rounded-md border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg shadow-xs hover:bg-components-panel-on-panel-item-bg-alt',
|
||||
)}
|
||||
onClick={handleClick}
|
||||
>
|
||||
{
|
||||
isImage
|
||||
? (
|
||||
<ImageRender
|
||||
sourceUrl={sourceUrl}
|
||||
name={name}
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<FileTypeIcon
|
||||
type={getFileAppearanceType(name, mimeType)}
|
||||
size="sm"
|
||||
/>
|
||||
)
|
||||
}
|
||||
</button>
|
||||
)}
|
||||
onClick={handleClick}
|
||||
>
|
||||
{
|
||||
isImage
|
||||
? (
|
||||
<ImageRender
|
||||
sourceUrl={sourceUrl}
|
||||
name={name}
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<FileTypeIcon
|
||||
type={getFileAppearanceType(name, mimeType)}
|
||||
size="sm"
|
||||
/>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
/>
|
||||
<TooltipContent placement="top" className="rounded-lg p-1.5 system-xs-medium text-text-secondary">
|
||||
{name}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Tooltip from '../../tooltip'
|
||||
import { Infotip } from '../../infotip'
|
||||
|
||||
export type LabelProps = {
|
||||
htmlFor: string
|
||||
@ -33,13 +33,9 @@ const Label = ({
|
||||
{!isRequired && showOptional && <div className="ml-1 system-xs-regular text-text-tertiary">{t('label.optional', { ns: 'common' })}</div>}
|
||||
{isRequired && <div className="ml-1 system-xs-regular text-text-destructive-secondary">*</div>}
|
||||
{tooltip && (
|
||||
<Tooltip
|
||||
popupContent={
|
||||
<div className="w-[200px]">{tooltip}</div>
|
||||
}
|
||||
triggerClassName="ml-0.5 w-4 h-4"
|
||||
triggerTestId={`${htmlFor}-tooltip`}
|
||||
/>
|
||||
<Infotip aria-label={tooltip} className="ml-0.5 h-4 w-4" popupClassName="w-[200px]">
|
||||
{tooltip}
|
||||
</Infotip>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
'use client'
|
||||
import type { InputProps } from '../input'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useClipboard } from '@/hooks/use-clipboard'
|
||||
import ActionButton from '../action-button'
|
||||
import Tooltip from '../tooltip'
|
||||
|
||||
type InputWithCopyProps = {
|
||||
showCopyButton?: boolean
|
||||
@ -64,18 +64,24 @@ const InputWithCopy = React.forwardRef<HTMLInputElement, InputWithCopyProps>((
|
||||
onMouseLeave={reset}
|
||||
data-testid="copy-button-wrapper"
|
||||
>
|
||||
<Tooltip
|
||||
popupContent={safeTooltipText}
|
||||
>
|
||||
<ActionButton
|
||||
size="xs"
|
||||
onClick={handleCopy}
|
||||
className="hover:bg-components-button-ghost-bg-hover"
|
||||
>
|
||||
{copied
|
||||
? (<span className="i-ri-clipboard-fill h-3.5 w-3.5 text-text-tertiary" data-testid="copied-icon" />)
|
||||
: (<span className="i-ri-clipboard-line h-3.5 w-3.5 text-text-tertiary" data-testid="copy-icon" />)}
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton
|
||||
size="xs"
|
||||
aria-label={safeTooltipText}
|
||||
onClick={handleCopy}
|
||||
className="hover:bg-components-button-ghost-bg-hover"
|
||||
>
|
||||
{copied
|
||||
? (<span className="i-ri-clipboard-fill h-3.5 w-3.5 text-text-tertiary" data-testid="copied-icon" />)
|
||||
: (<span className="i-ri-clipboard-line h-3.5 w-3.5 text-text-tertiary" data-testid="copy-icon" />)}
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{safeTooltipText}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
|
||||
import { RiInfoI } from '@remixicon/react'
|
||||
import * as React from 'react'
|
||||
|
||||
@ -11,14 +12,20 @@ const Tooltip = ({
|
||||
if (!content)
|
||||
return null
|
||||
return (
|
||||
<div className="group relative z-10 size-[18px] overflow-visible">
|
||||
<div className="absolute right-0 bottom-0 -z-10 hidden w-[260px] bg-saas-dify-blue-static px-5 py-[18px] system-xs-regular text-text-primary-on-surface group-hover:block">
|
||||
{content}
|
||||
</div>
|
||||
<div className="flex h-full w-full items-center justify-center rounded-sm bg-state-base-hover transition-all duration-500 ease-in-out group-hover:rounded-none group-hover:bg-saas-dify-blue-static">
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
openOnHover
|
||||
delay={0}
|
||||
closeDelay={0}
|
||||
aria-label={content}
|
||||
className="group relative z-10 flex size-[18px] items-center justify-center rounded-sm border-0 bg-state-base-hover p-0 transition-[border-radius,background-color] duration-500 ease-in-out hover:rounded-none hover:bg-saas-dify-blue-static"
|
||||
>
|
||||
<RiInfoI className="size-3.5 text-text-tertiary group-hover:text-text-primary-on-surface" data-testid="tooltip-icon" />
|
||||
</div>
|
||||
</div>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent placement="top-end" popupClassName="w-[260px] rounded-none border-0 bg-saas-dify-blue-static px-5 py-[18px] system-xs-regular text-text-primary-on-surface shadow-none">
|
||||
{content}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -16,15 +16,16 @@ import {
|
||||
DropdownMenuContent,
|
||||
DropdownMenuTrigger,
|
||||
} from '@langgenius/dify-ui/dropdown-menu'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
|
||||
import { Switch } from '@langgenius/dify-ui/switch'
|
||||
import { toast } from '@langgenius/dify-ui/toast'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { useBoolean, useDebounceFn } from 'ahooks'
|
||||
import { noop } from 'es-toolkit/function'
|
||||
import * as React from 'react'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { IS_CE_EDITION } from '@/config'
|
||||
import { DataSourceType, DocumentActionType } from '@/models/datasets'
|
||||
import { useRouter } from '@/next/navigation'
|
||||
@ -205,11 +206,12 @@ const Operations = ({ embeddingAvailable, datasetId, detail, selectedIds, onSele
|
||||
<>
|
||||
{archived
|
||||
? (
|
||||
<Tooltip popupContent={t('list.action.enableWarning', { ns: 'datasetDocuments' })} popupClassName="!font-semibold">
|
||||
<div>
|
||||
<Switch checked={false} onCheckedChange={noop} disabled={true} size="md" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
<Popover>
|
||||
<PopoverTrigger nativeButton={false} openOnHover render={<div><Switch checked={false} onCheckedChange={noop} disabled={true} size="md" /></div>} />
|
||||
<PopoverContent popupClassName="px-3 py-2 font-semibold system-xs-regular text-text-tertiary">
|
||||
{t('list.action.enableWarning', { ns: 'datasetDocuments' })}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)
|
||||
: <Switch checked={enabled} onCheckedChange={v => handleSwitch(v ? 'enable' : 'disable')} size="md" />}
|
||||
<Divider className="!mr-2 !ml-4 !h-3" type="vertical" />
|
||||
@ -217,16 +219,24 @@ const Operations = ({ embeddingAvailable, datasetId, detail, selectedIds, onSele
|
||||
)}
|
||||
{embeddingAvailable && (
|
||||
<>
|
||||
<Tooltip popupContent={t('list.action.settings', { ns: 'datasetDocuments' })} popupClassName="text-text-secondary system-xs-medium" needsDelay={false}>
|
||||
<button
|
||||
type="button"
|
||||
className={cn('mr-2 cursor-pointer rounded-lg', !isListScene
|
||||
? 'border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg p-2 shadow-xs shadow-shadow-shadow-3 backdrop-blur-[5px] hover:border-components-button-secondary-border-hover hover:bg-components-button-secondary-bg-hover'
|
||||
: 'p-0.5 hover:bg-state-base-hover')}
|
||||
onClick={() => router.push(`/datasets/${datasetId}/documents/${detail.id}/settings`)}
|
||||
>
|
||||
<span aria-hidden className="i-ri-equalizer-2-line h-4 w-4 text-components-button-secondary-text" />
|
||||
</button>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<button
|
||||
type="button"
|
||||
aria-label={t('list.action.settings', { ns: 'datasetDocuments' })}
|
||||
className={cn('mr-2 cursor-pointer rounded-lg', !isListScene
|
||||
? 'border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg p-2 shadow-xs shadow-shadow-shadow-3 backdrop-blur-[5px] hover:border-components-button-secondary-border-hover hover:bg-components-button-secondary-bg-hover'
|
||||
: 'p-0.5 hover:bg-state-base-hover')}
|
||||
onClick={() => router.push(`/datasets/${datasetId}/documents/${detail.id}/settings`)}
|
||||
>
|
||||
<span aria-hidden className="i-ri-equalizer-2-line h-4 w-4 text-components-button-secondary-text" />
|
||||
</button>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent className="system-xs-medium text-text-secondary">
|
||||
{t('list.action.settings', { ns: 'datasetDocuments' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<DropdownMenu open={isOperationsMenuOpen} onOpenChange={setIsOperationsMenuOpen}>
|
||||
<DropdownMenuTrigger
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
import type { Placement } from '@floating-ui/react'
|
||||
import type { OnlineDriveFile } from '@/models/pipeline'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
|
||||
import * as React from 'react'
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Checkbox from '@/app/components/base/checkbox'
|
||||
import Radio from '@/app/components/base/radio/ui'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { formatFileSize } from '@/utils/format'
|
||||
import FileIcon from './file-icon'
|
||||
|
||||
@ -33,14 +31,7 @@ const Item = ({
|
||||
const isBucket = type === 'bucket'
|
||||
const isFolder = type === 'folder'
|
||||
|
||||
const Wrapper = disabled ? Tooltip : React.Fragment
|
||||
const wrapperProps = disabled
|
||||
? {
|
||||
popupContent: t('onlineDrive.notSupportedFileType', { ns: 'datasetPipeline' }),
|
||||
position: 'top-end' as Placement,
|
||||
offset: { mainAxis: 4, crossAxis: -104 },
|
||||
}
|
||||
: {}
|
||||
const disabledTip = t('onlineDrive.notSupportedFileType', { ns: 'datasetPipeline' })
|
||||
|
||||
const handleSelect = useCallback((e: React.MouseEvent<HTMLDivElement> | React.KeyboardEvent<HTMLDivElement>) => {
|
||||
e.stopPropagation()
|
||||
@ -80,27 +71,44 @@ const Item = ({
|
||||
onCheck={handleSelect}
|
||||
/>
|
||||
)}
|
||||
<Wrapper
|
||||
{...wrapperProps}
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
'flex grow items-center gap-x-1 overflow-hidden py-0.5',
|
||||
disabled && 'opacity-30',
|
||||
{disabled
|
||||
? (
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
openOnHover
|
||||
aria-label={disabledTip}
|
||||
className="flex grow items-center gap-x-1 overflow-hidden border-0 bg-transparent p-0 py-0.5 text-left opacity-30"
|
||||
>
|
||||
<FileIcon type={type} fileName={name} className="shrink-0 transform-gpu" />
|
||||
<span
|
||||
className="grow truncate system-sm-medium text-text-secondary"
|
||||
title={name}
|
||||
>
|
||||
{name}
|
||||
</span>
|
||||
{!isFolder && typeof size === 'number' && (
|
||||
<span className="shrink-0 system-xs-regular text-text-tertiary">{formatFileSize(size)}</span>
|
||||
)}
|
||||
</PopoverTrigger>
|
||||
<PopoverContent placement="top-end" popupClassName="px-3 py-2 system-xs-regular text-text-tertiary">
|
||||
{disabledTip}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)
|
||||
: (
|
||||
<div className="flex grow items-center gap-x-1 overflow-hidden py-0.5">
|
||||
<FileIcon type={type} fileName={name} className="shrink-0 transform-gpu" />
|
||||
<span
|
||||
className="grow truncate system-sm-medium text-text-secondary"
|
||||
title={name}
|
||||
>
|
||||
{name}
|
||||
</span>
|
||||
{!isFolder && typeof size === 'number' && (
|
||||
<span className="shrink-0 system-xs-regular text-text-tertiary">{formatFileSize(size)}</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<FileIcon type={type} fileName={name} className="shrink-0 transform-gpu" />
|
||||
<span
|
||||
className="grow truncate system-sm-medium text-text-secondary"
|
||||
title={name}
|
||||
>
|
||||
{name}
|
||||
</span>
|
||||
{!isFolder && typeof size === 'number' && (
|
||||
<span className="shrink-0 system-xs-regular text-text-tertiary">{formatFileSize(size)}</span>
|
||||
)}
|
||||
</div>
|
||||
</Wrapper>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import type { InitialDocumentDetail } from '@/models/pipeline'
|
||||
import type { RETRIEVE_METHOD } from '@/types/app'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
|
||||
import {
|
||||
RiAedFill,
|
||||
RiArrowRightLine,
|
||||
@ -17,7 +18,6 @@ import { useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import NotionIcon from '@/app/components/base/notion-icon'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import PriorityLabel from '@/app/components/billing/priority-label'
|
||||
import { Plan } from '@/app/components/billing/type'
|
||||
import UpgradeBtn from '@/app/components/billing/upgrade-btn'
|
||||
@ -203,15 +203,18 @@ const EmbeddingProcess = ({
|
||||
<div className="shrink-0 text-xs text-text-secondary">{`${getSourcePercent(indexingStatusDetail)}%`}</div>
|
||||
)}
|
||||
{indexingStatusDetail.indexing_status === 'error' && (
|
||||
<Tooltip
|
||||
popupClassName="px-4 py-[14px] max-w-60 body-xs-regular text-text-secondary border-[0.5px] border-components-panel-border rounded-xl"
|
||||
offset={4}
|
||||
popupContent={indexingStatusDetail.error}
|
||||
>
|
||||
<span>
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
openOnHover
|
||||
aria-label={indexingStatusDetail.error}
|
||||
className="inline-flex border-0 bg-transparent p-0"
|
||||
>
|
||||
<RiErrorWarningFill className="size-4 shrink-0 text-text-destructive" />
|
||||
</span>
|
||||
</Tooltip>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent popupClassName="max-w-60 rounded-xl border-[0.5px] border-components-panel-border px-4 py-[14px] body-xs-regular text-text-secondary">
|
||||
{indexingStatusDetail.error}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)}
|
||||
{indexingStatusDetail.indexing_status === 'completed' && (
|
||||
<RiCheckboxCircleFill className="size-4 shrink-0 text-text-success" />
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import type { FC } from 'react'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { RiLineHeight } from '@remixicon/react'
|
||||
import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Collapse } from '@/app/components/base/icons/src/vender/knowledge'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
|
||||
type DisplayToggleProps = {
|
||||
isCollapsed: boolean
|
||||
@ -15,25 +15,30 @@ const DisplayToggle: FC<DisplayToggleProps> = ({
|
||||
toggleCollapsed,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const label = isCollapsed ? t('segment.expandChunks', { ns: 'datasetDocuments' }) : t('segment.collapseChunks', { ns: 'datasetDocuments' })
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
popupContent={isCollapsed ? t('segment.expandChunks', { ns: 'datasetDocuments' }) : t('segment.collapseChunks', { ns: 'datasetDocuments' })}
|
||||
popupClassName="text-text-secondary system-xs-medium border-[0.5px] border-components-panel-border"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="flex items-center justify-center rounded-lg border-[0.5px] border-components-button-secondary-border
|
||||
bg-components-button-secondary-bg p-2 shadow-xs shadow-shadow-shadow-3 backdrop-blur-[5px]"
|
||||
onClick={toggleCollapsed}
|
||||
>
|
||||
{
|
||||
isCollapsed
|
||||
? <RiLineHeight className="h-4 w-4 text-components-button-secondary-text" />
|
||||
: <Collapse className="h-4 w-4 text-components-button-secondary-text" />
|
||||
}
|
||||
</button>
|
||||
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<button
|
||||
type="button"
|
||||
aria-label={label}
|
||||
className="flex items-center justify-center rounded-lg border-[0.5px] border-components-button-secondary-border
|
||||
bg-components-button-secondary-bg p-2 shadow-xs shadow-shadow-shadow-3 backdrop-blur-[5px]"
|
||||
onClick={toggleCollapsed}
|
||||
>
|
||||
{
|
||||
isCollapsed
|
||||
? <RiLineHeight className="h-4 w-4 text-components-button-secondary-text" />
|
||||
: <Collapse className="h-4 w-4 text-components-button-secondary-text" />
|
||||
}
|
||||
</button>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent className="border-[0.5px] border-components-panel-border system-xs-medium text-text-secondary">
|
||||
{label}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@ -10,13 +10,13 @@ import {
|
||||
} from '@langgenius/dify-ui/alert-dialog'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Switch } from '@langgenius/dify-ui/switch'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { RiDeleteBinLine, RiEditLine } from '@remixicon/react'
|
||||
import * as React from 'react'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import ImageList from '@/app/components/datasets/common/image-list'
|
||||
import { ChunkingMode } from '@/models/datasets'
|
||||
import { formatNumber } from '@/utils/format'
|
||||
@ -182,35 +182,43 @@ const SegmentCard: FC<ISegmentCardProps> = ({
|
||||
>
|
||||
{!archived && (
|
||||
<>
|
||||
<Tooltip
|
||||
popupContent="Edit"
|
||||
popupClassName="text-text-secondary system-xs-medium"
|
||||
>
|
||||
<div
|
||||
data-testid="segment-edit-button"
|
||||
className="flex h-6 w-6 shrink-0 cursor-pointer items-center justify-center rounded-lg hover:bg-state-base-hover"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
onClickEdit?.()
|
||||
}}
|
||||
>
|
||||
<RiEditLine className="h-4 w-4 text-text-tertiary" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Edit"
|
||||
data-testid="segment-edit-button"
|
||||
className="flex h-6 w-6 shrink-0 cursor-pointer items-center justify-center rounded-lg hover:bg-state-base-hover"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
onClickEdit?.()
|
||||
}}
|
||||
>
|
||||
<RiEditLine className="h-4 w-4 text-text-tertiary" />
|
||||
</button>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent className="system-xs-medium text-text-secondary">Edit</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
popupContent="Delete"
|
||||
popupClassName="text-text-secondary system-xs-medium"
|
||||
>
|
||||
<div
|
||||
data-testid="segment-delete-button"
|
||||
className="group/delete flex h-6 w-6 shrink-0 cursor-pointer items-center justify-center rounded-lg hover:bg-state-destructive-hover"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setShowModal(true)
|
||||
}}
|
||||
>
|
||||
<RiDeleteBinLine className="h-4 w-4 text-text-tertiary group-hover/delete:text-text-destructive" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Delete"
|
||||
data-testid="segment-delete-button"
|
||||
className="group/delete flex h-6 w-6 shrink-0 cursor-pointer items-center justify-center rounded-lg hover:bg-state-destructive-hover"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setShowModal(true)
|
||||
}}
|
||||
>
|
||||
<RiDeleteBinLine className="h-4 w-4 text-text-tertiary group-hover/delete:text-text-destructive" />
|
||||
</button>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent className="system-xs-medium text-text-secondary">Delete</TooltipContent>
|
||||
</Tooltip>
|
||||
<Divider type="vertical" className="h-3.5 bg-divider-regular" />
|
||||
</>
|
||||
|
||||
@ -3,7 +3,6 @@ import type { FC } from 'react'
|
||||
import type { BuiltInMetadataItem, MetadataItemInBatchEdit, MetadataItemWithEdit } from '../types'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { toast } from '@langgenius/dify-ui/toast'
|
||||
import { RiQuestionLine } from '@remixicon/react'
|
||||
import { produce } from 'immer'
|
||||
import * as React from 'react'
|
||||
import { useCallback, useState } from 'react'
|
||||
@ -11,8 +10,8 @@ import { useTranslation } from 'react-i18next'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import { useCreateMetaData } from '@/service/knowledge/use-metadata'
|
||||
import Checkbox from '../../../base/checkbox'
|
||||
import { Infotip } from '../../../base/infotip'
|
||||
import Modal from '../../../base/modal'
|
||||
import Tooltip from '../../../base/tooltip'
|
||||
import AddMetadataButton from '../add-metadata-button'
|
||||
import useCheckMetadataName from '../hooks/use-check-metadata-name'
|
||||
import SelectMetadataModal from '../metadata-dataset/select-metadata-modal'
|
||||
@ -115,11 +114,14 @@ const EditMetadataBatchModal: FC<Props> = ({ datasetId, documentNum, list, onSav
|
||||
<div className="flex items-center select-none">
|
||||
<Checkbox checked={isApplyToAllSelectDocument} onCheck={() => setIsApplyToAllSelectDocument(!isApplyToAllSelectDocument)} id="apply-to-all" />
|
||||
<div className="mr-1 ml-2 system-xs-medium text-text-secondary">{t(`${i18nPrefix}.applyToAllSelectDocument`, { ns: 'dataset' })}</div>
|
||||
<Tooltip popupContent={<div className="max-w-[240px]">{t(`${i18nPrefix}.applyToAllSelectDocumentTip`, { ns: 'dataset' })}</div>}>
|
||||
<div className="cursor-pointer p-px">
|
||||
<RiQuestionLine className="size-3.5 text-text-tertiary" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
<Infotip
|
||||
aria-label={t(`${i18nPrefix}.applyToAllSelectDocumentTip`, { ns: 'dataset' })}
|
||||
className="p-px"
|
||||
iconClassName="size-3.5 text-text-tertiary"
|
||||
popupClassName="max-w-[240px]"
|
||||
>
|
||||
{t(`${i18nPrefix}.applyToAllSelectDocumentTip`, { ns: 'dataset' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Button onClick={onHide}>
|
||||
|
||||
@ -20,9 +20,9 @@ import * as React from 'react'
|
||||
import { useCallback, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Drawer from '@/app/components/base/drawer'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import Input from '@/app/components/base/input'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import CreateModal from '@/app/components/datasets/metadata/metadata-dataset/create-metadata-modal'
|
||||
import { getIcon } from '../utils/get-icon'
|
||||
import Field from './field'
|
||||
@ -215,7 +215,9 @@ const DatasetMetadataDrawer: FC<Props> = ({
|
||||
onCheckedChange={onIsBuiltInEnabledChange}
|
||||
/>
|
||||
<div className="mr-0.5 ml-2 system-sm-semibold text-text-secondary">{t(`${i18nPrefix}.builtIn`, { ns: 'dataset' })}</div>
|
||||
<Tooltip popupContent={<div className="max-w-[100px]">{t(`${i18nPrefix}.builtInDescription`, { ns: 'dataset' })}</div>} />
|
||||
<Infotip aria-label={t(`${i18nPrefix}.builtInDescription`, { ns: 'dataset' })} popupClassName="max-w-[100px]">
|
||||
{t(`${i18nPrefix}.builtInDescription`, { ns: 'dataset' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
|
||||
<div className="mt-1 space-y-1">
|
||||
|
||||
@ -5,6 +5,7 @@ import type {
|
||||
import {
|
||||
Button,
|
||||
} from '@langgenius/dify-ui/button'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import {
|
||||
RiEqualizer2Line,
|
||||
} from '@remixicon/react'
|
||||
@ -13,7 +14,6 @@ import {
|
||||
useCallback,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { ConfigurationMethodEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import Authorized from './authorized'
|
||||
import { useCredentialStatus } from './hooks'
|
||||
@ -53,11 +53,11 @@ const ConfigProvider = ({
|
||||
)
|
||||
if (notAllowCustomCredential && !hasCredential) {
|
||||
return (
|
||||
<Tooltip
|
||||
asChild
|
||||
popupContent={t('auth.credentialUnavailable', { ns: 'plugin' })}
|
||||
>
|
||||
{Item}
|
||||
<Tooltip>
|
||||
<TooltipTrigger render={Item} />
|
||||
<TooltipContent>
|
||||
{t('auth.credentialUnavailable', { ns: 'plugin' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import type {
|
||||
} from '../declarations'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { RiArrowDownSLine } from '@remixicon/react'
|
||||
import {
|
||||
memo,
|
||||
@ -13,7 +14,6 @@ import {
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { ConfigurationMethodEnum, ModelModalModeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import Indicator from '@/app/components/header/indicator'
|
||||
import Authorized from './authorized'
|
||||
@ -89,11 +89,11 @@ const SwitchCredentialInLoadBalancing = ({
|
||||
)
|
||||
if (empty && notAllowCustomCredential) {
|
||||
return (
|
||||
<Tooltip
|
||||
asChild
|
||||
popupContent={t('auth.credentialUnavailable', { ns: 'plugin' })}
|
||||
>
|
||||
{Item}
|
||||
<Tooltip>
|
||||
<TooltipTrigger render={Item} />
|
||||
<TooltipContent>
|
||||
{t('auth.credentialUnavailable', { ns: 'plugin' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import type { ReactNode } from 'react'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
|
||||
import { RiErrorWarningFill } from '@remixicon/react'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { SwitchPluginVersion } from '@/app/components/workflow/nodes/_base/components/switch-plugin-version'
|
||||
import Link from '@/next/link'
|
||||
import { useInstalledPluginList } from '@/service/use-plugins'
|
||||
@ -13,6 +14,28 @@ type StatusIndicatorsProps = {
|
||||
t: any
|
||||
}
|
||||
|
||||
type StatusPopoverProps = {
|
||||
ariaLabel: string
|
||||
content: ReactNode
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
const StatusPopover = ({ ariaLabel, content, children }: StatusPopoverProps) => (
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
openOnHover
|
||||
aria-label={ariaLabel}
|
||||
className="inline-flex border-0 bg-transparent p-0"
|
||||
onClick={e => e.stopPropagation()}
|
||||
>
|
||||
{children}
|
||||
</PopoverTrigger>
|
||||
<PopoverContent placement="top" popupClassName="rounded-md px-3 py-2 system-xs-regular text-text-tertiary">
|
||||
{content}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)
|
||||
|
||||
const StatusIndicators = ({ needsConfiguration, modelProvider, inModelList, disabled, pluginInfo, t }: StatusIndicatorsProps) => {
|
||||
const { data: pluginList } = useInstalledPluginList()
|
||||
const renderTooltipContent = (title: string, description?: string, linkText?: string, linkHref?: string) => {
|
||||
@ -48,27 +71,26 @@ const StatusIndicators = ({ needsConfiguration, modelProvider, inModelList, disa
|
||||
<>
|
||||
{inModelList
|
||||
? (
|
||||
<Tooltip
|
||||
popupContent={t('nodes.agent.modelSelectorTooltips.deprecated', { ns: 'workflow' })}
|
||||
asChild={false}
|
||||
needsDelay={false}
|
||||
<StatusPopover
|
||||
ariaLabel={t('nodes.agent.modelSelectorTooltips.deprecated', { ns: 'workflow' })}
|
||||
content={t('nodes.agent.modelSelectorTooltips.deprecated', { ns: 'workflow' })}
|
||||
>
|
||||
<RiErrorWarningFill className="h-4 w-4 text-text-destructive" />
|
||||
</Tooltip>
|
||||
</StatusPopover>
|
||||
)
|
||||
: !pluginInfo
|
||||
? (
|
||||
<Tooltip
|
||||
popupContent={renderTooltipContent(
|
||||
<StatusPopover
|
||||
ariaLabel={t('nodes.agent.modelNotSupport.title', { ns: 'workflow' })}
|
||||
content={renderTooltipContent(
|
||||
t('nodes.agent.modelNotSupport.title', { ns: 'workflow' }),
|
||||
t('nodes.agent.modelNotSupport.desc', { ns: 'workflow' }),
|
||||
t('nodes.agent.linkToPlugin', { ns: 'workflow' }),
|
||||
'/plugins',
|
||||
)}
|
||||
asChild={false}
|
||||
>
|
||||
<RiErrorWarningFill className="h-4 w-4 text-text-destructive" />
|
||||
</Tooltip>
|
||||
</StatusPopover>
|
||||
)
|
||||
: (
|
||||
<SwitchPluginVersion
|
||||
@ -82,17 +104,17 @@ const StatusIndicators = ({ needsConfiguration, modelProvider, inModelList, disa
|
||||
</>
|
||||
)}
|
||||
{!modelProvider && !pluginInfo && (
|
||||
<Tooltip
|
||||
popupContent={renderTooltipContent(
|
||||
<StatusPopover
|
||||
ariaLabel={t('nodes.agent.modelNotInMarketplace.title', { ns: 'workflow' })}
|
||||
content={renderTooltipContent(
|
||||
t('nodes.agent.modelNotInMarketplace.title', { ns: 'workflow' }),
|
||||
t('nodes.agent.modelNotInMarketplace.desc', { ns: 'workflow' }),
|
||||
t('nodes.agent.linkToPlugin', { ns: 'workflow' }),
|
||||
'/plugins',
|
||||
)}
|
||||
asChild={false}
|
||||
>
|
||||
<RiErrorWarningFill className="h-4 w-4 text-text-destructive" />
|
||||
</Tooltip>
|
||||
</StatusPopover>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import type { ModelItem, ModelProvider } from '../declarations'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
|
||||
import { Switch } from '@langgenius/dify-ui/switch'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { useDebounceFn } from 'ahooks'
|
||||
@ -7,7 +8,6 @@ import { memo, useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
import { Balance } from '@/app/components/base/icons/src/vender/line/financeAndECommerce'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { Plan } from '@/app/components/billing/type'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useProviderContext, useProviderContextSelector } from '@/context/provider-context'
|
||||
@ -102,14 +102,12 @@ const ModelListItem = ({ model, provider, isConfigurable, onChange, onModifyLoad
|
||||
{
|
||||
model.deprecated
|
||||
? (
|
||||
<Tooltip
|
||||
popupContent={
|
||||
<span className="font-semibold">{t('modelProvider.modelHasBeenDeprecated', { ns: 'common' })}</span>
|
||||
}
|
||||
offset={{ mainAxis: 4 }}
|
||||
>
|
||||
<Switch checked={false} disabled size="md" />
|
||||
</Tooltip>
|
||||
<Popover>
|
||||
<PopoverTrigger nativeButton={false} openOnHover render={<span><Switch checked={false} disabled size="md" /></span>} />
|
||||
<PopoverContent popupClassName="px-3 py-2 font-semibold system-xs-regular text-text-tertiary">
|
||||
{t('modelProvider.modelHasBeenDeprecated', { ns: 'common' })}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)
|
||||
: (isCurrentWorkspaceManager && (
|
||||
<Switch
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
import type { PluginDetail } from '@/app/components/plugins/types'
|
||||
import type { TriggerSubscription } from '@/app/components/workflow/block-selector/types'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
|
||||
import {
|
||||
RiDeleteBinLine,
|
||||
RiEditLine,
|
||||
@ -10,7 +11,6 @@ import {
|
||||
import { useBoolean } from 'ahooks'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { DeleteConfirm } from './delete-confirm'
|
||||
import { EditModal } from './edit'
|
||||
|
||||
@ -65,19 +65,26 @@ const SubscriptionCard = ({ data, pluginDetail }: Props) => {
|
||||
</div>
|
||||
|
||||
<div className="mt-1 flex items-center justify-between">
|
||||
<Tooltip
|
||||
disabled={!data.endpoint}
|
||||
popupContent={data.endpoint && (
|
||||
<div className="max-w-[320px] break-all">
|
||||
{data.endpoint}
|
||||
</div>
|
||||
)}
|
||||
position="left"
|
||||
>
|
||||
<div className="flex-1 truncate system-xs-regular text-text-tertiary">
|
||||
{data.endpoint}
|
||||
</div>
|
||||
</Tooltip>
|
||||
{data.endpoint
|
||||
? (
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
openOnHover
|
||||
aria-label={data.endpoint}
|
||||
className="flex-1 truncate border-0 bg-transparent p-0 text-left system-xs-regular text-text-tertiary"
|
||||
>
|
||||
{data.endpoint}
|
||||
</PopoverTrigger>
|
||||
<PopoverContent placement="left" popupClassName="max-w-[320px] break-all px-3 py-2 system-xs-regular text-text-tertiary">
|
||||
{data.endpoint}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)
|
||||
: (
|
||||
<div className="flex-1 truncate system-xs-regular text-text-tertiary">
|
||||
{data.endpoint}
|
||||
</div>
|
||||
)}
|
||||
<div className="mx-2 text-xs text-text-tertiary opacity-30">·</div>
|
||||
<div className="shrink-0 system-xs-regular text-text-tertiary">
|
||||
{data.workflows_in_use > 0 ? t('subscription.list.item.usedByNum', { ns: 'pluginTrigger', num: data.workflows_in_use }) : t('subscription.list.item.noUsed', { ns: 'pluginTrigger' })}
|
||||
|
||||
@ -9,6 +9,7 @@ import type {
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Select, SelectContent, SelectItem, SelectItemIndicator, SelectItemText, SelectTrigger } from '@langgenius/dify-ui/select'
|
||||
import { Switch } from '@langgenius/dify-ui/switch'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import {
|
||||
RiArrowRightUpLine,
|
||||
RiBracesLine,
|
||||
@ -16,9 +17,8 @@ import {
|
||||
import { useBoolean } from 'ahooks'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import Input from '@/app/components/base/input'
|
||||
// eslint-disable-next-line no-restricted-imports -- legacy tooltip migration is handled separately from this change
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { FormTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import { AppSelector } from '@/app/components/plugins/plugin-detail-panel/app-selector'
|
||||
@ -127,17 +127,16 @@ const ReasoningConfigForm: React.FC<Props> = ({
|
||||
} = schema
|
||||
const auto = value[variable]?.auto
|
||||
const fieldTitle = getFieldTitle(label, language)
|
||||
const tooltipContent = (tooltip && (
|
||||
<Tooltip
|
||||
popupContent={(
|
||||
<div className="w-[200px]">
|
||||
{tooltip[language] || tooltip.en_US}
|
||||
</div>
|
||||
)}
|
||||
triggerClassName="ml-0.5 w-4 h-4"
|
||||
asChild={false}
|
||||
/>
|
||||
))
|
||||
const tooltipText = tooltip?.[language] || tooltip?.en_US
|
||||
const tooltipContent = tooltipText && (
|
||||
<Infotip
|
||||
aria-label={tooltipText}
|
||||
className="ml-0.5 h-4 w-4"
|
||||
popupClassName="w-[200px]"
|
||||
>
|
||||
{tooltipText}
|
||||
</Infotip>
|
||||
)
|
||||
const varInput = value[variable]!.value
|
||||
const {
|
||||
isString,
|
||||
@ -173,20 +172,22 @@ const ReasoningConfigForm: React.FC<Props> = ({
|
||||
<span className="mx-1 system-xs-regular text-text-quaternary">·</span>
|
||||
<span className="system-xs-regular text-text-tertiary">{resolveTargetVarType(type)}</span>
|
||||
{isShowJSONEditor && (
|
||||
<Tooltip
|
||||
popupContent={(
|
||||
<div className="system-xs-medium text-text-secondary">
|
||||
{t('nodes.agent.clickToViewParameterSchema', { ns: 'workflow' })}
|
||||
</div>
|
||||
)}
|
||||
asChild={false}
|
||||
>
|
||||
<div
|
||||
className="ml-0.5 cursor-pointer rounded-sm p-px text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary"
|
||||
onClick={() => showSchema(input_schema as SchemaRoot, fieldTitle!)}
|
||||
>
|
||||
<RiBracesLine className="size-3.5" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<button
|
||||
type="button"
|
||||
aria-label={t('nodes.agent.clickToViewParameterSchema', { ns: 'workflow' })}
|
||||
className="ml-0.5 cursor-pointer rounded-sm border-0 bg-transparent p-px text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary"
|
||||
onClick={() => showSchema(input_schema as SchemaRoot, fieldTitle!)}
|
||||
>
|
||||
<RiBracesLine className="size-3.5" />
|
||||
</button>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent className="system-xs-medium text-text-secondary">
|
||||
{t('nodes.agent.clickToViewParameterSchema', { ns: 'workflow' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
'use client'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
|
||||
import { Switch } from '@langgenius/dify-ui/switch'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import {
|
||||
RiDeleteBinLine,
|
||||
RiEqualizer2Line,
|
||||
@ -14,7 +14,6 @@ import { useTranslation } from 'react-i18next'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import AppIcon from '@/app/components/base/app-icon'
|
||||
import { Group } from '@/app/components/base/icons/src/vender/other'
|
||||
import { ToolTipContent } from '@/app/components/base/tooltip/content'
|
||||
import Indicator from '@/app/components/header/indicator'
|
||||
import { InstallPluginButton } from '@/app/components/workflow/nodes/_base/components/install-plugin-button'
|
||||
import { useMCPToolAvailability } from '@/app/components/workflow/nodes/_base/components/mcp-tool-availability'
|
||||
@ -144,11 +143,14 @@ const ToolItem = ({
|
||||
className="-mt-1"
|
||||
uniqueIdentifier={installInfo}
|
||||
tooltip={(
|
||||
<ToolTipContent
|
||||
title={t('detailPanel.toolSelector.unsupportedTitle', { ns: 'plugin' })}
|
||||
>
|
||||
{`${t('detailPanel.toolSelector.unsupportedContent', { ns: 'plugin' })} ${t('detailPanel.toolSelector.unsupportedContent2', { ns: 'plugin' })}`}
|
||||
</ToolTipContent>
|
||||
<div className="w-[180px]" data-testid="tooltip-content">
|
||||
<div className="mb-1.5 font-semibold text-text-secondary" data-testid="tooltip-content-title">
|
||||
{t('detailPanel.toolSelector.unsupportedTitle', { ns: 'plugin' })}
|
||||
</div>
|
||||
<div className="mb-1.5 text-text-tertiary" data-testid="tooltip-content-body">
|
||||
{`${t('detailPanel.toolSelector.unsupportedContent', { ns: 'plugin' })} ${t('detailPanel.toolSelector.unsupportedContent2', { ns: 'plugin' })}`}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
onChange={() => {
|
||||
onInstall?.()
|
||||
@ -167,18 +169,18 @@ const ToolItem = ({
|
||||
/>
|
||||
)}
|
||||
{isError && (
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div aria-label={typeof errorTip === 'string' ? errorTip : undefined}>
|
||||
<RiErrorWarningFill className="h-4 w-4 text-text-destructive" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
openOnHover
|
||||
aria-label={typeof errorTip === 'string' ? errorTip : t('detailPanel.toolSelector.unsupportedTitle', { ns: 'plugin' })}
|
||||
className="inline-flex border-0 bg-transparent p-0"
|
||||
>
|
||||
<RiErrorWarningFill className="h-4 w-4 text-text-destructive" />
|
||||
</PopoverTrigger>
|
||||
<PopoverContent popupClassName="px-3 py-2 system-xs-regular text-text-tertiary">
|
||||
{errorTip}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
import type { FC } from 'react'
|
||||
import type { PluginDetail } from '../types'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
|
||||
import {
|
||||
RiArrowRightUpLine,
|
||||
RiBugLine,
|
||||
@ -13,7 +14,6 @@ import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import * as React from 'react'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import useRefreshPluginList from '@/app/components/plugins/install-plugin/hooks/use-refresh-plugin-list'
|
||||
import { API_PREFIX } from '@/config'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
@ -124,12 +124,18 @@ const PluginItem: FC<Props> = ({
|
||||
<Title title={title} />
|
||||
{verified && <Verified className="ml-0.5 h-4 w-4" text={t('marketplace.verifiedTip', { ns: 'plugin' })} />}
|
||||
{!isDifyVersionCompatible && (
|
||||
<Tooltip popupContent={
|
||||
t('difyVersionNotCompatible', { ns: 'plugin', minimalDifyVersion: declarationMeta.minimum_dify_version })
|
||||
}
|
||||
>
|
||||
<RiErrorWarningLine color="red" className="ml-0.5 h-4 w-4 shrink-0 text-text-accent" />
|
||||
</Tooltip>
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
openOnHover
|
||||
aria-label={t('difyVersionNotCompatible', { ns: 'plugin', minimalDifyVersion: declarationMeta.minimum_dify_version })}
|
||||
className="ml-0.5 inline-flex h-4 w-4 shrink-0 border-0 bg-transparent p-0"
|
||||
>
|
||||
<RiErrorWarningLine color="red" className="h-4 w-4 text-text-accent" />
|
||||
</PopoverTrigger>
|
||||
<PopoverContent popupClassName="px-3 py-2 system-xs-regular text-text-tertiary">
|
||||
{t('difyVersionNotCompatible', { ns: 'plugin', minimalDifyVersion: declarationMeta.minimum_dify_version })}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)}
|
||||
<Badge
|
||||
className="ml-1 shrink-0"
|
||||
|
||||
@ -13,7 +13,7 @@ import {
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNodes } from 'reactflow'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import { useInputFieldPanel } from '@/app/components/rag-pipeline/hooks'
|
||||
import { useNodesSyncDraft } from '@/app/components/workflow/hooks'
|
||||
import { useStore } from '@/app/components/workflow/store'
|
||||
@ -137,10 +137,12 @@ const InputFieldPanel = () => {
|
||||
<span className="system-sm-semibold-uppercase text-text-secondary">
|
||||
{t('inputFieldPanel.uniqueInputs.title', { ns: 'datasetPipeline' })}
|
||||
</span>
|
||||
<Tooltip
|
||||
popupContent={t('inputFieldPanel.uniqueInputs.tooltip', { ns: 'datasetPipeline' })}
|
||||
<Infotip
|
||||
aria-label={t('inputFieldPanel.uniqueInputs.tooltip', { ns: 'datasetPipeline' })}
|
||||
popupClassName="max-w-[240px]"
|
||||
/>
|
||||
>
|
||||
{t('inputFieldPanel.uniqueInputs.tooltip', { ns: 'datasetPipeline' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
<div className="flex flex-col gap-y-1 py-1">
|
||||
{
|
||||
|
||||
@ -6,9 +6,9 @@ import { cn } from '@langgenius/dify-ui/cn'
|
||||
import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Drawer from '@/app/components/base/drawer-plus'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import Input from '@/app/components/base/input'
|
||||
import Radio from '@/app/components/base/radio/ui'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { AuthHeaderPrefix, AuthType } from '@/app/components/tools/types'
|
||||
|
||||
type Props = {
|
||||
@ -123,14 +123,13 @@ const ConfigCredential: FC<Props> = ({
|
||||
<div>
|
||||
<div className="flex items-center py-2 system-sm-medium text-text-primary">
|
||||
{t('createTool.authMethod.key', { ns: 'tools' })}
|
||||
<Tooltip
|
||||
popupContent={(
|
||||
<div className="w-[261px] text-text-tertiary">
|
||||
{t('createTool.authMethod.keyTooltip', { ns: 'tools' })}
|
||||
</div>
|
||||
)}
|
||||
triggerClassName="ml-0.5 w-4 h-4"
|
||||
/>
|
||||
<Infotip
|
||||
aria-label={t('createTool.authMethod.keyTooltip', { ns: 'tools' })}
|
||||
className="ml-0.5 h-4 w-4"
|
||||
popupClassName="w-[261px] text-text-tertiary"
|
||||
>
|
||||
{t('createTool.authMethod.keyTooltip', { ns: 'tools' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
<Input
|
||||
value={tempCredential.api_key_header}
|
||||
@ -153,14 +152,13 @@ const ConfigCredential: FC<Props> = ({
|
||||
<div>
|
||||
<div className="flex items-center py-2 system-sm-medium text-text-primary">
|
||||
{t('createTool.authMethod.queryParam', { ns: 'tools' })}
|
||||
<Tooltip
|
||||
popupContent={(
|
||||
<div className="w-[261px] text-text-tertiary">
|
||||
{t('createTool.authMethod.queryParamTooltip', { ns: 'tools' })}
|
||||
</div>
|
||||
)}
|
||||
triggerClassName="ml-0.5 w-4 h-4"
|
||||
/>
|
||||
<Infotip
|
||||
aria-label={t('createTool.authMethod.queryParamTooltip', { ns: 'tools' })}
|
||||
className="ml-0.5 h-4 w-4"
|
||||
popupClassName="w-[261px] text-text-tertiary"
|
||||
>
|
||||
{t('createTool.authMethod.queryParamTooltip', { ns: 'tools' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
<Input
|
||||
value={tempCredential.api_key_query_param}
|
||||
|
||||
@ -6,10 +6,10 @@ import type {
|
||||
ToolWithProvider,
|
||||
} from '../types'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { memo, useEffect, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { useFeaturedToolsRecommendations } from '@/service/use-plugins'
|
||||
import { useAllBuiltInTools, useAllCustomTools, useAllMCPTools, useAllWorkflowTools, useInvalidateAllBuiltInTools } from '@/service/use-tools'
|
||||
@ -129,19 +129,22 @@ const TabHeaderItem = ({
|
||||
|
||||
if (tab.disabled) {
|
||||
return (
|
||||
<Tooltip
|
||||
key={tab.key}
|
||||
position="top"
|
||||
popupClassName="max-w-[200px]"
|
||||
popupContent={disabledTip}
|
||||
>
|
||||
<div
|
||||
className={className}
|
||||
aria-disabled={tab.disabled}
|
||||
onClick={handleClick}
|
||||
>
|
||||
{tab.name}
|
||||
</div>
|
||||
<Tooltip key={tab.key}>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<button
|
||||
type="button"
|
||||
className={className}
|
||||
aria-disabled={tab.disabled}
|
||||
onClick={handleClick}
|
||||
>
|
||||
{tab.name}
|
||||
</button>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent placement="top" className="max-w-[200px]">
|
||||
{disabledTip}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,22 +1,23 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
|
||||
import { RiAlertFill } from '@remixicon/react'
|
||||
import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
|
||||
const McpToolNotSupportTooltip: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const tip = t('detailPanel.toolSelector.unsupportedMCPTool', { ns: 'plugin' })
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
popupContent={(
|
||||
<div className="w-[256px]">
|
||||
{t('detailPanel.toolSelector.unsupportedMCPTool', { ns: 'plugin' })}
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<RiAlertFill className="size-4 text-text-warning-secondary" />
|
||||
</Tooltip>
|
||||
<Popover>
|
||||
<PopoverTrigger openOnHover aria-label={tip} className="inline-flex border-0 bg-transparent p-0">
|
||||
<RiAlertFill className="size-4 text-text-warning-secondary" />
|
||||
</PopoverTrigger>
|
||||
<PopoverContent popupClassName="w-[256px] px-3 py-2 system-xs-regular text-text-tertiary">
|
||||
{tip}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
export default React.memo(McpToolNotSupportTooltip)
|
||||
|
||||
@ -2,13 +2,13 @@
|
||||
|
||||
import type { FC, ReactNode } from 'react'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
|
||||
import { RiArrowLeftRightLine, RiExternalLinkLine } from '@remixicon/react'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
import { Badge as Badge2, BadgeState } from '@/app/components/base/badge/index'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import useGetIcon from '@/app/components/plugins/install-plugin/base/use-get-icon'
|
||||
import { pluginManifestToCardPluginProps } from '@/app/components/plugins/install-plugin/utils'
|
||||
import PluginMutationModel from '@/app/components/plugins/plugin-mutation-model'
|
||||
@ -67,76 +67,91 @@ export const SwitchPluginVersion: FC<SwitchPluginVersionProps> = (props) => {
|
||||
if (!uniqueIdentifier || !pluginId)
|
||||
return null
|
||||
|
||||
const content = (
|
||||
<div className={cn('flex w-fit items-center justify-center', className)} onClick={e => e.stopPropagation()}>
|
||||
{isShowUpdateModal && pluginDetail && (
|
||||
<PluginMutationModel
|
||||
onCancel={hideUpdateModal}
|
||||
plugin={pluginManifestToCardPluginProps({
|
||||
...pluginDetail.declaration,
|
||||
icon: icon!,
|
||||
})}
|
||||
mutation={mutation}
|
||||
mutate={install}
|
||||
confirmButtonText={t('nodes.agent.installPlugin.install', { ns: 'workflow' })}
|
||||
cancelButtonText={t('nodes.agent.installPlugin.cancel', { ns: 'workflow' })}
|
||||
modelTitle={t('nodes.agent.installPlugin.title', { ns: 'workflow' })}
|
||||
description={t('nodes.agent.installPlugin.desc', { ns: 'workflow' })}
|
||||
cardTitleLeft={(
|
||||
<>
|
||||
<Badge2 className="mx-1" size="s" state={BadgeState.Warning}>
|
||||
{`${pluginDetail.version} -> ${target!.version}`}
|
||||
</Badge2>
|
||||
</>
|
||||
)}
|
||||
modalBottomLeft={(
|
||||
<Link
|
||||
className="flex items-center justify-center gap-1"
|
||||
href={getMarketplaceUrl(`/plugins/${pluginDetail.declaration.author}/${pluginDetail.declaration.name}`)}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<span className="system-xs-regular text-xs text-text-accent">
|
||||
{t('nodes.agent.installPlugin.changelog', { ns: 'workflow' })}
|
||||
</span>
|
||||
<RiExternalLinkLine className="size-3 text-text-accent" />
|
||||
</Link>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{pluginDetail && (
|
||||
<PluginVersionPicker
|
||||
isShow={isShow}
|
||||
onShowChange={setIsShow}
|
||||
pluginID={pluginId}
|
||||
currentVersion={pluginDetail.version}
|
||||
onSelect={(state) => {
|
||||
setTarget({
|
||||
pluginUniqueIden: state.unique_identifier,
|
||||
version: state.version,
|
||||
})
|
||||
showUpdateModal()
|
||||
}}
|
||||
trigger={(
|
||||
<Badge
|
||||
className={cn(
|
||||
'mx-1 flex hover:bg-state-base-hover',
|
||||
isShow && 'bg-state-base-hover',
|
||||
)}
|
||||
uppercase={true}
|
||||
text={(
|
||||
<>
|
||||
<div>{pluginDetail.version}</div>
|
||||
<RiArrowLeftRightLine className="ml-1 h-3 w-3 text-text-tertiary" />
|
||||
</>
|
||||
)}
|
||||
hasRedCornerMark={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
if (!tooltip || isShow || isShowUpdateModal)
|
||||
return content
|
||||
|
||||
return (
|
||||
<Tooltip popupContent={!isShow && !isShowUpdateModal && tooltip} triggerMethod="hover">
|
||||
<div className={cn('flex w-fit items-center justify-center', className)} onClick={e => e.stopPropagation()}>
|
||||
{isShowUpdateModal && pluginDetail && (
|
||||
<PluginMutationModel
|
||||
onCancel={hideUpdateModal}
|
||||
plugin={pluginManifestToCardPluginProps({
|
||||
...pluginDetail.declaration,
|
||||
icon: icon!,
|
||||
})}
|
||||
mutation={mutation}
|
||||
mutate={install}
|
||||
confirmButtonText={t('nodes.agent.installPlugin.install', { ns: 'workflow' })}
|
||||
cancelButtonText={t('nodes.agent.installPlugin.cancel', { ns: 'workflow' })}
|
||||
modelTitle={t('nodes.agent.installPlugin.title', { ns: 'workflow' })}
|
||||
description={t('nodes.agent.installPlugin.desc', { ns: 'workflow' })}
|
||||
cardTitleLeft={(
|
||||
<>
|
||||
<Badge2 className="mx-1" size="s" state={BadgeState.Warning}>
|
||||
{`${pluginDetail.version} -> ${target!.version}`}
|
||||
</Badge2>
|
||||
</>
|
||||
)}
|
||||
modalBottomLeft={(
|
||||
<Link
|
||||
className="flex items-center justify-center gap-1"
|
||||
href={getMarketplaceUrl(`/plugins/${pluginDetail.declaration.author}/${pluginDetail.declaration.name}`)}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<span className="system-xs-regular text-xs text-text-accent">
|
||||
{t('nodes.agent.installPlugin.changelog', { ns: 'workflow' })}
|
||||
</span>
|
||||
<RiExternalLinkLine className="size-3 text-text-accent" />
|
||||
</Link>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{pluginDetail && (
|
||||
<PluginVersionPicker
|
||||
isShow={isShow}
|
||||
onShowChange={setIsShow}
|
||||
pluginID={pluginId}
|
||||
currentVersion={pluginDetail.version}
|
||||
onSelect={(state) => {
|
||||
setTarget({
|
||||
pluginUniqueIden: state.unique_identifier,
|
||||
version: state.version,
|
||||
})
|
||||
showUpdateModal()
|
||||
}}
|
||||
trigger={(
|
||||
<Badge
|
||||
className={cn(
|
||||
'mx-1 flex hover:bg-state-base-hover',
|
||||
isShow && 'bg-state-base-hover',
|
||||
)}
|
||||
uppercase={true}
|
||||
text={(
|
||||
<>
|
||||
<div>{pluginDetail.version}</div>
|
||||
<RiArrowLeftRightLine className="ml-1 h-3 w-3 text-text-tertiary" />
|
||||
</>
|
||||
)}
|
||||
hasRedCornerMark={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Tooltip>
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
openOnHover
|
||||
nativeButton={false}
|
||||
aria-label={typeof tooltip === 'string' ? tooltip : t('nodes.agent.installPlugin.title', { ns: 'workflow' })}
|
||||
render={content}
|
||||
/>
|
||||
<PopoverContent popupClassName="px-3 py-2 system-xs-regular text-text-tertiary">
|
||||
{tooltip}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import type { NodeProps } from 'reactflow'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { RiHome5Fill } from '@remixicon/react'
|
||||
import { memo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { NodeSourceHandle } from '@/app/components/workflow/nodes/_base/components/node-handle'
|
||||
|
||||
const IterationStartNode = ({ id, data }: NodeProps) => {
|
||||
@ -10,10 +10,14 @@ const IterationStartNode = ({ id, data }: NodeProps) => {
|
||||
|
||||
return (
|
||||
<div className="nodrag group mt-1 flex h-11 w-11 items-center justify-center rounded-2xl border border-workflow-block-border bg-workflow-block-bg shadow-xs">
|
||||
<Tooltip popupContent={t('blocks.iteration-start', { ns: 'workflow' })} asChild={false}>
|
||||
<div className="flex h-6 w-6 items-center justify-center rounded-full border-[0.5px] border-components-panel-border-subtle bg-util-colors-blue-brand-blue-brand-500">
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
aria-label={t('blocks.iteration-start', { ns: 'workflow' })}
|
||||
className="flex h-6 w-6 items-center justify-center rounded-full border-[0.5px] border-components-panel-border-subtle bg-util-colors-blue-brand-blue-brand-500 p-0"
|
||||
>
|
||||
<RiHome5Fill className="h-3 w-3 text-text-primary-on-surface" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{t('blocks.iteration-start', { ns: 'workflow' })}</TooltipContent>
|
||||
</Tooltip>
|
||||
<NodeSourceHandle
|
||||
id={id}
|
||||
@ -30,10 +34,14 @@ export const IterationStartNodeDumb = () => {
|
||||
|
||||
return (
|
||||
<div className="nodrag relative top-[21px] left-[17px] z-11 flex h-11 w-11 items-center justify-center rounded-2xl border border-workflow-block-border bg-workflow-block-bg">
|
||||
<Tooltip popupContent={t('blocks.iteration-start', { ns: 'workflow' })} asChild={false}>
|
||||
<div className="flex h-6 w-6 items-center justify-center rounded-full border-[0.5px] border-components-panel-border-subtle bg-util-colors-blue-brand-blue-brand-500">
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
aria-label={t('blocks.iteration-start', { ns: 'workflow' })}
|
||||
className="flex h-6 w-6 items-center justify-center rounded-full border-[0.5px] border-components-panel-border-subtle bg-util-colors-blue-brand-blue-brand-500 p-0"
|
||||
>
|
||||
<RiHome5Fill className="h-3 w-3 text-text-primary-on-surface" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{t('blocks.iteration-start', { ns: 'workflow' })}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -17,7 +17,7 @@ import {
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import WeightedScoreComponent from '@/app/components/app/configuration/dataset-config/params-config/weighted-score'
|
||||
import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import { DEFAULT_WEIGHTED_SCORE } from '@/models/datasets'
|
||||
import {
|
||||
HybridSearchModeEnum,
|
||||
@ -174,10 +174,13 @@ const SearchMethodOption = ({
|
||||
disabled={readonly}
|
||||
/>
|
||||
{t('modelProvider.rerankModel.key', { ns: 'common' })}
|
||||
<Tooltip
|
||||
triggerClassName="ml-0.5 shrink-0 w-3.5 h-3.5"
|
||||
popupContent={t('modelProvider.rerankModel.tip', { ns: 'common' })}
|
||||
/>
|
||||
<Infotip
|
||||
aria-label={t('modelProvider.rerankModel.tip', { ns: 'common' })}
|
||||
className="ml-0.5 h-3.5 w-3.5 shrink-0"
|
||||
iconClassName="h-3.5 w-3.5"
|
||||
>
|
||||
{t('modelProvider.rerankModel.tip', { ns: 'common' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import {
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal'
|
||||
import Collapse from '@/app/components/workflow/nodes/_base/components/collapse'
|
||||
import { MetadataFilteringModeEnum } from '@/app/components/workflow/nodes/knowledge-retrieval/types'
|
||||
@ -46,13 +46,9 @@ const MetadataFilter = ({
|
||||
<div className="mr-0.5 system-sm-semibold-uppercase text-text-secondary">
|
||||
{t('nodes.knowledgeRetrieval.metadata.title', { ns: 'workflow' })}
|
||||
</div>
|
||||
<Tooltip
|
||||
popupContent={(
|
||||
<div className="w-[200px]">
|
||||
{t('nodes.knowledgeRetrieval.metadata.tip', { ns: 'workflow' })}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<Infotip aria-label={t('nodes.knowledgeRetrieval.metadata.tip', { ns: 'workflow' })} popupClassName="w-[200px]">
|
||||
{t('nodes.knowledgeRetrieval.metadata.tip', { ns: 'workflow' })}
|
||||
</Infotip>
|
||||
{collapseIcon}
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import type { NodeProps } from 'reactflow'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { RiHome5Fill } from '@remixicon/react'
|
||||
import { memo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { NodeSourceHandle } from '@/app/components/workflow/nodes/_base/components/node-handle'
|
||||
|
||||
const LoopStartNode = ({ id, data }: NodeProps) => {
|
||||
@ -10,10 +10,14 @@ const LoopStartNode = ({ id, data }: NodeProps) => {
|
||||
|
||||
return (
|
||||
<div className="nodrag group mt-1 flex h-11 w-11 items-center justify-center rounded-2xl border border-workflow-block-border bg-workflow-block-bg">
|
||||
<Tooltip popupContent={t('blocks.loop-start', { ns: 'workflow' })} asChild={false}>
|
||||
<div className="flex h-6 w-6 items-center justify-center rounded-full border-[0.5px] border-components-panel-border-subtle bg-util-colors-blue-brand-blue-brand-500">
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
aria-label={t('blocks.loop-start', { ns: 'workflow' })}
|
||||
className="flex h-6 w-6 items-center justify-center rounded-full border-[0.5px] border-components-panel-border-subtle bg-util-colors-blue-brand-blue-brand-500 p-0"
|
||||
>
|
||||
<RiHome5Fill className="h-3 w-3 text-text-primary-on-surface" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{t('blocks.loop-start', { ns: 'workflow' })}</TooltipContent>
|
||||
</Tooltip>
|
||||
<NodeSourceHandle
|
||||
id={id}
|
||||
@ -30,10 +34,14 @@ export const LoopStartNodeDumb = () => {
|
||||
|
||||
return (
|
||||
<div className="nodrag relative top-[21px] left-[17px] z-11 flex h-11 w-11 items-center justify-center rounded-2xl border border-workflow-block-border bg-workflow-block-bg">
|
||||
<Tooltip popupContent={t('blocks.loop-start', { ns: 'workflow' })} asChild={false}>
|
||||
<div className="flex h-6 w-6 items-center justify-center rounded-full border-[0.5px] border-components-panel-border-subtle bg-util-colors-blue-brand-blue-brand-500">
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
aria-label={t('blocks.loop-start', { ns: 'workflow' })}
|
||||
className="flex h-6 w-6 items-center justify-center rounded-full border-[0.5px] border-components-panel-border-subtle bg-util-colors-blue-brand-blue-brand-500 p-0"
|
||||
>
|
||||
<RiHome5Fill className="h-3 w-3 text-text-primary-on-surface" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{t('blocks.loop-start', { ns: 'workflow' })}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -3,7 +3,7 @@ import type { ParameterExtractorNodeType } from './types'
|
||||
import type { NodePanelProps } from '@/app/components/workflow/types'
|
||||
import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal'
|
||||
import { FieldCollapse } from '@/app/components/workflow/nodes/_base/components/collapse'
|
||||
import Field from '@/app/components/workflow/nodes/_base/components/field'
|
||||
@ -131,14 +131,14 @@ const Panel: FC<NodePanelProps<ParameterExtractorNodeType>> = ({
|
||||
title={(
|
||||
<div className="flex items-center space-x-1">
|
||||
<span className="uppercase">{t(`${i18nPrefix}.instruction`, { ns: 'workflow' })}</span>
|
||||
<Tooltip
|
||||
popupContent={(
|
||||
<div className="w-[120px]">
|
||||
{t(`${i18nPrefix}.instructionTip`, { ns: 'workflow' })}
|
||||
</div>
|
||||
)}
|
||||
triggerClassName="w-3.5 h-3.5 ml-0.5"
|
||||
/>
|
||||
<Infotip
|
||||
aria-label={t(`${i18nPrefix}.instructionTip`, { ns: 'workflow' })}
|
||||
className="ml-0.5 h-3.5 w-3.5"
|
||||
iconClassName="h-3.5 w-3.5"
|
||||
popupClassName="w-[120px]"
|
||||
>
|
||||
{t(`${i18nPrefix}.instructionTip`, { ns: 'workflow' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
)}
|
||||
value={inputs.instruction}
|
||||
|
||||
@ -3,7 +3,7 @@ import type { FC } from 'react'
|
||||
import type { Memory, Node, NodeOutPutVar } from '@/app/components/workflow/types'
|
||||
import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor'
|
||||
import MemoryConfig from '../../_base/components/memory-config'
|
||||
|
||||
@ -48,14 +48,14 @@ const AdvancedSetting: FC<Props> = ({
|
||||
title={(
|
||||
<div className="flex items-center space-x-1">
|
||||
<span className="uppercase">{t(`${i18nPrefix}.instruction`, { ns: 'workflow' })}</span>
|
||||
<Tooltip
|
||||
popupContent={(
|
||||
<div className="w-[120px]">
|
||||
{t(`${i18nPrefix}.instructionTip`, { ns: 'workflow' })}
|
||||
</div>
|
||||
)}
|
||||
triggerClassName="w-3.5 h-3.5 ml-0.5"
|
||||
/>
|
||||
<Infotip
|
||||
aria-label={t(`${i18nPrefix}.instructionTip`, { ns: 'workflow' })}
|
||||
className="ml-0.5 h-3.5 w-3.5"
|
||||
iconClassName="h-3.5 w-3.5"
|
||||
popupClassName="w-[120px]"
|
||||
>
|
||||
{t(`${i18nPrefix}.instructionTip`, { ns: 'workflow' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
)}
|
||||
value={instruction}
|
||||
|
||||
@ -2,9 +2,9 @@ import type { TFunction } from 'i18next'
|
||||
import type { FC } from 'react'
|
||||
import type { NodeProps } from 'reactflow'
|
||||
import type { QuestionClassifierNodeType } from './types'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
|
||||
import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import {
|
||||
useTextGenerationCurrentProviderAndModelAndModelList,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
@ -47,15 +47,18 @@ const TruncatedClassItem: FC<TruncatedClassItemProps> = ({ topic, index, nodeId,
|
||||
</div>
|
||||
{shouldShowTooltip
|
||||
? (
|
||||
<Tooltip
|
||||
popupContent={(
|
||||
<div className="max-w-[300px] wrap-break-word">
|
||||
<ReadonlyInputWithSelectVar value={topic.name} nodeId={nodeId} />
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
{content}
|
||||
</Tooltip>
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
openOnHover
|
||||
aria-label={topic.name}
|
||||
className="w-full border-0 bg-transparent p-0 text-left"
|
||||
>
|
||||
{content}
|
||||
</PopoverTrigger>
|
||||
<PopoverContent popupClassName="max-w-[300px] px-3 py-2 system-xs-regular wrap-break-word text-text-tertiary">
|
||||
<ReadonlyInputWithSelectVar value={topic.name} nodeId={nodeId} />
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)
|
||||
: content}
|
||||
</div>
|
||||
|
||||
@ -9,7 +9,7 @@ import {
|
||||
RiBracesLine,
|
||||
} from '@remixicon/react'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import { FormTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import { SchemaModal } from '@/app/components/plugins/plugin-detail-panel/tool-selector/components'
|
||||
@ -57,15 +57,13 @@ const TriggerFormItem: FC<Props> = ({
|
||||
<div className="ml-1 system-xs-regular text-text-destructive-secondary">*</div>
|
||||
)}
|
||||
{!showDescription && tooltip && (
|
||||
<Tooltip
|
||||
popupContent={(
|
||||
<div className="w-[200px]">
|
||||
{tooltip[language] || tooltip.en_US}
|
||||
</div>
|
||||
)}
|
||||
triggerClassName="ml-1 w-4 h-4"
|
||||
asChild={false}
|
||||
/>
|
||||
<Infotip
|
||||
aria-label={tooltip[language] || tooltip.en_US}
|
||||
className="ml-1 h-4 w-4"
|
||||
popupClassName="w-[200px]"
|
||||
>
|
||||
{tooltip[language] || tooltip.en_US}
|
||||
</Infotip>
|
||||
)}
|
||||
{showSchemaButton && (
|
||||
<>
|
||||
|
||||
@ -11,12 +11,12 @@ import {
|
||||
} from '@langgenius/dify-ui/number-field'
|
||||
import { Select, SelectContent, SelectItem, SelectItemIndicator, SelectItemText, SelectTrigger } from '@langgenius/dify-ui/select'
|
||||
import { toast } from '@langgenius/dify-ui/toast'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import copy from 'copy-to-clipboard'
|
||||
import * as React from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import InputWithCopy from '@/app/components/base/input-with-copy'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import Field from '@/app/components/workflow/nodes/_base/components/field'
|
||||
import OutputVars from '@/app/components/workflow/nodes/_base/components/output-vars'
|
||||
import Split from '@/app/components/workflow/nodes/_base/components/split'
|
||||
@ -118,32 +118,38 @@ const Panel: FC<NodePanelProps<WebhookTriggerNodeType>> = ({
|
||||
</div>
|
||||
{inputs.webhook_debug_url && (
|
||||
<div className="space-y-2">
|
||||
<Tooltip
|
||||
popupContent={debugUrlCopied ? t(`${i18nPrefix}.debugUrlCopied`, { ns: 'workflow' }) : t(`${i18nPrefix}.debugUrlCopy`, { ns: 'workflow' })}
|
||||
popupClassName="system-xs-regular text-text-primary bg-components-tooltip-bg border border-components-panel-border shadow-lg backdrop-blur-xs rounded-md px-1.5 py-1"
|
||||
position="top"
|
||||
offset={{ mainAxis: -20 }}
|
||||
needsDelay={true}
|
||||
>
|
||||
<div
|
||||
className="flex cursor-pointer gap-1.5 rounded-lg px-1 py-1.5 transition-colors"
|
||||
style={{ width: '368px', height: '38px' }}
|
||||
onClick={() => {
|
||||
copy(inputs.webhook_debug_url || '')
|
||||
setDebugUrlCopied(true)
|
||||
setTimeout(() => setDebugUrlCopied(false), 2000)
|
||||
}}
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<button
|
||||
type="button"
|
||||
aria-label={t(`${i18nPrefix}.debugUrlCopy`, { ns: 'workflow' })}
|
||||
className="flex cursor-pointer gap-1.5 rounded-lg px-1 py-1.5 text-left transition-colors"
|
||||
style={{ width: '368px', height: '38px' }}
|
||||
onClick={() => {
|
||||
copy(inputs.webhook_debug_url || '')
|
||||
setDebugUrlCopied(true)
|
||||
setTimeout(() => setDebugUrlCopied(false), 2000)
|
||||
}}
|
||||
>
|
||||
<span className="mt-0.5 w-0.5 bg-divider-regular" style={{ height: '28px' }} />
|
||||
<span className="flex-1" style={{ width: '352px', height: '32px' }}>
|
||||
<span className="block text-xs leading-4 text-text-tertiary">
|
||||
{t(`${i18nPrefix}.debugUrlTitle`, { ns: 'workflow' })}
|
||||
</span>
|
||||
<span className="block truncate text-xs leading-4 text-text-primary">
|
||||
{inputs.webhook_debug_url}
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent
|
||||
placement="top"
|
||||
className="rounded-md border border-components-panel-border bg-components-tooltip-bg px-1.5 py-1 system-xs-regular text-text-primary shadow-lg backdrop-blur-xs"
|
||||
>
|
||||
<div className="mt-0.5 w-0.5 bg-divider-regular" style={{ height: '28px' }}></div>
|
||||
<div className="flex-1" style={{ width: '352px', height: '32px' }}>
|
||||
<div className="text-xs leading-4 text-text-tertiary">
|
||||
{t(`${i18nPrefix}.debugUrlTitle`, { ns: 'workflow' })}
|
||||
</div>
|
||||
<div className="truncate text-xs leading-4 text-text-primary">
|
||||
{inputs.webhook_debug_url}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{debugUrlCopied ? t(`${i18nPrefix}.debugUrlCopied`, { ns: 'workflow' }) : t(`${i18nPrefix}.debugUrlCopy`, { ns: 'workflow' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
{isPrivateOrLocalAddress(inputs.webhook_debug_url) && (
|
||||
<div className="mt-1 px-0 py-[2px] system-xs-regular text-text-warning">
|
||||
|
||||
@ -7,8 +7,8 @@ import * as React from 'react'
|
||||
import { useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { v4 as uuid4 } from 'uuid'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import Input from '@/app/components/base/input'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { useWorkflowStore } from '@/app/components/workflow/store'
|
||||
import { checkKeys, replaceSpaceWithUnderscoreInVarNameInput } from '@/utils/var'
|
||||
|
||||
@ -129,14 +129,14 @@ const VariableModal = ({
|
||||
onClick={() => setType('secret')}
|
||||
>
|
||||
<span>Secret</span>
|
||||
<Tooltip
|
||||
popupContent={(
|
||||
<div className="w-[240px]">
|
||||
{t('env.modal.secretTip', { ns: 'workflow' })}
|
||||
</div>
|
||||
)}
|
||||
triggerClassName="ml-0.5 w-3.5 h-3.5"
|
||||
/>
|
||||
<Infotip
|
||||
aria-label={t('env.modal.secretTip', { ns: 'workflow' })}
|
||||
className="ml-0.5 h-3.5 w-3.5"
|
||||
iconClassName="h-3.5 w-3.5"
|
||||
popupClassName="w-[240px]"
|
||||
>
|
||||
{t('env.modal.secretTip', { ns: 'workflow' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -4,12 +4,12 @@ import type { Node } from 'reactflow'
|
||||
import type { ScheduleTriggerNodeType } from '@/app/components/workflow/nodes/trigger-schedule/types'
|
||||
import type { WebhookTriggerNodeType } from '@/app/components/workflow/nodes/trigger-webhook/types'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import copy from 'copy-to-clipboard'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useStoreApi } from 'reactflow'
|
||||
import { StopCircle } from '@/app/components/base/icons/src/vender/line/mediaAndDevices'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import BlockIcon from '@/app/components/workflow/block-icon'
|
||||
import { useGetToolIcon } from '@/app/components/workflow/hooks/use-tool-icon'
|
||||
import { getNextExecutionTime } from '@/app/components/workflow/nodes/trigger-schedule/utils/execution-time-calculator'
|
||||
@ -179,28 +179,32 @@ const Listening: FC<ListeningProps> = ({
|
||||
<div className="shrink-0 system-xs-regular whitespace-pre-line text-text-tertiary">
|
||||
{t('nodes.triggerWebhook.debugUrlTitle', { ns: 'workflow' })}
|
||||
</div>
|
||||
<Tooltip
|
||||
popupContent={debugUrlCopied
|
||||
? t('nodes.triggerWebhook.debugUrlCopied', { ns: 'workflow' })
|
||||
: t('nodes.triggerWebhook.debugUrlCopy', { ns: 'workflow' })}
|
||||
popupClassName="system-xs-regular text-text-primary bg-components-tooltip-bg border border-components-panel-border shadow-lg backdrop-blur-xs rounded-md px-1.5 py-1"
|
||||
position="top"
|
||||
offset={{ mainAxis: -4 }}
|
||||
needsDelay={true}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
aria-label={t('nodes.triggerWebhook.debugUrlCopy', { ns: 'workflow' }) || ''}
|
||||
className={`inline-flex items-center rounded-md border border-divider-regular bg-components-badge-white-to-dark px-1.5 py-[2px] font-mono text-[13px] leading-[18px] text-text-secondary transition-colors hover:bg-components-panel-on-panel-item-bg-hover focus:outline-hidden focus-visible:outline-2 focus-visible:outline-components-panel-border focus-visible:outline-solid ${debugUrlCopied ? 'bg-components-panel-on-panel-item-bg-hover text-text-primary' : ''}`}
|
||||
onClick={() => {
|
||||
copy(webhookDebugUrl)
|
||||
setDebugUrlCopied(true)
|
||||
}}
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<button
|
||||
type="button"
|
||||
aria-label={t('nodes.triggerWebhook.debugUrlCopy', { ns: 'workflow' }) || ''}
|
||||
className={`inline-flex items-center rounded-md border border-divider-regular bg-components-badge-white-to-dark px-1.5 py-[2px] font-mono text-[13px] leading-[18px] text-text-secondary transition-colors hover:bg-components-panel-on-panel-item-bg-hover focus:outline-hidden focus-visible:outline-2 focus-visible:outline-components-panel-border focus-visible:outline-solid ${debugUrlCopied ? 'bg-components-panel-on-panel-item-bg-hover text-text-primary' : ''}`}
|
||||
onClick={() => {
|
||||
copy(webhookDebugUrl)
|
||||
setDebugUrlCopied(true)
|
||||
}}
|
||||
>
|
||||
<span className="whitespace-nowrap text-text-primary">
|
||||
{webhookDebugUrl}
|
||||
</span>
|
||||
</button>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent
|
||||
placement="top"
|
||||
className="rounded-md border border-components-panel-border bg-components-tooltip-bg px-1.5 py-1 system-xs-regular text-text-primary shadow-lg backdrop-blur-xs"
|
||||
>
|
||||
<span className="whitespace-nowrap text-text-primary">
|
||||
{webhookDebugUrl}
|
||||
</span>
|
||||
</button>
|
||||
{debugUrlCopied
|
||||
? t('nodes.triggerWebhook.debugUrlCopied', { ns: 'workflow' })
|
||||
: t('nodes.triggerWebhook.debugUrlCopy', { ns: 'workflow' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -6,12 +6,12 @@ import type {
|
||||
NodeProps,
|
||||
} from '@/app/components/workflow/types'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
|
||||
import {
|
||||
cloneElement,
|
||||
memo,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import BlockIcon from '@/app/components/workflow/block-icon'
|
||||
import {
|
||||
BlockEnum,
|
||||
@ -91,19 +91,21 @@ const BaseCard = ({
|
||||
</div>
|
||||
{
|
||||
data.type === BlockEnum.Iteration && (data as IterationNodeType).is_parallel && (
|
||||
<Tooltip popupContent={(
|
||||
<div className="w-[180px]">
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
openOnHover
|
||||
aria-label={t('nodes.iteration.parallelModeEnableTitle', { ns: 'workflow' })}
|
||||
className="ml-1 flex items-center justify-center rounded-[5px] border border-text-warning bg-transparent px-[5px] py-[3px] system-2xs-medium-uppercase text-text-warning"
|
||||
>
|
||||
{t('nodes.iteration.parallelModeUpper', { ns: 'workflow' })}
|
||||
</PopoverTrigger>
|
||||
<PopoverContent popupClassName="w-[180px] px-3 py-2 system-xs-regular text-text-tertiary">
|
||||
<div className="font-extrabold">
|
||||
{t('nodes.iteration.parallelModeEnableTitle', { ns: 'workflow' })}
|
||||
</div>
|
||||
{t('nodes.iteration.parallelModeEnableDesc', { ns: 'workflow' })}
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<div className="ml-1 flex items-center justify-center rounded-[5px] border border-text-warning px-[5px] py-[3px] system-2xs-medium-uppercase text-text-warning">
|
||||
{t('nodes.iteration.parallelModeUpper', { ns: 'workflow' })}
|
||||
</div>
|
||||
</Tooltip>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import type { NodeProps } from 'reactflow'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { RiHome5Fill } from '@remixicon/react'
|
||||
import { memo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { NodeSourceHandle } from '../../node-handle'
|
||||
|
||||
const IterationStartNode = ({ id, data }: NodeProps) => {
|
||||
@ -10,10 +10,14 @@ const IterationStartNode = ({ id, data }: NodeProps) => {
|
||||
|
||||
return (
|
||||
<div className="nodrag group mt-1 flex h-11 w-11 items-center justify-center rounded-2xl border border-workflow-block-border bg-workflow-block-bg shadow-xs">
|
||||
<Tooltip popupContent={t('blocks.iteration-start', { ns: 'workflow' })} asChild={false}>
|
||||
<div className="flex h-6 w-6 items-center justify-center rounded-full border-[0.5px] border-components-panel-border-subtle bg-util-colors-blue-brand-blue-brand-500">
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
aria-label={t('blocks.iteration-start', { ns: 'workflow' })}
|
||||
className="flex h-6 w-6 items-center justify-center rounded-full border-[0.5px] border-components-panel-border-subtle bg-util-colors-blue-brand-blue-brand-500 p-0"
|
||||
>
|
||||
<RiHome5Fill className="h-3 w-3 text-text-primary-on-surface" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{t('blocks.iteration-start', { ns: 'workflow' })}</TooltipContent>
|
||||
</Tooltip>
|
||||
<NodeSourceHandle
|
||||
id={id}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import type { NodeProps } from 'reactflow'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { RiHome5Fill } from '@remixicon/react'
|
||||
import { memo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { NodeSourceHandle } from '../../node-handle'
|
||||
|
||||
const LoopStartNode = ({ id, data }: NodeProps) => {
|
||||
@ -10,10 +10,14 @@ const LoopStartNode = ({ id, data }: NodeProps) => {
|
||||
|
||||
return (
|
||||
<div className="nodrag group mt-1 flex h-11 w-11 items-center justify-center rounded-2xl border border-workflow-block-border bg-workflow-block-bg">
|
||||
<Tooltip popupContent={t('blocks.loop-start', { ns: 'workflow' })} asChild={false}>
|
||||
<div className="flex h-6 w-6 items-center justify-center rounded-full border-[0.5px] border-components-panel-border-subtle bg-util-colors-blue-brand-blue-brand-500">
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
aria-label={t('blocks.loop-start', { ns: 'workflow' })}
|
||||
className="flex h-6 w-6 items-center justify-center rounded-full border-[0.5px] border-components-panel-border-subtle bg-util-colors-blue-brand-blue-brand-500 p-0"
|
||||
>
|
||||
<RiHome5Fill className="h-3 w-3 text-text-primary-on-surface" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{t('blocks.loop-start', { ns: 'workflow' })}</TooltipContent>
|
||||
</Tooltip>
|
||||
<NodeSourceHandle
|
||||
id={id}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user