mirror of
https://github.com/langgenius/dify.git
synced 2026-05-11 23:18:39 +08:00
fix: use infotip for help glyphs (#36008)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
2162ea6a68
commit
bd0d10ac5c
@ -2527,11 +2527,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"web/app/components/plugins/plugin-detail-panel/multiple-tool-selector/index.tsx": {
|
||||
"ts/no-explicit-any": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"web/app/components/plugins/plugin-detail-panel/strategy-detail.tsx": {
|
||||
"ts/no-explicit-any": {
|
||||
"count": 2
|
||||
|
||||
@ -5,11 +5,6 @@ import type { PromptRole, PromptVariable } from '@/models/debug'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { toast } from '@langgenius/dify-ui/toast'
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from '@langgenius/dify-ui/tooltip'
|
||||
import {
|
||||
RiDeleteBinLine,
|
||||
RiErrorWarningFill,
|
||||
@ -25,6 +20,7 @@ import {
|
||||
Copy,
|
||||
CopyCheck,
|
||||
} from '@/app/components/base/icons/src/vender/line/files'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import PromptEditor from '@/app/components/base/prompt-editor'
|
||||
import { INSERT_VARIABLE_VALUE_BLOCK_COMMAND } from '@/app/components/base/prompt-editor/plugins/variable-block'
|
||||
import ConfigContext from '@/context/debug-configuration'
|
||||
@ -183,18 +179,13 @@ const AdvancedPromptInput: FC<Props> = ({
|
||||
<div className="text-sm font-semibold text-indigo-800 uppercase">
|
||||
{t('pageTitle.line1', { ns: 'appDebug' })}
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<span className="ml-1 i-ri-question-line h-4 w-4 shrink-0 text-text-quaternary" />
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
<div className="w-[180px]">
|
||||
{t('promptTip', { ns: 'appDebug' })}
|
||||
</div>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Infotip
|
||||
aria-label={t('promptTip', { ns: 'appDebug' })}
|
||||
className="ml-1"
|
||||
popupClassName="w-[180px]"
|
||||
>
|
||||
{t('promptTip', { ns: 'appDebug' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
)}
|
||||
<div className={cn(s.optionWrap, 'items-center space-x-1')}>
|
||||
|
||||
@ -5,11 +5,6 @@ import type { PromptVariable } from '@/models/debug'
|
||||
import type { GenRes } from '@/service/debug'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { toast } from '@langgenius/dify-ui/toast'
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from '@langgenius/dify-ui/tooltip'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import { noop } from 'es-toolkit/function'
|
||||
import { produce } from 'immer'
|
||||
@ -21,6 +16,7 @@ import { ADD_EXTERNAL_DATA_TOOL } from '@/app/components/app/configuration/confi
|
||||
import AutomaticBtn from '@/app/components/app/configuration/config/automatic/automatic-btn'
|
||||
import GetAutomaticResModal from '@/app/components/app/configuration/config/automatic/get-automatic-res'
|
||||
import { useFeaturesStore } from '@/app/components/base/features/hooks'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import PromptEditor from '@/app/components/base/prompt-editor'
|
||||
import { PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER } from '@/app/components/base/prompt-editor/plugins/update-block'
|
||||
import { INSERT_VARIABLE_VALUE_BLOCK_COMMAND } from '@/app/components/base/prompt-editor/plugins/variable-block'
|
||||
@ -183,18 +179,13 @@ const Prompt: FC<ISimplePromptInput> = ({
|
||||
<div className="flex items-center space-x-1">
|
||||
<div className="system-sm-semibold-uppercase text-text-secondary">{mode !== AppModeEnum.COMPLETION ? t('chatSubTitle', { ns: 'appDebug' }) : t('completionSubTitle', { ns: 'appDebug' })}</div>
|
||||
{!readonly && (
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<span className="ml-1 i-ri-question-line h-4 w-4 shrink-0 text-text-quaternary" />
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
<div className="w-[180px]">
|
||||
{t('promptTip', { ns: 'appDebug' })}
|
||||
</div>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Infotip
|
||||
aria-label={t('promptTip', { ns: 'appDebug' })}
|
||||
className="ml-1"
|
||||
popupClassName="w-[180px]"
|
||||
>
|
||||
{t('promptTip', { ns: 'appDebug' })}
|
||||
</Infotip>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
|
||||
@ -369,7 +369,7 @@ describe('OpeningSettingModal', () => {
|
||||
expect(screen.getByTestId('opener-input-section')).toBeInTheDocument()
|
||||
expect(screen.getByTestId('opener-questions-section')).toBeInTheDocument()
|
||||
expect(screen.getByText(/openingStatement\.editorTitle/)).toBeInTheDocument()
|
||||
expect(screen.getByTestId('opening-questions-tooltip')).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: /openingStatement\.openingQuestionDescription/ })).toBeInTheDocument()
|
||||
expect(screen.queryByText(/openingStatement\.openingQuestionDescription/)).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
@ -383,7 +383,7 @@ describe('OpeningSettingModal', () => {
|
||||
)
|
||||
|
||||
act(() => {
|
||||
fireEvent.mouseEnter(screen.getByTestId('opening-questions-tooltip'))
|
||||
fireEvent.mouseEnter(screen.getByRole('button', { name: /openingStatement\.openingQuestionDescription/ }))
|
||||
})
|
||||
|
||||
expect(screen.getByText(/openingStatement\.openingQuestionDescription/)).toBeInTheDocument()
|
||||
|
||||
@ -4,7 +4,6 @@ import type { PromptVariable } from '@/models/debug'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Dialog, DialogContent } from '@langgenius/dify-ui/dialog'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import { produce } from 'immer'
|
||||
import * as React from 'react'
|
||||
@ -14,6 +13,7 @@ import { ReactSortable } from 'react-sortablejs'
|
||||
import ConfirmAddVar from '@/app/components/app/configuration/config-prompt/confirm-add-var'
|
||||
import { getInputKeys } from '@/app/components/base/block-input'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import PromptEditor from '@/app/components/base/prompt-editor'
|
||||
import { checkKeys, getNewVar } from '@/utils/var'
|
||||
|
||||
@ -117,24 +117,14 @@ const OpeningSettingModal = ({
|
||||
<div className="text-sm font-medium text-text-primary">
|
||||
{t('openingStatement.openingQuestion', { ns: 'appDebug' })}
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
delay={0}
|
||||
render={(
|
||||
<button
|
||||
type="button"
|
||||
className="flex items-center rounded-sm p-px text-text-quaternary hover:text-text-tertiary"
|
||||
data-testid="opening-questions-tooltip"
|
||||
aria-label={t('openingStatement.openingQuestionDescription', { ns: 'appDebug' })}
|
||||
>
|
||||
<span className="i-ri-question-line h-3.5 w-3.5" />
|
||||
</button>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent className="max-w-[220px] system-sm-regular text-text-secondary">
|
||||
{t('openingStatement.openingQuestionDescription', { ns: 'appDebug' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Infotip
|
||||
aria-label={t('openingStatement.openingQuestionDescription', { ns: 'appDebug' })}
|
||||
className="h-3.5 w-3.5"
|
||||
popupClassName="max-w-[220px] system-sm-regular text-text-secondary"
|
||||
delay={0}
|
||||
>
|
||||
{t('openingStatement.openingQuestionDescription', { ns: 'appDebug' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
<div className="text-xs leading-[18px] font-medium text-text-tertiary">
|
||||
{tempSuggestedQuestions.length}
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
import { Switch } from '@langgenius/dify-ui/switch'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import {
|
||||
RiQuestionLine,
|
||||
} from '@remixicon/react'
|
||||
import * as React from 'react'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
|
||||
type Props = {
|
||||
icon: any
|
||||
@ -41,16 +38,12 @@ const FeatureCard = ({
|
||||
<div className="flex grow items-center system-sm-semibold text-text-secondary">
|
||||
{title}
|
||||
{tooltip && (
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="ml-0.5 p-px"><RiQuestionLine className="h-3.5 w-3.5 text-text-quaternary" /></div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{tooltip}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Infotip
|
||||
aria-label={typeof tooltip === 'string' ? tooltip : String(title)}
|
||||
className="ml-0.5 h-3.5 w-3.5"
|
||||
>
|
||||
{tooltip}
|
||||
</Infotip>
|
||||
)}
|
||||
</div>
|
||||
<Switch disabled={disabled} className="shrink-0" onCheckedChange={state => onChange?.(state)} checked={value} />
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import type { Placement } from '@langgenius/dify-ui/popover'
|
||||
import type { ReactNode } from 'react'
|
||||
import type { MouseEvent, ReactNode } from 'react'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
|
||||
|
||||
@ -58,6 +58,10 @@ export function Infotip({
|
||||
delay = 300,
|
||||
closeDelay = 200,
|
||||
}: InfotipProps) {
|
||||
const handleClick = (event: MouseEvent<HTMLButtonElement>) => {
|
||||
event.stopPropagation()
|
||||
}
|
||||
|
||||
return (
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
@ -65,6 +69,7 @@ export function Infotip({
|
||||
delay={delay}
|
||||
closeDelay={closeDelay}
|
||||
aria-label={ariaLabel}
|
||||
onClick={handleClick}
|
||||
className={cn(
|
||||
'inline-flex h-4 w-4 shrink-0 cursor-pointer items-center justify-center border-0 bg-transparent p-0 focus-visible:ring-1 focus-visible:ring-components-input-border-hover focus-visible:outline-hidden',
|
||||
className,
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
import type { FC } from 'react'
|
||||
import type { PreProcessingRule, SummaryIndexSetting as SummaryIndexSettingType } from '@/models/datasets'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import {
|
||||
RiAlertFill,
|
||||
RiSearchEyeLine,
|
||||
@ -11,6 +10,7 @@ import {
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Checkbox from '@/app/components/base/checkbox'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import SummaryIndexSetting from '@/app/components/datasets/settings/summary-index-setting'
|
||||
import { IS_CE_EDITION } from '@/config'
|
||||
import { ChunkingMode } from '@/models/datasets'
|
||||
@ -191,18 +191,13 @@ export const GeneralChunkingOptions: FC<GeneralChunkingOptionsProps> = ({
|
||||
onSelect={onDocLanguageChange}
|
||||
disabled={currentDocForm !== ChunkingMode.qa}
|
||||
/>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<span className="flex h-3.5 w-3.5 shrink-0 p-px">
|
||||
<span aria-hidden className="i-ri-question-line h-full w-full text-text-quaternary hover:text-text-tertiary" />
|
||||
</span>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('stepTwo.QATip', { ns: 'datasetCreation' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Infotip
|
||||
aria-label={t('stepTwo.QATip', { ns: 'datasetCreation' })}
|
||||
className="h-3.5 w-3.5"
|
||||
iconClassName="h-full w-full"
|
||||
>
|
||||
{t('stepTwo.QATip', { ns: 'datasetCreation' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
{currentDocForm === ChunkingMode.qa && (
|
||||
<div
|
||||
|
||||
@ -14,7 +14,9 @@ describe('IndexMethod', () => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
const getKeywordSlider = () => screen.getByLabelText('datasetSettings.form.numberOfKeywords')
|
||||
const getKeywordSlider = () => screen.getByLabelText('datasetSettings.form.numberOfKeywords', {
|
||||
selector: 'input[type="range"]',
|
||||
})
|
||||
|
||||
describe('Rendering', () => {
|
||||
it('should render without crashing', () => {
|
||||
|
||||
@ -11,7 +11,9 @@ describe('KeyWordNumber', () => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
const getSlider = () => screen.getByLabelText('datasetSettings.form.numberOfKeywords')
|
||||
const getSlider = () => screen.getByLabelText('datasetSettings.form.numberOfKeywords', {
|
||||
selector: 'input[type="range"]',
|
||||
})
|
||||
|
||||
describe('Rendering', () => {
|
||||
it('should render without crashing', () => {
|
||||
@ -24,9 +26,10 @@ describe('KeyWordNumber', () => {
|
||||
expect(screen.getByText(/form\.numberOfKeywords/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render tooltip with question icon', () => {
|
||||
it('should render infotip with question icon', () => {
|
||||
render(<KeyWordNumber {...defaultProps} />)
|
||||
const container = screen.getByText(/form\.numberOfKeywords/).closest('div')?.parentElement
|
||||
const trigger = screen.getByRole('button', { name: 'datasetSettings.form.numberOfKeywords' })
|
||||
const container = trigger.parentElement
|
||||
const questionIcon = container?.querySelector('.i-ri-question-line')
|
||||
expect(questionIcon).toBeInTheDocument()
|
||||
})
|
||||
|
||||
@ -7,10 +7,10 @@ import {
|
||||
NumberFieldInput,
|
||||
} from '@langgenius/dify-ui/number-field'
|
||||
import { Slider } from '@langgenius/dify-ui/slider'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import * as React from 'react'
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
|
||||
const MIN_KEYWORD_NUMBER = 0
|
||||
const MAX_KEYWORD_NUMBER = 50
|
||||
@ -36,16 +36,12 @@ const KeyWordNumber = ({
|
||||
<div className="truncate system-xs-medium text-text-secondary">
|
||||
{t('form.numberOfKeywords', { ns: 'datasetSettings' })}
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<span className="i-ri-question-line h-3.5 w-3.5 text-text-quaternary" />
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('form.numberOfKeywords', { ns: 'datasetSettings' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Infotip
|
||||
aria-label={t('form.numberOfKeywords', { ns: 'datasetSettings' })}
|
||||
className="h-3.5 w-3.5"
|
||||
>
|
||||
{t('form.numberOfKeywords', { ns: 'datasetSettings' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
<Slider
|
||||
className="mr-3 w-[206px] shrink-0"
|
||||
|
||||
@ -15,6 +15,7 @@ import { useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Badge from '@/app/components/base/badge/index'
|
||||
import GridMask from '@/app/components/base/grid-mask'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import UpgradeBtn from '@/app/components/billing/upgrade-btn'
|
||||
import s from '@/app/components/custom/style.module.css'
|
||||
import { AddCredentialInLoadBalancing } from '@/app/components/header/account-setting/model-provider-page/model-auth'
|
||||
@ -152,18 +153,14 @@ const ModelLoadBalancingConfigs = ({
|
||||
<div className="grow">
|
||||
<div className="flex items-center gap-1 text-sm text-text-primary">
|
||||
{t('modelProvider.loadBalancing', { ns: 'common' })}
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<span className="flex h-3 w-3 shrink-0 p-px">
|
||||
<span aria-hidden className="i-ri-question-line h-full w-full text-text-quaternary hover:text-text-tertiary" />
|
||||
</span>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent className="max-w-[300px]">
|
||||
{t('modelProvider.loadBalancingInfo', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Infotip
|
||||
aria-label={t('modelProvider.loadBalancingInfo', { ns: 'common' })}
|
||||
className="h-3 w-3"
|
||||
iconClassName="h-full w-full"
|
||||
popupClassName="max-w-[300px]"
|
||||
>
|
||||
{t('modelProvider.loadBalancingInfo', { ns: 'common' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
<div className="text-xs text-text-tertiary">{t('modelProvider.loadBalancingDescription', { ns: 'common' })}</div>
|
||||
</div>
|
||||
|
||||
@ -2,16 +2,15 @@ import type { Node } from 'reactflow'
|
||||
import type { ToolValue } from '@/app/components/workflow/block-selector/types'
|
||||
import type { NodeOutPutVar } from '@/app/components/workflow/types'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import {
|
||||
RiAddLine,
|
||||
RiQuestionLine,
|
||||
} from '@remixicon/react'
|
||||
import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import { ArrowDownRoundFill } from '@/app/components/base/icons/src/vender/solid/general'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import ToolSelector from '@/app/components/plugins/plugin-detail-panel/tool-selector'
|
||||
import { useMCPToolAvailability } from '@/app/components/workflow/nodes/_base/components/mcp-tool-availability'
|
||||
import { useAllMCPTools } from '@/service/use-tools'
|
||||
@ -21,7 +20,7 @@ type Props = {
|
||||
value: ToolValue[]
|
||||
label: string
|
||||
required?: boolean
|
||||
tooltip?: any
|
||||
tooltip?: React.ReactNode
|
||||
supportCollapse?: boolean
|
||||
scope?: string
|
||||
onChange: (value: ToolValue[]) => void
|
||||
@ -111,18 +110,16 @@ const MultipleToolSelector = ({
|
||||
>
|
||||
<div className="flex h-6 items-center system-sm-semibold-uppercase text-text-secondary">{label}</div>
|
||||
{required && <div className="text-red-500">*</div>}
|
||||
{tooltip && (
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div><RiQuestionLine className="h-3.5 w-3.5 text-text-quaternary hover:text-text-tertiary" /></div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{tooltip}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{tooltip
|
||||
? (
|
||||
<Infotip
|
||||
aria-label={typeof tooltip === 'string' ? tooltip : label}
|
||||
className="h-3.5 w-3.5"
|
||||
>
|
||||
{tooltip}
|
||||
</Infotip>
|
||||
)
|
||||
: null}
|
||||
{supportCollapse && (
|
||||
<ArrowDownRoundFill
|
||||
className={cn(
|
||||
|
||||
@ -257,6 +257,10 @@ const createDefaultProps = (overrides: Partial<Parameters<typeof CreateSubscript
|
||||
...overrides,
|
||||
})
|
||||
|
||||
const getCreateButton = () => screen.getByRole('button', {
|
||||
name: /pluginTrigger\.subscription\.(createButton|empty\.button)/,
|
||||
})
|
||||
|
||||
const setupMocks = (config: {
|
||||
providerInfo?: TriggerProviderApiEntity
|
||||
oauthConfig?: TriggerOAuthConfig
|
||||
@ -353,7 +357,7 @@ describe('CreateSubscriptionButton', () => {
|
||||
|
||||
// Assert
|
||||
// Assert
|
||||
expect(screen.getByRole('button'))!.toBeInTheDocument()
|
||||
expect(getCreateButton()).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render icon button when buttonType is ICON_BUTTON', () => {
|
||||
@ -387,7 +391,7 @@ describe('CreateSubscriptionButton', () => {
|
||||
|
||||
// Assert
|
||||
// Assert
|
||||
expect(screen.getByRole('button'))!.toBeInTheDocument()
|
||||
expect(getCreateButton()).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should apply shape prop correctly', () => {
|
||||
@ -592,7 +596,7 @@ describe('CreateSubscriptionButton', () => {
|
||||
|
||||
// Assert
|
||||
// Assert
|
||||
expect(screen.getByRole('button'))!.toHaveTextContent('pluginTrigger.subscription.createButton.apiKey')
|
||||
expect(getCreateButton()).toHaveTextContent('pluginTrigger.subscription.createButton.apiKey')
|
||||
})
|
||||
|
||||
it('should display correct button text for MANUAL method', () => {
|
||||
@ -610,7 +614,7 @@ describe('CreateSubscriptionButton', () => {
|
||||
|
||||
// Assert
|
||||
// Assert
|
||||
expect(screen.getByRole('button'))!.toHaveTextContent('pluginTrigger.subscription.createButton.manual')
|
||||
expect(getCreateButton()).toHaveTextContent('pluginTrigger.subscription.createButton.manual')
|
||||
})
|
||||
|
||||
it('should display default button text when multiple methods are supported', () => {
|
||||
@ -628,7 +632,7 @@ describe('CreateSubscriptionButton', () => {
|
||||
|
||||
// Assert
|
||||
// Assert
|
||||
expect(screen.getByRole('button'))!.toHaveTextContent('pluginTrigger.subscription.empty.button')
|
||||
expect(getCreateButton()).toHaveTextContent('pluginTrigger.subscription.empty.button')
|
||||
})
|
||||
})
|
||||
|
||||
@ -780,7 +784,7 @@ describe('CreateSubscriptionButton', () => {
|
||||
|
||||
// Act
|
||||
render(<CreateSubscriptionButton {...props} />)
|
||||
const button = screen.getByRole('button')
|
||||
const button = getCreateButton()
|
||||
fireEvent.click(button)
|
||||
|
||||
// Assert - modal should not open
|
||||
@ -830,7 +834,7 @@ describe('CreateSubscriptionButton', () => {
|
||||
|
||||
// Act
|
||||
render(<CreateSubscriptionButton {...props} />)
|
||||
const button = screen.getByRole('button')
|
||||
const button = getCreateButton()
|
||||
fireEvent.click(button)
|
||||
|
||||
// Assert - modal should open
|
||||
@ -1328,7 +1332,7 @@ describe('CreateSubscriptionButton', () => {
|
||||
render(<CreateSubscriptionButton {...props} />)
|
||||
|
||||
// Assert - should not have settings divider
|
||||
const button = screen.getByRole('button')
|
||||
const button = getCreateButton()
|
||||
const divider = button.querySelector('.bg-text-primary-on-surface')
|
||||
expect(divider).not.toBeInTheDocument()
|
||||
})
|
||||
@ -1447,7 +1451,7 @@ describe('CreateSubscriptionButton', () => {
|
||||
render(<CreateSubscriptionButton {...props} />)
|
||||
|
||||
// Assert
|
||||
const button = screen.getByRole('button')
|
||||
const button = getCreateButton()
|
||||
expect(button)!.toHaveClass('w-full')
|
||||
})
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@ import { useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { ActionButton, ActionButtonState } from '@/app/components/base/action-button'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import { openOAuthPopup } from '@/hooks/use-oauth'
|
||||
import { useInitiateTriggerOAuth, useTriggerOAuthConfig, useTriggerProviderInfo } from '@/service/use-triggers'
|
||||
import { SupportedCreationMethods } from '../../../types'
|
||||
@ -124,18 +125,13 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU
|
||||
value: SupportedCreationMethods.MANUAL,
|
||||
label: t('subscription.addType.options.manual.description', { ns: 'pluginTrigger' }),
|
||||
extra: (
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<span className="flex h-3.5 w-3.5 shrink-0 p-px">
|
||||
<span aria-hidden className="i-ri-question-line h-full w-full text-text-quaternary hover:text-text-tertiary" />
|
||||
</span>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('subscription.addType.options.manual.tip', { ns: 'pluginTrigger' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Infotip
|
||||
aria-label={t('subscription.addType.options.manual.tip', { ns: 'pluginTrigger' })}
|
||||
className="h-3.5 w-3.5"
|
||||
iconClassName="h-full w-full"
|
||||
>
|
||||
{t('subscription.addType.options.manual.tip', { ns: 'pluginTrigger' })}
|
||||
</Infotip>
|
||||
),
|
||||
show: supportedMethods.includes(SupportedCreationMethods.MANUAL),
|
||||
},
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
'use client'
|
||||
import type { PluginDetail } from '@/app/components/plugins/types'
|
||||
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 { Infotip } from '@/app/components/base/infotip'
|
||||
import { CreateSubscriptionButton } from './create'
|
||||
import { CreateButtonType } from './create/types'
|
||||
import SubscriptionCard from './subscription-card'
|
||||
@ -31,18 +31,13 @@ export const SubscriptionListView: React.FC<SubscriptionListViewProps> = ({
|
||||
<span className="system-sm-semibold-uppercase text-text-secondary">
|
||||
{t('subscription.listNum', { ns: 'pluginTrigger', num: subscriptionCount })}
|
||||
</span>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<span className="flex h-3.5 w-3.5 shrink-0 p-px">
|
||||
<span aria-hidden className="i-ri-question-line h-full w-full text-text-quaternary hover:text-text-tertiary" />
|
||||
</span>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('subscription.list.tip', { ns: 'pluginTrigger' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Infotip
|
||||
aria-label={t('subscription.list.tip', { ns: 'pluginTrigger' })}
|
||||
className="h-3.5 w-3.5"
|
||||
iconClassName="h-full w-full"
|
||||
>
|
||||
{t('subscription.list.tip', { ns: 'pluginTrigger' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
)}
|
||||
<CreateSubscriptionButton
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
'use client'
|
||||
import type { TriggerSubscription } from '@/app/components/workflow/block-selector/types'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { RiCheckLine, RiDeleteBinLine, RiWebhookLine } from '@remixicon/react'
|
||||
import * as React from 'react'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import { CreateSubscriptionButton } from './create'
|
||||
import { CreateButtonType } from './create/types'
|
||||
import { DeleteConfirm } from './delete-confirm'
|
||||
@ -34,18 +34,13 @@ export const SubscriptionSelectorView: React.FC<SubscriptionSelectorProps> = ({
|
||||
<span className="system-sm-semibold-uppercase text-text-secondary">
|
||||
{t('subscription.listNum', { ns: 'pluginTrigger', num: subscriptionCount })}
|
||||
</span>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<span className="flex h-3.5 w-3.5 shrink-0 p-px">
|
||||
<span aria-hidden className="i-ri-question-line h-full w-full text-text-quaternary hover:text-text-tertiary" />
|
||||
</span>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('subscription.list.tip', { ns: 'pluginTrigger' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Infotip
|
||||
aria-label={t('subscription.list.tip', { ns: 'pluginTrigger' })}
|
||||
className="h-3.5 w-3.5"
|
||||
iconClassName="h-full w-full"
|
||||
>
|
||||
{t('subscription.list.tip', { ns: 'pluginTrigger' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
<CreateSubscriptionButton
|
||||
buttonType={CreateButtonType.ICON_BUTTON}
|
||||
|
||||
@ -23,6 +23,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import AppIcon from '@/app/components/base/app-icon'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import EmojiPickerInner from '@/app/components/base/emoji-picker/Inner'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import Input from '@/app/components/base/input'
|
||||
import Textarea from '@/app/components/base/textarea'
|
||||
import LabelSelector from '@/app/components/tools/labels/selector'
|
||||
@ -71,20 +72,16 @@ type WorkflowToolDrawerFrameProps = {
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
const InfoTooltip = ({ children }: { children: React.ReactNode }) => {
|
||||
const InfoTooltip = ({ children }: { children: string }) => {
|
||||
return (
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<span className="i-ri-question-line h-3.5 w-3.5 shrink-0 cursor-help text-text-quaternary hover:text-text-tertiary" />
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
<div className="w-[180px]">
|
||||
{children}
|
||||
</div>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Infotip
|
||||
aria-label={children}
|
||||
className="ml-1 h-3.5 w-3.5"
|
||||
iconClassName="h-3.5 w-3.5"
|
||||
popupClassName="w-[180px]"
|
||||
>
|
||||
{children}
|
||||
</Infotip>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -1,12 +1,6 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { FieldTitle } from '../field-title'
|
||||
|
||||
vi.mock('@langgenius/dify-ui/tooltip', () => ({
|
||||
Tooltip: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
|
||||
TooltipTrigger: ({ render }: { render: React.ReactNode }) => <>{render}</>,
|
||||
TooltipContent: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
|
||||
}))
|
||||
|
||||
describe('FieldTitle', () => {
|
||||
it('should render title, subtitle, operation, tooltip and warning dot', () => {
|
||||
render(
|
||||
@ -21,7 +15,7 @@ describe('FieldTitle', () => {
|
||||
|
||||
expect(screen.getByText('Embedding')).toBeInTheDocument()
|
||||
expect(screen.getByText('subtitle')).toBeInTheDocument()
|
||||
expect(screen.getByText('Tooltip copy')).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: 'Tooltip copy' })).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: 'action' })).toBeInTheDocument()
|
||||
expect(document.querySelector('.bg-text-warning-secondary')).not.toBeNull()
|
||||
})
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import type { ReactNode } from 'react'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import {
|
||||
memo,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
|
||||
export type FieldTitleProps = {
|
||||
title?: string
|
||||
@ -62,18 +62,9 @@ export const FieldTitle = memo(({
|
||||
}
|
||||
{
|
||||
tooltip && (
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<span className="ml-1 flex h-4 w-4 shrink-0 items-center justify-center">
|
||||
<span aria-hidden className="i-ri-question-line h-3.5 w-3.5 text-text-quaternary hover:text-text-tertiary" />
|
||||
</span>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{tooltip}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Infotip aria-label={tooltip} className="ml-1">
|
||||
{tooltip}
|
||||
</Infotip>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Slider } from '@langgenius/dify-ui/slider'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { RiQuestionLine } from '@remixicon/react'
|
||||
import {
|
||||
memo,
|
||||
useCallback,
|
||||
@ -11,6 +9,7 @@ import {
|
||||
Economic,
|
||||
HighQuality,
|
||||
} from '@/app/components/base/icons/src/vender/knowledge'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import Input from '@/app/components/base/input'
|
||||
import { Field } from '@/app/components/workflow/nodes/_base/components/layout'
|
||||
import {
|
||||
@ -97,14 +96,12 @@ const IndexMethod = ({
|
||||
<div className="truncate system-xs-medium text-text-secondary">
|
||||
{t('form.numberOfKeywords', { ns: 'datasetSettings' })}
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={<RiQuestionLine className="ml-0.5 h-3.5 w-3.5 text-text-quaternary" />}
|
||||
/>
|
||||
<TooltipContent>
|
||||
number of keywords
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Infotip
|
||||
aria-label={t('form.numberOfKeywords', { ns: 'datasetSettings' })}
|
||||
className="ml-0.5 h-3.5 w-3.5"
|
||||
>
|
||||
{t('form.numberOfKeywords', { ns: 'datasetSettings' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
|
||||
@ -2,11 +2,11 @@ import type { FC } from 'react'
|
||||
import type { FormValue } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import type { Model } from '@/types/app'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { RiCloseLine, RiSparklingFill } from '@remixicon/react'
|
||||
import * as React from 'react'
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import Textarea from '@/app/components/base/textarea'
|
||||
import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal'
|
||||
|
||||
@ -80,18 +80,13 @@ const PromptEditor: FC<PromptEditorProps> = ({
|
||||
<div className="flex flex-col gap-y-1 px-4 py-2">
|
||||
<div className="flex h-6 items-center system-sm-semibold-uppercase text-text-secondary">
|
||||
<span>{t('nodes.llm.jsonSchema.instruction', { ns: 'workflow' })}</span>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<span className="flex h-3.5 w-3.5 shrink-0 p-px">
|
||||
<span aria-hidden className="i-ri-question-line h-full w-full text-text-quaternary hover:text-text-tertiary" />
|
||||
</span>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('nodes.llm.jsonSchema.promptTooltip', { ns: 'workflow' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Infotip
|
||||
aria-label={t('nodes.llm.jsonSchema.promptTooltip', { ns: 'workflow' })}
|
||||
className="h-3.5 w-3.5"
|
||||
iconClassName="h-full w-full"
|
||||
>
|
||||
{t('nodes.llm.jsonSchema.promptTooltip', { ns: 'workflow' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<Textarea
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { RiQuestionLine } from '@remixicon/react'
|
||||
import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
|
||||
type MonthlyDaysSelectorProps = {
|
||||
selectedDays: (number | 'last')[]
|
||||
@ -41,38 +40,46 @@ const MonthlyDaysSelector = ({ selectedDays, onChange }: MonthlyDaysSelectorProp
|
||||
{rows.map((row, rowIndex) => (
|
||||
<div key={rowIndex} className="grid grid-cols-7 gap-1.5">
|
||||
{row.map(day => (
|
||||
<button
|
||||
key={day}
|
||||
type="button"
|
||||
onClick={() => handleDayClick(day)}
|
||||
className={`rounded-lg border bg-components-option-card-option-bg py-1 text-xs transition-colors ${
|
||||
day === 'last' ? 'col-span-2 min-w-0' : ''
|
||||
} ${
|
||||
isDaySelected(day)
|
||||
? 'border-util-colors-blue-brand-blue-brand-600 text-text-secondary'
|
||||
: 'border-divider-subtle text-text-tertiary hover:border-divider-regular hover:text-text-secondary'
|
||||
}`}
|
||||
>
|
||||
{day === 'last'
|
||||
? (
|
||||
<div className="flex items-center justify-center gap-1">
|
||||
<span>{t('nodes.triggerSchedule.lastDay', { ns: 'workflow' })}</span>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<RiQuestionLine className="h-3 w-3 text-text-quaternary" />
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('nodes.triggerSchedule.lastDayTooltip', { ns: 'workflow' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
day
|
||||
)}
|
||||
</button>
|
||||
day === 'last'
|
||||
? (
|
||||
<div
|
||||
key={day}
|
||||
className={`col-span-2 flex min-w-0 items-center rounded-lg border bg-components-option-card-option-bg text-xs transition-colors ${
|
||||
isDaySelected(day)
|
||||
? 'border-util-colors-blue-brand-blue-brand-600 text-text-secondary'
|
||||
: 'border-divider-subtle text-text-tertiary hover:border-divider-regular hover:text-text-secondary'
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleDayClick(day)}
|
||||
className="min-w-0 flex-1 py-1"
|
||||
>
|
||||
{t('nodes.triggerSchedule.lastDay', { ns: 'workflow' })}
|
||||
</button>
|
||||
<Infotip
|
||||
aria-label={t('nodes.triggerSchedule.lastDayTooltip', { ns: 'workflow' })}
|
||||
className="mr-1 h-3 w-3"
|
||||
iconClassName="h-3 w-3"
|
||||
>
|
||||
{t('nodes.triggerSchedule.lastDayTooltip', { ns: 'workflow' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
<button
|
||||
key={day}
|
||||
type="button"
|
||||
onClick={() => handleDayClick(day)}
|
||||
className={`rounded-lg border bg-components-option-card-option-bg py-1 text-xs transition-colors ${
|
||||
isDaySelected(day)
|
||||
? 'border-util-colors-blue-brand-blue-brand-600 text-text-secondary'
|
||||
: 'border-divider-subtle text-text-tertiary hover:border-divider-regular hover:text-text-secondary'
|
||||
}`}
|
||||
>
|
||||
{day}
|
||||
</button>
|
||||
)
|
||||
))}
|
||||
{/* Fill empty cells in the last row (Last day takes 2 cols, so need 1 less) */}
|
||||
{rowIndex === rows.length - 1 && Array.from({ length: 7 - row.length - 1 }, (_, i) => (
|
||||
|
||||
Loading…
Reference in New Issue
Block a user