diff --git a/eslint-suppressions.json b/eslint-suppressions.json index f8208a8265..ced0d27afe 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -119,11 +119,6 @@ "count": 3 } }, - "web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-popup.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-panel.tsx": { "ts/no-explicit-any": { "count": 1 @@ -526,11 +521,6 @@ "count": 2 } }, - "web/app/components/app/configuration/debug/debug-with-multiple-model/model-parameter-trigger.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/app/configuration/debug/debug-with-multiple-model/text-generation-item.tsx": { "ts/no-explicit-any": { "count": 8 @@ -559,11 +549,6 @@ "count": 1 } }, - "web/app/components/app/configuration/prompt-value-panel/index.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/app/configuration/prompt-value-panel/utils.ts": { "ts/no-explicit-any": { "count": 1 @@ -620,9 +605,6 @@ } }, "web/app/components/app/log/list.tsx": { - "no-restricted-imports": { - "count": 1 - }, "react/set-state-in-effect": { "count": 6 }, @@ -645,7 +627,7 @@ }, "web/app/components/app/overview/embedded/index.tsx": { "no-restricted-imports": { - "count": 2 + "count": 1 }, "react/set-state-in-effect": { "count": 1 @@ -791,11 +773,6 @@ "count": 3 } }, - "web/app/components/base/audio-btn/index.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/base/audio-gallery/AudioPlayer.tsx": { "ts/no-explicit-any": { "count": 2 @@ -871,9 +848,6 @@ } }, "web/app/components/base/chat/chat-with-history/header/index.tsx": { - "no-restricted-imports": { - "count": 1 - }, "ts/no-explicit-any": { "count": 2 } @@ -991,11 +965,6 @@ "count": 7 } }, - "web/app/components/base/chat/embedded-chatbot/header/index.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/base/chat/embedded-chatbot/hooks.tsx": { "react-hooks-extra/no-direct-set-state-in-use-effect": { "count": 3 @@ -1037,11 +1006,6 @@ "count": 1 } }, - "web/app/components/base/copy-feedback/index.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/base/date-and-time-picker/hooks.ts": { "react/no-unnecessary-use-prefix": { "count": 2 @@ -1093,11 +1057,6 @@ "count": 1 } }, - "web/app/components/base/features/new-feature-panel/annotation-reply/annotation-ctrl-button.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/base/features/new-feature-panel/annotation-reply/config-param-modal.tsx": { "no-restricted-imports": { "count": 1 @@ -1123,15 +1082,7 @@ "count": 2 } }, - "web/app/components/base/features/new-feature-panel/feature-bar.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/base/features/new-feature-panel/feature-card.tsx": { - "no-restricted-imports": { - "count": 1 - }, "ts/no-explicit-any": { "count": 5 } @@ -1168,9 +1119,6 @@ } }, "web/app/components/base/file-uploader/file-list-in-log.tsx": { - "no-restricted-imports": { - "count": 1 - }, "react/no-missing-key": { "count": 1 } @@ -1193,11 +1141,6 @@ "count": 2 } }, - "web/app/components/base/file-uploader/pdf-preview.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/base/file-uploader/store.tsx": { "react-refresh/only-export-components": { "count": 4 @@ -1593,15 +1536,7 @@ "count": 1 } }, - "web/app/components/base/image-uploader/image-list.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/base/image-uploader/image-preview.tsx": { - "no-restricted-imports": { - "count": 1 - }, "ts/no-explicit-any": { "count": 1 } @@ -1764,9 +1699,6 @@ } }, "web/app/components/base/new-audio-button/index.tsx": { - "no-restricted-imports": { - "count": 1 - }, "ts/no-explicit-any": { "count": 1 } @@ -1949,11 +1881,6 @@ "count": 1 } }, - "web/app/components/base/qrcode/index.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/base/radio-card/index.stories.tsx": { "ts/no-explicit-any": { "count": 1 @@ -2262,11 +2189,6 @@ "count": 1 } }, - "web/app/components/datasets/create/step-two/components/general-chunking-options.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/datasets/create/step-two/components/index.ts": { "no-barrel-files/no-barrel-files": { "count": 5 @@ -2374,11 +2296,6 @@ "count": 1 } }, - "web/app/components/datasets/documents/components/document-list/components/document-table-row.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/datasets/documents/components/document-list/components/index.ts": { "no-barrel-files/no-barrel-files": { "count": 2 @@ -2553,11 +2470,6 @@ "count": 1 } }, - "web/app/components/datasets/documents/detail/metadata/components/doc-type-selector.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/datasets/documents/detail/metadata/components/metadata-field-list.tsx": { "ts/no-non-null-asserted-optional-chain": { "count": 1 @@ -2619,11 +2531,6 @@ "count": 1 } }, - "web/app/components/datasets/hit-testing/components/query-input/textarea.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/datasets/hit-testing/components/result-item-external.tsx": { "no-restricted-imports": { "count": 1 @@ -2639,21 +2546,11 @@ "count": 1 } }, - "web/app/components/datasets/list/dataset-card/components/dataset-card-footer.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/datasets/list/dataset-card/hooks/use-dataset-card-state.ts": { "react/set-state-in-effect": { "count": 1 } }, - "web/app/components/datasets/metadata/edit-metadata-batch/edited-beacon.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/datasets/metadata/edit-metadata-batch/input-combined.tsx": { "ts/no-explicit-any": { "count": 2 @@ -2722,11 +2619,6 @@ "count": 1 } }, - "web/app/components/datasets/settings/index-method/keyword-number.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/datasets/settings/summary-index-setting.tsx": { "no-restricted-imports": { "count": 1 @@ -2790,11 +2682,6 @@ "count": 1 } }, - "web/app/components/explore/try-app/app/chat.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/explore/try-app/index.tsx": { "no-restricted-imports": { "count": 1 @@ -3043,15 +2930,7 @@ "count": 2 } }, - "web/app/components/header/account-setting/model-provider-page/model-selector/feature-icon.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/header/account-setting/model-provider-page/provider-added-card/cooldown-timer.tsx": { - "no-restricted-imports": { - "count": 1 - }, "react/set-state-in-effect": { "count": 2 } @@ -3067,9 +2946,6 @@ } }, "web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx": { - "no-restricted-imports": { - "count": 1 - }, "ts/no-explicit-any": { "count": 5 } @@ -3085,11 +2961,6 @@ "count": 3 } }, - "web/app/components/header/account-setting/model-provider-page/provider-added-card/priority-use-tip.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/header/account-setting/model-provider-page/utils.ts": { "no-barrel-files/no-barrel-files": { "count": 2 @@ -3182,20 +3053,12 @@ "count": 1 } }, - "web/app/components/plugins/plugin-auth/authorize/index.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/plugins/plugin-auth/authorized-in-node.tsx": { "ts/no-explicit-any": { "count": 1 } }, "web/app/components/plugins/plugin-auth/authorized/item.tsx": { - "no-restricted-imports": { - "count": 1 - }, "ts/no-explicit-any": { "count": 1 } @@ -3290,9 +3153,6 @@ } }, "web/app/components/plugins/plugin-detail-panel/multiple-tool-selector/index.tsx": { - "no-restricted-imports": { - "count": 1 - }, "ts/no-explicit-any": { "count": 1 } @@ -3325,9 +3185,6 @@ "web/app/components/plugins/plugin-detail-panel/subscription-list/create/index.tsx": { "no-barrel-files/no-barrel-files": { "count": 3 - }, - "no-restricted-imports": { - "count": 1 } }, "web/app/components/plugins/plugin-detail-panel/subscription-list/create/oauth-client.tsx": { @@ -3363,11 +3220,6 @@ "count": 2 } }, - "web/app/components/plugins/plugin-detail-panel/subscription-list/list-view.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/plugins/plugin-detail-panel/subscription-list/log-viewer.tsx": { "erasable-syntax-only/enums": { "count": 1 @@ -3376,11 +3228,6 @@ "count": 2 } }, - "web/app/components/plugins/plugin-detail-panel/subscription-list/selector-view.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/plugins/plugin-detail-panel/subscription-list/subscription-card.tsx": { "no-restricted-imports": { "count": 1 @@ -3403,7 +3250,7 @@ }, "web/app/components/plugins/plugin-detail-panel/tool-selector/components/tool-item.tsx": { "no-restricted-imports": { - "count": 2 + "count": 1 } }, "web/app/components/plugins/plugin-detail-panel/tool-selector/hooks/index.ts": { @@ -3444,11 +3291,6 @@ "count": 2 } }, - "web/app/components/plugins/plugin-page/index.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/plugins/plugin-page/install-plugin-dropdown.tsx": { "react/set-state-in-effect": { "count": 2 @@ -4090,11 +3932,6 @@ "count": 1 } }, - "web/app/components/workflow/nodes/_base/components/config-vision.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/workflow/nodes/_base/components/editor/code-editor/editor-support-vars.tsx": { "react/set-state-in-effect": { "count": 1 @@ -4143,9 +3980,6 @@ } }, "web/app/components/workflow/nodes/_base/components/input-support-select-var.tsx": { - "no-restricted-imports": { - "count": 1 - }, "ts/no-explicit-any": { "count": 1 } @@ -4209,9 +4043,6 @@ } }, "web/app/components/workflow/nodes/_base/components/setting-item.tsx": { - "no-restricted-imports": { - "count": 1 - }, "ts/no-explicit-any": { "count": 1 } @@ -4226,11 +4057,6 @@ "count": 8 } }, - "web/app/components/workflow/nodes/_base/components/variable/object-child-tree-panel/picker/field.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/workflow/nodes/_base/components/variable/output-var-list.tsx": { "ts/no-non-null-asserted-optional-chain": { "count": 1 @@ -4544,11 +4370,6 @@ "count": 1 } }, - "web/app/components/workflow/nodes/human-input/components/delivery-method/index.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/workflow/nodes/human-input/components/delivery-method/method-item.tsx": { "no-restricted-imports": { "count": 1 @@ -4664,11 +4485,6 @@ "count": 1 } }, - "web/app/components/workflow/nodes/knowledge-base/components/index-method.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/workflow/nodes/knowledge-base/components/retrieval-setting/hooks.tsx": { "ts/no-explicit-any": { "count": 4 @@ -4806,11 +4622,6 @@ "count": 2 } }, - "web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-generator/prompt-editor.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/context.tsx": { "react-refresh/only-export-components": { "count": 2 @@ -5144,11 +4955,6 @@ "count": 7 } }, - "web/app/components/workflow/nodes/trigger-schedule/components/monthly-days-selector.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/workflow/nodes/trigger-schedule/default.ts": { "regexp/no-unused-capturing-group": { "count": 2 @@ -5286,11 +5092,6 @@ "count": 12 } }, - "web/app/components/workflow/panel/debug-and-preview/index.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/workflow/panel/env-panel/variable-modal.tsx": { "no-restricted-imports": { "count": 1 @@ -5515,9 +5316,6 @@ } }, "web/app/components/workflow/variable-inspect/group.tsx": { - "no-restricted-imports": { - "count": 1 - }, "ts/no-explicit-any": { "count": 2 } @@ -5541,17 +5339,11 @@ } }, "web/app/components/workflow/variable-inspect/right.tsx": { - "no-restricted-imports": { - "count": 1 - }, "ts/no-explicit-any": { "count": 3 } }, "web/app/components/workflow/variable-inspect/trigger.tsx": { - "no-restricted-imports": { - "count": 1 - }, "ts/no-explicit-any": { "count": 1 } diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-popup.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-popup.tsx index 471ab86e12..2b0f978906 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-popup.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-popup.tsx @@ -3,12 +3,12 @@ import type { FC, JSX } from 'react' import type { AliyunConfig, ArizeConfig, DatabricksConfig, LangFuseConfig, LangSmithConfig, MLflowConfig, OpikConfig, PhoenixConfig, TencentConfig, WeaveConfig } from './type' import { cn } from '@langgenius/dify-ui/cn' import { Switch } from '@langgenius/dify-ui/switch' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { useBoolean } from 'ahooks' 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 Indicator from '@/app/components/header/indicator' import ProviderConfigModal from './provider-config-modal' import ProviderPanel from './provider-panel' @@ -338,10 +338,13 @@ const ConfigPopup: FC = ({ <> {providerAllNotConfigured ? ( - - {switchContent} + + + + {t(`${I18N_PREFIX}.disabledTip`, { ns: 'app' })} + ) : switchContent} diff --git a/web/app/components/app/configuration/debug/debug-with-multiple-model/__tests__/model-parameter-trigger.spec.tsx b/web/app/components/app/configuration/debug/debug-with-multiple-model/__tests__/model-parameter-trigger.spec.tsx index 2edc6191de..b99a2034b6 100644 --- a/web/app/components/app/configuration/debug/debug-with-multiple-model/__tests__/model-parameter-trigger.spec.tsx +++ b/web/app/components/app/configuration/debug/debug-with-multiple-model/__tests__/model-parameter-trigger.spec.tsx @@ -5,6 +5,7 @@ import type { ModelProvider, } from '@/app/components/header/account-setting/model-provider-page/declarations' import { render, screen } from '@testing-library/react' +import userEvent from '@testing-library/user-event' import { createMockProviderContextValue } from '@/__mocks__/provider-context' import { ConfigurationMethodEnum, @@ -86,12 +87,6 @@ vi.mock('@/app/components/header/account-setting/model-provider-page/model-name' ), })) -vi.mock('@/app/components/base/tooltip', () => ({ - default: ({ children, popupContent }: { children: ReactNode, popupContent: string }) => ( -
{children}
- ), -})) - const createModelAndParameter = (overrides: Partial = {}): ModelAndParameter => ({ id: 'model-1', model: 'gpt-3.5-turbo', @@ -385,14 +380,15 @@ describe('ModelParameterTrigger', () => { expect(screen.getByText('common.modelProvider.selectModel')).toBeInTheDocument() }) - it('should render configured model id and incompatible tooltip when model is missing from the provider list', () => { + it('should render configured model id and incompatible tooltip when model is missing from the provider list', async () => { renderComponent() expect(screen.getByText('gpt-3.5-turbo')).toBeInTheDocument() - expect(screen.getByTestId('tooltip')).toHaveAttribute('data-content', 'common.modelProvider.selector.incompatibleTip') + await userEvent.hover(screen.getByLabelText('common.modelProvider.selector.incompatibleTip')) + expect(await screen.findByText('common.modelProvider.selector.incompatibleTip')).toBeInTheDocument() }) - it('should render configure required tooltip for no-configure status', () => { + it('should render configure required tooltip for no-configure status', async () => { const { unmount } = renderComponent() const triggerContent = capturedModalProps?.renderTrigger({ open: false, @@ -403,10 +399,11 @@ describe('ModelParameterTrigger', () => { unmount() render(<>{triggerContent}) - expect(screen.getByTestId('tooltip')).toHaveAttribute('data-content', 'common.modelProvider.selector.configureRequired') + await userEvent.hover(screen.getByLabelText('common.modelProvider.selector.configureRequired')) + expect(await screen.findByText('common.modelProvider.selector.configureRequired')).toBeInTheDocument() }) - it('should render disabled tooltip for disabled status', () => { + it('should render disabled tooltip for disabled status', async () => { const { unmount } = renderComponent() const triggerContent = capturedModalProps?.renderTrigger({ open: false, @@ -417,7 +414,8 @@ describe('ModelParameterTrigger', () => { unmount() render(<>{triggerContent}) - expect(screen.getByTestId('tooltip')).toHaveAttribute('data-content', 'common.modelProvider.selector.disabled') + await userEvent.hover(screen.getByLabelText('common.modelProvider.selector.disabled')) + expect(await screen.findByText('common.modelProvider.selector.disabled')).toBeInTheDocument() }) it('should apply expanded and warning styles when the trigger is open for a non-active status', () => { diff --git a/web/app/components/app/configuration/debug/debug-with-multiple-model/model-parameter-trigger.tsx b/web/app/components/app/configuration/debug/debug-with-multiple-model/model-parameter-trigger.tsx index a870538edc..bf889e20ea 100644 --- a/web/app/components/app/configuration/debug/debug-with-multiple-model/model-parameter-trigger.tsx +++ b/web/app/components/app/configuration/debug/debug-with-multiple-model/model-parameter-trigger.tsx @@ -1,9 +1,9 @@ import type { FC } from 'react' import type { ModelAndParameter } from '../types' import type { FormValue } from '@/app/components/header/account-setting/model-provider-page/declarations' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { memo } from 'react' import { useTranslation } from 'react-i18next' -import Tooltip from '@/app/components/base/tooltip' import { DERIVED_MODEL_STATUS_BADGE_I18N, DERIVED_MODEL_STATUS_TOOLTIP_I18N, @@ -132,8 +132,18 @@ const ModelParameterTrigger: FC = ({ { !isEmpty && !isActive && statusLabelKey && ( - - + + + )} + /> + + {t((statusTooltipKey || statusLabelKey) as 'modelProvider.selector.incompatible', { ns: 'common' })} + ) } diff --git a/web/app/components/app/configuration/prompt-value-panel/index.tsx b/web/app/components/app/configuration/prompt-value-panel/index.tsx index c3ba69bf34..c2a438b5e9 100644 --- a/web/app/components/app/configuration/prompt-value-panel/index.tsx +++ b/web/app/components/app/configuration/prompt-value-panel/index.tsx @@ -5,6 +5,7 @@ import type { VisionFile, VisionSettings } from '@/types/app' import { Button } from '@langgenius/dify-ui/button' import { cn } from '@langgenius/dify-ui/cn' import { Select, SelectContent, SelectItem, SelectItemIndicator, SelectItemText, SelectTrigger } from '@langgenius/dify-ui/select' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { RiArrowDownSLine, RiArrowRightSLine, @@ -19,7 +20,6 @@ import FeatureBar from '@/app/components/base/features/new-feature-panel/feature import TextGenerationImageUploader from '@/app/components/base/image-uploader/text-generation-image-uploader' import Input from '@/app/components/base/input' import Textarea from '@/app/components/base/textarea' -import Tooltip from '@/app/components/base/tooltip' import BoolInput from '@/app/components/workflow/nodes/_base/components/before-run-form/bool-input' import ConfigContext from '@/context/debug-configuration' import { AppModeEnum, ModelModeType } from '@/types/app' @@ -224,16 +224,23 @@ const PromptValuePanel: FC = ({
{canNotRun && ( - - + + onSend?.()} + className="w-[96px]" + > + )} {!canNotRun && ( diff --git a/web/app/components/app/log/list.tsx b/web/app/components/app/log/list.tsx index da96d41804..1633d53ccc 100644 --- a/web/app/components/app/log/list.tsx +++ b/web/app/components/app/log/list.tsx @@ -10,6 +10,7 @@ import { } from '@heroicons/react/24/outline' import { cn } from '@langgenius/dify-ui/cn' import { toast } from '@langgenius/dify-ui/toast' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { RiCloseLine, RiEditFill } from '@remixicon/react' import dayjs from 'dayjs' import timezone from 'dayjs/plugin/timezone' @@ -30,7 +31,6 @@ import CopyIcon from '@/app/components/base/copy-icon' import Drawer from '@/app/components/base/drawer' import Loading from '@/app/components/base/loading' import MessageLogModal from '@/app/components/base/message-log-modal' -import Tooltip from '@/app/components/base/tooltip' import { WorkflowContextProvider } from '@/app/components/workflow/context' import { useAppContext } from '@/context/app-context' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' @@ -409,10 +409,15 @@ function DetailPanel({ detail, onFeedback }: IDetailPanel) {
{isChatMode ? t('detail.conversationId', { ns: 'appLog' }) : t('detail.time', { ns: 'appLog' })}
{isChatMode && (
- -
{detail.id}
+ + {detail.id}
+ )} + /> + + {detail.id} +
@@ -769,18 +774,20 @@ const ConversationList: FC = ({ logs, appDetail, onRefresh }) // Annotated data needs to be highlighted const renderTdValue = (value: string | number | null, isEmptyStyle: boolean, isHighlight = false, annotation?: LogAnnotation) => { return ( - + + {value || '-'} + + )} + /> + {`${t('detail.annotationTip', { ns: 'appLog', user: annotation?.account?.name })} ${formatTime(annotation?.created_at || dayjs().unix(), 'MM-DD hh:mm A')}`} - )} - popupClassName={(isHighlight && !isChatMode) ? '' : 'hidden!'} - > -
- {value || '-'} -
+
) } diff --git a/web/app/components/app/overview/embedded/index.tsx b/web/app/components/app/overview/embedded/index.tsx index 029566587e..e810c7f1eb 100644 --- a/web/app/components/app/overview/embedded/index.tsx +++ b/web/app/components/app/overview/embedded/index.tsx @@ -1,5 +1,6 @@ import type { SiteInfo } from '@/models/share' import { cn } from '@langgenius/dify-ui/cn' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { RiClipboardFill, RiClipboardLine, @@ -11,7 +12,6 @@ import { useTranslation } from 'react-i18next' import ActionButton from '@/app/components/base/action-button' import { useThemeContext } from '@/app/components/base/chat/embedded-chatbot/theme/theme-context' import Modal from '@/app/components/base/modal' -import Tooltip from '@/app/components/base/tooltip' import { IS_CE_EDITION } from '@/config' import { useAppContext } from '@/context/app-context' import { basePath } from '@/utils/var' @@ -174,21 +174,24 @@ const Embedded = ({ siteInfo, isShow, onClose, appBaseUrl, accessToken, classNam
{t(`${prefixEmbedded}.${option}`, { ns: 'appOverview' })}
- + +
+ {isCopied[option] && } + {!isCopied[option] && } +
+ + )} + /> + + {(isCopied[option] ? t(`${prefixEmbedded}.copied`, { ns: 'appOverview' }) - : t(`${prefixEmbedded}.copy`, { ns: 'appOverview' })) || '' - } - > - -
- {isCopied[option] && } - {!isCopied[option] && } -
-
+ : t(`${prefixEmbedded}.copy`, { ns: 'appOverview' })) || ''} +
diff --git a/web/app/components/base/audio-btn/index.tsx b/web/app/components/base/audio-btn/index.tsx index 47fefe19e5..3ca453213d 100644 --- a/web/app/components/base/audio-btn/index.tsx +++ b/web/app/components/base/audio-btn/index.tsx @@ -1,9 +1,9 @@ 'use client' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { t } from 'i18next' import { useState } from 'react' import { AudioPlayerManager } from '@/app/components/base/audio-btn/audio.player.manager' import Loading from '@/app/components/base/loading' -import Tooltip from '@/app/components/base/tooltip' import { useParams, usePathname } from '@/next/navigation' import s from './style.module.css' @@ -82,27 +82,34 @@ const AudioBtn = ({ return (
- - + + + + + )} + /> + + {tooltipContent} +
) diff --git a/web/app/components/base/chat/chat-with-history/header/index.tsx b/web/app/components/base/chat/chat-with-history/header/index.tsx index 95b6146afa..75cfab4228 100644 --- a/web/app/components/base/chat/chat-with-history/header/index.tsx +++ b/web/app/components/base/chat/chat-with-history/header/index.tsx @@ -9,6 +9,7 @@ import { AlertDialogTitle, } from '@langgenius/dify-ui/alert-dialog' import { cn } from '@langgenius/dify-ui/cn' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { RiEditBoxLine, RiLayoutRight2Line, @@ -20,7 +21,6 @@ import ActionButton, { ActionButtonState } from '@/app/components/base/action-bu import AppIcon from '@/app/components/base/app-icon' import ViewFormDropdown from '@/app/components/base/chat/chat-with-history/inputs-form/view-form-dropdown' import RenameModal from '@/app/components/base/chat/chat-with-history/sidebar/rename-modal' -import Tooltip from '@/app/components/base/tooltip' import { useChatWithHistoryContext, } from '../context' @@ -117,31 +117,41 @@ const Header = () => {
{isSidebarCollapsed && ( - -
- - - -
+ + + + + + + )} + /> + + {t('chat.newChatTip', { ns: 'share' })} + )}
{currentConversationId && ( - - - - + + + + + )} + /> + + {t('chat.resetChat', { ns: 'share' })} + )} {currentConversationId && inputsForms.length > 0 && ( diff --git a/web/app/components/base/chat/embedded-chatbot/header/index.tsx b/web/app/components/base/chat/embedded-chatbot/header/index.tsx index 598e3068de..6d0cc9bc06 100644 --- a/web/app/components/base/chat/embedded-chatbot/header/index.tsx +++ b/web/app/components/base/chat/embedded-chatbot/header/index.tsx @@ -1,6 +1,7 @@ import type { FC } from 'react' import type { Theme } from '../theme/theme-context' import { cn } from '@langgenius/dify-ui/cn' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { useSuspenseQuery } from '@tanstack/react-query' import * as React from 'react' import { useCallback, useEffect, useState } from 'react' @@ -9,7 +10,6 @@ import ActionButton from '@/app/components/base/action-button' import ViewFormDropdown from '@/app/components/base/chat/embedded-chatbot/inputs-form/view-form-dropdown' import Divider from '@/app/components/base/divider' import DifyLogo from '@/app/components/base/logo/dify-logo' -import Tooltip from '@/app/components/base/tooltip' import { systemFeaturesQueryOptions } from '@/service/system-features' import { isClient } from '@/utils/client' import { @@ -111,26 +111,36 @@ const Header: FC = ({ )} { showToggleExpandButton && ( - - - { - expanded - ?
- :
- } - + + + { + expanded + ?
+ :
+ } + + )} + /> + + {expanded ? t('chat.collapse', { ns: 'share' }) : t('chat.expand', { ns: 'share' })} + ) } {currentConversationId && allowResetChat && ( - - -
- + + +
+ + )} + /> + + {t('chat.resetChat', { ns: 'share' })} + )} {currentConversationId && inputsForms.length > 0 && !allInputsHidden && ( @@ -158,26 +168,36 @@ const Header: FC = ({
{ showToggleExpandButton && ( - - - { - expanded - ?
- :
- } - + + + { + expanded + ?
+ :
+ } + + )} + /> + + {expanded ? t('chat.collapse', { ns: 'share' }) : t('chat.expand', { ns: 'share' })} + ) } {currentConversationId && allowResetChat && ( - - -
- + + +
+ + )} + /> + + {t('chat.resetChat', { ns: 'share' })} + )} {currentConversationId && inputsForms.length > 0 && !allInputsHidden && ( diff --git a/web/app/components/base/copy-feedback/index.tsx b/web/app/components/base/copy-feedback/index.tsx index 431b697a6a..860b88b245 100644 --- a/web/app/components/base/copy-feedback/index.tsx +++ b/web/app/components/base/copy-feedback/index.tsx @@ -1,4 +1,5 @@ 'use client' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { RiClipboardFill, RiClipboardLine, @@ -6,7 +7,6 @@ import { import { useCallback } from 'react' import { useTranslation } from 'react-i18next' import ActionButton from '@/app/components/base/action-button' -import Tooltip from '@/app/components/base/tooltip' import { useClipboard } from '@/hooks/use-clipboard' import copyStyle from './style.module.css' @@ -35,15 +35,20 @@ const CopyFeedback = ({ content }: Props) => { }, [copy, content]) return ( - - -
- {copied && } - {!copied && } -
-
+ + +
+ {copied && } + {!copied && } +
+ + )} + /> + + {safeText} +
) } @@ -65,18 +70,23 @@ export const CopyFeedbackNew = ({ content, className }: Pick -
-
-
-
+ + +
+
+
+ )} + /> + + {safeText} +
) } diff --git a/web/app/components/base/features/new-feature-panel/annotation-reply/annotation-ctrl-button.tsx b/web/app/components/base/features/new-feature-panel/annotation-reply/annotation-ctrl-button.tsx index 3f3e68b32e..090f4d459f 100644 --- a/web/app/components/base/features/new-feature-panel/annotation-reply/annotation-ctrl-button.tsx +++ b/web/app/components/base/features/new-feature-panel/annotation-reply/annotation-ctrl-button.tsx @@ -1,11 +1,11 @@ 'use client' import type { FC } from 'react' import { toast } from '@langgenius/dify-ui/toast' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { RiEditLine, RiFileEditLine } from '@remixicon/react' import * as React from 'react' import { useTranslation } from 'react-i18next' import ActionButton from '@/app/components/base/action-button' -import Tooltip from '@/app/components/base/tooltip' import { useModalContext } from '@/context/modal-context' import { useProviderContext } from '@/context/provider-context' import { addAnnotation } from '@/service/annotation' @@ -40,17 +40,31 @@ const AnnotationCtrlButton: FC = ({ cached, query, answer, appId, message return ( <> {cached && ( - - - - + + + + + )} + /> + + {t('feature.annotation.edit', { ns: 'appDebug' })} + )} {!cached && answer && ( - - - - + + + + + )} + /> + + {t('feature.annotation.add', { ns: 'appDebug' })} + )} diff --git a/web/app/components/base/features/new-feature-panel/feature-bar.tsx b/web/app/components/base/features/new-feature-panel/feature-bar.tsx index 9b442ca52f..bf9d1c6cf0 100644 --- a/web/app/components/base/features/new-feature-panel/feature-bar.tsx +++ b/web/app/components/base/features/new-feature-panel/feature-bar.tsx @@ -1,5 +1,6 @@ import { Button } from '@langgenius/dify-ui/button' import { cn } from '@langgenius/dify-ui/cn' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { RiApps2AddLine, RiArrowRightLine, RiSparklingFill } from '@remixicon/react' import * as React from 'react' import { useMemo, useState } from 'react' @@ -7,7 +8,6 @@ import { useTranslation } from 'react-i18next' import { useFeatures } from '@/app/components/base/features/hooks' import VoiceSettings from '@/app/components/base/features/new-feature-panel/text-to-speech/voice-settings' import { Citations, ContentModeration, FolderUpload, LoveMessage, MessageFast, Microphone01, TextToAudio, VirtualAssistant } from '@/app/components/base/icons/src/vender/features' -import Tooltip from '@/app/components/base/tooltip' type Props = { isChatMode?: boolean @@ -51,86 +51,131 @@ const FeatureBar = ({
{!!features.moreLikeThis?.enabled && ( - -
- -
+ + + +
+ )} + /> + + {t('feature.moreLikeThis.title', { ns: 'appDebug' })} + )} {!!features.opening?.enabled && ( - -
- -
+ + + +
+ )} + /> + + {t('feature.conversationOpener.title', { ns: 'appDebug' })} +
)} {!!features.moderation?.enabled && ( - -
- -
+ + + +
+ )} + /> + + {t('feature.moderation.title', { ns: 'appDebug' })} +
)} {!!features.speech2text?.enabled && ( - -
- -
+ + + +
+ )} + /> + + {t('feature.speechToText.title', { ns: 'appDebug' })} + )} {!!features.text2speech?.enabled && ( - -
- -
+ + + +
+ )} + /> + + {t('feature.textToSpeech.title', { ns: 'appDebug' })} +
)} {showFileUpload && !!features.file?.enabled && ( - -
- -
+ + + +
+ )} + /> + + {t('feature.fileUpload.title', { ns: 'appDebug' })} + )} {!!features.suggested?.enabled && ( - -
- -
+ + + +
+ )} + /> + + {t('feature.suggestedQuestionsAfterAnswer.title', { ns: 'appDebug' })} +
)} {isChatMode && !!features.citation?.enabled && ( - -
- -
+ + + +
+ )} + /> + + {t('feature.citation.title', { ns: 'appDebug' })} + )} {isChatMode && !!features.annotationReply?.enabled && ( - -
- -
+ + + +
+ )} + /> + + {t('feature.annotation.title', { ns: 'appDebug' })} +
)}
diff --git a/web/app/components/base/features/new-feature-panel/feature-card.tsx b/web/app/components/base/features/new-feature-panel/feature-card.tsx index 58725a31a1..0c25a514fe 100644 --- a/web/app/components/base/features/new-feature-panel/feature-card.tsx +++ b/web/app/components/base/features/new-feature-panel/feature-card.tsx @@ -1,9 +1,9 @@ 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 Tooltip from '@/app/components/base/tooltip' type Props = { icon: any @@ -41,10 +41,15 @@ const FeatureCard = ({
{title} {tooltip && ( - -
+ +
+ )} + /> + + {tooltip} +
)}
diff --git a/web/app/components/base/file-uploader/file-list-in-log.tsx b/web/app/components/base/file-uploader/file-list-in-log.tsx index 14dd171b59..9edd1ffed4 100644 --- a/web/app/components/base/file-uploader/file-list-in-log.tsx +++ b/web/app/components/base/file-uploader/file-list-in-log.tsx @@ -1,10 +1,10 @@ import type { FileEntity } from './types' import { cn } from '@langgenius/dify-ui/cn' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { RiArrowRightSLine } from '@remixicon/react' import * as React from 'react' import { useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' -import Tooltip from '@/app/components/base/tooltip' import { SupportUploadFileTypes } from '@/app/components/workflow/types' import FileImageRender from './file-image-render' import FileTypeIcon from './file-type-icon' @@ -49,27 +49,37 @@ const FileListInLog = ({ fileList, isExpanded = false, noBorder = false, noPaddi return ( <> {isImageFile && ( - -
- -
+ + + +
+ )} + /> + + {name} +
)} {!isImageFile && ( - -
- -
+ + + +
+ )} + /> + + {name} + )} diff --git a/web/app/components/base/file-uploader/pdf-preview.tsx b/web/app/components/base/file-uploader/pdf-preview.tsx index bfd115401b..c129f9cfb3 100644 --- a/web/app/components/base/file-uploader/pdf-preview.tsx +++ b/web/app/components/base/file-uploader/pdf-preview.tsx @@ -1,4 +1,5 @@ import type { FC } from 'react' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { RiCloseLine, RiZoomInLine, RiZoomOutLine } from '@remixicon/react' import { noop } from 'es-toolkit/function' import { t } from 'i18next' @@ -7,7 +8,6 @@ import { useState } from 'react' import { createPortal } from 'react-dom' import { useHotkeys } from 'react-hotkeys-hook' import Loading from '@/app/components/base/loading' -import Tooltip from '@/app/components/base/tooltip' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import { PdfHighlighter, PdfLoader } from './pdf-highlighter-adapter' @@ -76,29 +76,50 @@ const PdfPreview: FC = ({ }}
- -
- -
+ + + +
+ )} + /> + + {t('operation.zoomOut', { ns: 'common' })} +
- -
- -
+ + + + + )} + /> + + {t('operation.zoomIn', { ns: 'common' })} + - -
- -
+ + + + + )} + /> + + {t('operation.cancel', { ns: 'common' })} + , document.body, diff --git a/web/app/components/base/image-uploader/image-list.tsx b/web/app/components/base/image-uploader/image-list.tsx index c6cb977bb3..2e56b88f65 100644 --- a/web/app/components/base/image-uploader/image-list.tsx +++ b/web/app/components/base/image-uploader/image-list.tsx @@ -1,11 +1,11 @@ import type { FC } from 'react' import type { ImageFile } from '@/types/app' import { cn } from '@langgenius/dify-ui/cn' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { useState } from 'react' import { useTranslation } from 'react-i18next' import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback' import ImagePreview from '@/app/components/base/image-uploader/image-preview' -import Tooltip from '@/app/components/base/tooltip' import { TransferMethod } from '@/types/app' type ImageListProps = { @@ -82,10 +82,15 @@ const ImageList: FC = ({ )} {item.progress === -1 && ( - - + + + )} + /> + + {t('imageUploader.pasteImageLinkInvalid', { ns: 'common' })} + )} diff --git a/web/app/components/base/image-uploader/image-preview.tsx b/web/app/components/base/image-uploader/image-preview.tsx index 7cc4ec8a14..354fb5ff2a 100644 --- a/web/app/components/base/image-uploader/image-preview.tsx +++ b/web/app/components/base/image-uploader/image-preview.tsx @@ -1,12 +1,12 @@ import type { FC } from 'react' import { toast } from '@langgenius/dify-ui/toast' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { noop } from 'es-toolkit/function' import { t } from 'i18next' import * as React from 'react' import { useCallback, useEffect, useRef, useState } from 'react' import { createPortal } from 'react-dom' import { useHotkeys } from 'react-hotkeys-hook' -import Tooltip from '@/app/components/base/tooltip' import { downloadUrl } from '@/utils/download' type ImagePreviewProps = { @@ -198,55 +198,97 @@ const ImagePreview: FC = ({ }} data-testid="image-preview-image" /> - -
- {isCopied - ? - : } -
+ + + {isCopied + ? + : } + + )} + /> + + {t('operation.copyImage', { ns: 'common' })} + - -
- -
+ + + + + )} + /> + + {t('operation.zoomOut', { ns: 'common' })} + - -
- -
+ + + + + )} + /> + + {t('operation.zoomIn', { ns: 'common' })} + - -
- -
+ + + + + )} + /> + + {t('operation.download', { ns: 'common' })} + - -
- -
+ + + + + )} + /> + + {t('operation.openInNewTab', { ns: 'common' })} + - -
- -
+ + + + + )} + /> + + {t('operation.cancel', { ns: 'common' })} + , document.body, diff --git a/web/app/components/base/new-audio-button/index.tsx b/web/app/components/base/new-audio-button/index.tsx index c6569ff958..56ada77df6 100644 --- a/web/app/components/base/new-audio-button/index.tsx +++ b/web/app/components/base/new-audio-button/index.tsx @@ -1,4 +1,5 @@ 'use client' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { RiVolumeUpLine, } from '@remixicon/react' @@ -6,7 +7,6 @@ import { t } from 'i18next' import { useState } from 'react' import ActionButton, { ActionButtonState } from '@/app/components/base/action-button' import { AudioPlayerManager } from '@/app/components/base/audio-btn/audio.player.manager' -import Tooltip from '@/app/components/base/tooltip' import { useParams, usePathname } from '@/next/navigation' type AudioBtnProps = { @@ -78,20 +78,27 @@ const AudioBtn = ({ }[audioState] return ( - - - - + + + + + +
+ )} + /> + + {tooltipContent} +
) } diff --git a/web/app/components/base/qrcode/index.tsx b/web/app/components/base/qrcode/index.tsx index ba3946b185..cfc30d752b 100644 --- a/web/app/components/base/qrcode/index.tsx +++ b/web/app/components/base/qrcode/index.tsx @@ -1,10 +1,10 @@ 'use client' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { QRCodeCanvas as QRCode } from 'qrcode.react' import * as React from 'react' import { useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import ActionButton from '@/app/components/base/action-button' -import Tooltip from '@/app/components/base/tooltip' import { downloadUrl } from '@/utils/download' type Props = { @@ -54,28 +54,33 @@ const ShareQRCode = ({ content }: Props) => { const safeTooltipText = tooltipText || '' return ( - -
- - - - {isShow && ( -
- -
-
{t('overview.appInfo.qrcode.scan', { ns: 'appOverview' })}
-
·
-
{t('overview.appInfo.qrcode.download', { ns: 'appOverview' })}
-
+ + + + + + {isShow && ( +
+ +
+
{t('overview.appInfo.qrcode.scan', { ns: 'appOverview' })}
+
·
+
{t('overview.appInfo.qrcode.download', { ns: 'appOverview' })}
+
+
+ )}
)} -
+ /> + + {safeTooltipText} +
) } diff --git a/web/app/components/datasets/create/step-two/components/general-chunking-options.tsx b/web/app/components/datasets/create/step-two/components/general-chunking-options.tsx index e2be96da86..f0740e9cf4 100644 --- a/web/app/components/datasets/create/step-two/components/general-chunking-options.tsx +++ b/web/app/components/datasets/create/step-two/components/general-chunking-options.tsx @@ -3,6 +3,7 @@ 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, @@ -10,7 +11,6 @@ import { import { useTranslation } from 'react-i18next' import Checkbox from '@/app/components/base/checkbox' import Divider from '@/app/components/base/divider' -import Tooltip from '@/app/components/base/tooltip' import SummaryIndexSetting from '@/app/components/datasets/settings/summary-index-setting' import { IS_CE_EDITION } from '@/config' import { ChunkingMode } from '@/models/datasets' @@ -191,7 +191,18 @@ export const GeneralChunkingOptions: FC = ({ onSelect={onDocLanguageChange} disabled={currentDocForm !== ChunkingMode.qa} /> - + + + + + )} + /> + + {t('stepTwo.QATip', { ns: 'datasetCreation' })} + + {currentDocForm === ChunkingMode.qa && (
= React.memo(({
- - {doc.name} + + {doc.name} + )} + /> + + {doc.name} + {doc.summary_index_status && (
@@ -110,13 +117,20 @@ const DocumentTableRow: FC = React.memo(({
)}
- -
- -
+ + + +
+ )} + /> + + {t('list.table.rename', { ns: 'datasetDocuments' })} +
diff --git a/web/app/components/datasets/documents/detail/metadata/components/doc-type-selector.tsx b/web/app/components/datasets/documents/detail/metadata/components/doc-type-selector.tsx index c6044b261a..5dfa02aa80 100644 --- a/web/app/components/datasets/documents/detail/metadata/components/doc-type-selector.tsx +++ b/web/app/components/datasets/documents/detail/metadata/components/doc-type-selector.tsx @@ -3,9 +3,9 @@ import type { FC } from 'react' import type { DocType } from '@/models/datasets' import { Button } from '@langgenius/dify-ui/button' import { cn } from '@langgenius/dify-ui/cn' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { useTranslation } from 'react-i18next' import Radio from '@/app/components/base/radio' -import Tooltip from '@/app/components/base/tooltip' import { useMetadataMap } from '@/hooks/use-metadata' import { CUSTOMIZABLE_DOC_TYPES } from '@/models/datasets' import s from '../style.module.css' @@ -17,13 +17,20 @@ const TypeIcon: FC<{ iconName: string, className?: string }> = ({ iconName, clas const IconButton: FC<{ type: DocType, isChecked: boolean }> = ({ type, isChecked = false }) => { const metadataMap = useMetadataMap() return ( - - + + + + + )} + /> + + {metadataMap[type].text} + ) } diff --git a/web/app/components/datasets/hit-testing/components/query-input/textarea.tsx b/web/app/components/datasets/hit-testing/components/query-input/textarea.tsx index eec34630db..b30fcdcf1e 100644 --- a/web/app/components/datasets/hit-testing/components/query-input/textarea.tsx +++ b/web/app/components/datasets/hit-testing/components/query-input/textarea.tsx @@ -1,9 +1,9 @@ import type { ChangeEvent } from 'react' 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 { Corner } from '@/app/components/base/icons/src/vender/solid/shapes' -import Tooltip from '@/app/components/base/tooltip' type TextareaProps = { text: string @@ -36,14 +36,19 @@ const Textarea = ({ /> {text.length > 200 ? ( - -
- {`${text.length}/200`} -
+ + + {`${text.length}/200`} + + )} + /> + + {t('input.countWarning', { ns: 'datasetHitTesting' })} + ) : ( diff --git a/web/app/components/datasets/list/dataset-card/components/dataset-card-footer.tsx b/web/app/components/datasets/list/dataset-card/components/dataset-card-footer.tsx index 49dcade8f3..df3b5c68d2 100644 --- a/web/app/components/datasets/list/dataset-card/components/dataset-card-footer.tsx +++ b/web/app/components/datasets/list/dataset-card/components/dataset-card-footer.tsx @@ -1,10 +1,10 @@ import type { DataSet } from '@/models/datasets' import { cn } from '@langgenius/dify-ui/cn' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { RiFileTextFill, RiRobot2Fill } from '@remixicon/react' import * as React from 'react' import { useMemo } from 'react' import { useTranslation } from 'react-i18next' -import Tooltip from '@/app/components/base/tooltip' import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now' const EXTERNAL_PROVIDER = 'external' @@ -39,18 +39,32 @@ const DatasetCardFooter = ({ dataset }: DatasetCardFooterProps) => { !dataset.embedding_available && 'opacity-30', )} > - -
- - {documentCount} -
+ + + + {documentCount} + + )} + /> + + {documentCountTooltip} + {!isExternalProvider && ( - -
- - {dataset.app_count} -
+ + + + {dataset.app_count} + + )} + /> + + {`${dataset.app_count} ${t('appCount', { ns: 'dataset' })}`} + )} / diff --git a/web/app/components/datasets/metadata/edit-metadata-batch/edited-beacon.tsx b/web/app/components/datasets/metadata/edit-metadata-batch/edited-beacon.tsx index 001ec74c00..25f1e19f8d 100644 --- a/web/app/components/datasets/metadata/edit-metadata-batch/edited-beacon.tsx +++ b/web/app/components/datasets/metadata/edit-metadata-batch/edited-beacon.tsx @@ -1,11 +1,11 @@ 'use client' import type { FC } from 'react' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { RiResetLeftLine } from '@remixicon/react' import { useHover } from 'ahooks' import * as React from 'react' import { useRef } from 'react' import { useTranslation } from 'react-i18next' -import Tooltip from '@/app/components/base/tooltip' type Props = { onReset: () => void @@ -22,10 +22,17 @@ const EditedBeacon: FC = ({
{isHovering ? ( - -
- -
+ + + +
+ )} + /> + + {t('operation.reset', { ns: 'common' })} +
) : ( diff --git a/web/app/components/datasets/settings/index-method/keyword-number.tsx b/web/app/components/datasets/settings/index-method/keyword-number.tsx index 1f467e1798..3cbc18393f 100644 --- a/web/app/components/datasets/settings/index-method/keyword-number.tsx +++ b/web/app/components/datasets/settings/index-method/keyword-number.tsx @@ -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 Tooltip from '@/app/components/base/tooltip' const MIN_KEYWORD_NUMBER = 0 const MAX_KEYWORD_NUMBER = 50 @@ -36,10 +36,15 @@ const KeyWordNumber = ({
{t('form.numberOfKeywords', { ns: 'datasetSettings' })}
- - + + + )} + /> + + {t('form.numberOfKeywords', { ns: 'datasetSettings' })} + = ({
{currentConversationId && ( - - - - + + + + + )} + /> + + {t('chat.resetChat', { ns: 'share' })} + )} {currentConversationId && inputsForms.length > 0 && ( diff --git a/web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/feature-icon.spec.tsx b/web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/feature-icon.spec.tsx index 8e68ef11dc..ffdbf69780 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/feature-icon.spec.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/feature-icon.spec.tsx @@ -1,4 +1,5 @@ -import { fireEvent, render, screen } from '@testing-library/react' +import { render, screen } from '@testing-library/react' +import userEvent from '@testing-library/user-event' import { ModelFeatureEnum, ModelFeatureTextEnum, @@ -36,7 +37,7 @@ describe('FeatureIcon', () => { for (const { feature, text } of cases) { const { container, unmount } = render() - fireEvent.mouseEnter(container.firstElementChild as HTMLElement) + await userEvent.hover(container.firstElementChild as HTMLElement) expect(await screen.findByText(`common.modelProvider.featureSupported:{"feature":"${text}"}`)) .toBeInTheDocument() unmount() diff --git a/web/app/components/header/account-setting/model-provider-page/model-selector/feature-icon.tsx b/web/app/components/header/account-setting/model-provider-page/model-selector/feature-icon.tsx index a2a357abb5..cc5e0154d7 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-selector/feature-icon.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-selector/feature-icon.tsx @@ -1,5 +1,6 @@ import type { FC } from 'react' import { cn } from '@langgenius/dify-ui/cn' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { RiFileTextLine, RiFilmAiLine, @@ -7,7 +8,6 @@ import { RiVoiceAiFill, } from '@remixicon/react' import { useTranslation } from 'react-i18next' -import Tooltip from '@/app/components/base/tooltip' import { ModelFeatureEnum, ModelFeatureTextEnum, @@ -75,19 +75,24 @@ const FeatureIcon: FC = ({ } return ( - -
- - - -
+ + + + + +
+ )} + /> + + {t('modelProvider.featureSupported', { ns: 'common', feature: ModelFeatureTextEnum.vision })} +
) } @@ -105,19 +110,24 @@ const FeatureIcon: FC = ({ } return ( - -
- - - -
+ + + + + + + )} + /> + + {t('modelProvider.featureSupported', { ns: 'common', feature: ModelFeatureTextEnum.document })} + ) } @@ -135,19 +145,24 @@ const FeatureIcon: FC = ({ } return ( - -
- - - -
+ + + + + + + )} + /> + + {t('modelProvider.featureSupported', { ns: 'common', feature: ModelFeatureTextEnum.audio })} + ) } @@ -165,19 +180,24 @@ const FeatureIcon: FC = ({ } return ( - -
- - - -
+ + + + + + + )} + /> + + {t('modelProvider.featureSupported', { ns: 'common', feature: ModelFeatureTextEnum.video })} + ) } diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/cooldown-timer.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/cooldown-timer.tsx index 47e3ccffaa..84690f3a36 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/cooldown-timer.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/cooldown-timer.tsx @@ -1,8 +1,8 @@ +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { useLatest } from 'ahooks' import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import SimplePieChart from '@/app/components/base/simple-pie-chart' -import Tooltip from '@/app/components/base/tooltip' type CooldownTimerProps = { secondsRemaining?: number @@ -54,8 +54,15 @@ const CooldownTimer = ({ secondsRemaining, onFinish }: CooldownTimerProps) => { return displayTime ? ( - - + + + )} + /> + + {t('modelProvider.apiKeyRateLimit', { ns: 'common', seconds: displayTime })} + ) : null diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx index 9b7b858c13..e8b99bbcea 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx @@ -10,11 +10,11 @@ import type { } from '../declarations' import { cn } from '@langgenius/dify-ui/cn' import { Switch } from '@langgenius/dify-ui/switch' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' 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 Tooltip from '@/app/components/base/tooltip' 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,11 +152,18 @@ const ModelLoadBalancingConfigs = ({
{t('modelProvider.loadBalancing', { ns: 'common' })} - + + + + + )} + /> + + {t('modelProvider.loadBalancingInfo', { ns: 'common' })} + +
{t('modelProvider.loadBalancingDescription', { ns: 'common' })}
@@ -187,8 +194,15 @@ const ModelLoadBalancingConfigs = ({ clearCountdown(index)} /> ) : ( - - + + + )} + /> + + {t('modelProvider.apiKeyStatusNormal', { ns: 'common' })} + )} @@ -208,14 +222,21 @@ const ModelLoadBalancingConfigs = ({ {!isProviderManaged && ( <>
- - updateConfigEntry(index, () => undefined)} - data-testid={`load-balancing-remove-${config.id || index}`} - > -
- + + updateConfigEntry(index, () => undefined)} + data-testid={`load-balancing-remove-${config.id || index}`} + > +
+ + )} + /> + + {t('operation.remove', { ns: 'common' })} +
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/priority-use-tip.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/priority-use-tip.tsx index 174e417dc9..ce647416ea 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/priority-use-tip.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/priority-use-tip.tsx @@ -1,17 +1,22 @@ +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { useTranslation } from 'react-i18next' import { ChevronDownDouble } from '@/app/components/base/icons/src/vender/line/arrows' -import Tooltip from '@/app/components/base/tooltip' const PriorityUseTip = () => { const { t } = useTranslation() return ( - -
- -
+ + + +
+ )} + /> + + {t('modelProvider.priorityUsing', { ns: 'common' }) || ''} +
) } diff --git a/web/app/components/plugins/plugin-auth/authorize/index.tsx b/web/app/components/plugins/plugin-auth/authorize/index.tsx index fe82498fad..a6e53f977e 100644 --- a/web/app/components/plugins/plugin-auth/authorize/index.tsx +++ b/web/app/components/plugins/plugin-auth/authorize/index.tsx @@ -2,12 +2,12 @@ import type { PluginPayload } from '../types' import type { AddApiKeyButtonProps } from './add-api-key-button' import type { AddOAuthButtonProps } from './add-oauth-button' import { cn } from '@langgenius/dify-ui/cn' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { memo, useMemo, } from 'react' import { useTranslation } from 'react-i18next' -import Tooltip from '@/app/components/base/tooltip' import AddApiKeyButton from './add-api-key-button' import AddOAuthButton from './add-oauth-button' @@ -79,8 +79,11 @@ const Authorize = ({ if (notAllowCustomCredential) { return ( - - {Item} + + + + {t('auth.credentialUnavailable', { ns: 'plugin' })} + ) } @@ -100,8 +103,11 @@ const Authorize = ({ if (notAllowCustomCredential) { return ( - - {Item} + + + + {t('auth.credentialUnavailable', { ns: 'plugin' })} + ) } diff --git a/web/app/components/plugins/plugin-auth/authorized/__tests__/item.spec.tsx b/web/app/components/plugins/plugin-auth/authorized/__tests__/item.spec.tsx index 0225c8c8c6..39ec436ece 100644 --- a/web/app/components/plugins/plugin-auth/authorized/__tests__/item.spec.tsx +++ b/web/app/components/plugins/plugin-auth/authorized/__tests__/item.spec.tsx @@ -110,7 +110,7 @@ describe('Item Component', () => { const { container } = render() - expect(container.querySelector('[data-state]')).toBeInTheDocument() + expect(container.firstElementChild).toHaveClass('cursor-not-allowed', 'opacity-50') }) it('should not call onItemClick when disabled is true', () => { diff --git a/web/app/components/plugins/plugin-auth/authorized/item.tsx b/web/app/components/plugins/plugin-auth/authorized/item.tsx index 9193238a55..0bdb9c1a21 100644 --- a/web/app/components/plugins/plugin-auth/authorized/item.tsx +++ b/web/app/components/plugins/plugin-auth/authorized/item.tsx @@ -1,6 +1,7 @@ import type { Credential } from '../types' import { Button } from '@langgenius/dify-ui/button' import { cn } from '@langgenius/dify-ui/cn' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { RiCheckLine, RiDeleteBinLine, @@ -16,7 +17,6 @@ import { useTranslation } from 'react-i18next' import ActionButton from '@/app/components/base/action-button' import Badge from '@/app/components/base/badge' import Input from '@/app/components/base/input' -import Tooltip from '@/app/components/base/tooltip' import Indicator from '@/app/components/header/indicator' import { CredentialTypeEnum } from '../types' @@ -172,55 +172,76 @@ const Item = ({ } { !disableRename && !credential.from_enterprise && !credential.not_allowed_to_use && ( - - { - e.stopPropagation() - setRenaming(true) - setRenameValue(credential.name) - }} - > - - + + { + e.stopPropagation() + setRenaming(true) + setRenameValue(credential.name) + }} + > + + + )} + /> + + {t('operation.rename', { ns: 'common' })} + ) } { !isOAuth && !disableEdit && !credential.from_enterprise && !credential.not_allowed_to_use && ( - - { - e.stopPropagation() - onEdit?.( - credential.id, - { - ...credential.credentials, - __name__: credential.name, - __credential_id__: credential.id, - }, - ) - }} - > - - + + { + e.stopPropagation() + onEdit?.( + credential.id, + { + ...credential.credentials, + __name__: credential.name, + __credential_id__: credential.id, + }, + ) + }} + > + + + )} + /> + + {t('operation.edit', { ns: 'common' })} + ) } { !disableDelete && !credential.from_enterprise && ( - - { - e.stopPropagation() - onDelete?.(credential.id) - }} - > - - + + { + e.stopPropagation() + onDelete?.(credential.id) + }} + > + + + )} + /> + + {t('operation.delete', { ns: 'common' })} + ) } @@ -232,8 +253,11 @@ const Item = ({ if (credential.not_allowed_to_use) { return ( - - {CredentialItem} + + + + {t('auth.customCredentialUnavailable', { ns: 'plugin' })} + ) } diff --git a/web/app/components/plugins/plugin-detail-panel/multiple-tool-selector/index.tsx b/web/app/components/plugins/plugin-detail-panel/multiple-tool-selector/index.tsx index 723560832a..7972ea5f89 100644 --- a/web/app/components/plugins/plugin-detail-panel/multiple-tool-selector/index.tsx +++ b/web/app/components/plugins/plugin-detail-panel/multiple-tool-selector/index.tsx @@ -2,6 +2,7 @@ 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, @@ -11,7 +12,6 @@ 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 Tooltip from '@/app/components/base/tooltip' 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' @@ -112,10 +112,15 @@ const MultipleToolSelector = ({
{label}
{required &&
*
} {tooltip && ( - -
+ +
+ )} + /> + + {tooltip} +
)} {supportCollapse && ( diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/create/index.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/index.tsx index c30e49affc..be970b6cec 100644 --- a/web/app/components/plugins/plugin-detail-panel/subscription-list/create/index.tsx +++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/index.tsx @@ -3,13 +3,13 @@ import { Button } from '@langgenius/dify-ui/button' import { cn } from '@langgenius/dify-ui/cn' import { Select, SelectContent, SelectItem, SelectItemIndicator, SelectTrigger } from '@langgenius/dify-ui/select' import { toast } from '@langgenius/dify-ui/toast' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { RiAddLine, RiEqualizer2Line } from '@remixicon/react' import { useBoolean } from 'ahooks' 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 Tooltip from '@/app/components/base/tooltip' import { openOAuthPopup } from '@/hooks/use-oauth' import { useInitiateTriggerOAuth, useTriggerOAuthConfig, useTriggerProviderInfo } from '@/service/use-triggers' import { SupportedCreationMethods } from '../../../types' @@ -86,10 +86,17 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU ), extra: ( - - - - + + + + + )} + /> + + {t('subscription.addType.options.oauth.clientSettings', { ns: 'pluginTrigger' })} + ), show: supportedMethods.includes(SupportedCreationMethods.OAUTH), @@ -102,7 +109,20 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU { value: SupportedCreationMethods.MANUAL, label: t('subscription.addType.options.manual.description', { ns: 'pluginTrigger' }), - extra: , + extra: ( + + + + + )} + /> + + {t('subscription.addType.options.manual.tip', { ns: 'pluginTrigger' })} + + + ), show: supportedMethods.includes(SupportedCreationMethods.MANUAL), }, ] @@ -196,30 +216,42 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU && (
- -
- -
+ + + +
+ )} + /> + + {t('subscription.addType.options.oauth.clientSettings', { ns: 'pluginTrigger' })} +
)} ) : ( - = MAX_COUNT ? t('subscription.maxCount', { ns: 'pluginTrigger', num: MAX_COUNT }) : t(`subscription.addType.options.${methodType!.toLowerCase() as Lowercase}.description`, { ns: 'pluginTrigger' })} - disabled={!(supportedMethods?.length === 1 || subscriptionCount >= MAX_COUNT)} - > - + = MAX_COUNT)} + render={( + = MAX_COUNT ? ActionButtonState.Disabled : ActionButtonState.Default} + > + + )} - state={subscriptionCount >= MAX_COUNT ? ActionButtonState.Disabled : ActionButtonState.Default} - > - - + /> + + {subscriptionCount >= MAX_COUNT ? t('subscription.maxCount', { ns: 'pluginTrigger', num: MAX_COUNT }) : t(`subscription.addType.options.${methodType!.toLowerCase() as Lowercase}.description`, { ns: 'pluginTrigger' })} + )} diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/list-view.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/list-view.tsx index c78cda7a13..45d4c486b7 100644 --- a/web/app/components/plugins/plugin-detail-panel/subscription-list/list-view.tsx +++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/list-view.tsx @@ -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 Tooltip from '@/app/components/base/tooltip' import { CreateButtonType, CreateSubscriptionButton } from './create' import SubscriptionCard from './subscription-card' import { useSubscriptionList } from './use-subscription-list' @@ -30,7 +30,18 @@ export const SubscriptionListView: React.FC = ({ {t('subscription.listNum', { ns: 'pluginTrigger', num: subscriptionCount })} - + + + + + )} + /> + + {t('subscription.list.tip', { ns: 'pluginTrigger' })} + + )} = ({ {t('subscription.listNum', { ns: 'pluginTrigger', num: subscriptionCount })} - + + + + + )} + /> + + {t('subscription.list.tip', { ns: 'pluginTrigger' })} + + ({ - default: ({ - children, - popupContent, - }: { - children: React.ReactNode - popupContent: React.ReactNode - }) => ( -
- {children} -
{popupContent}
-
- ), -})) - describe('ToolItem', () => { beforeEach(() => { vi.clearAllMocks() @@ -102,7 +88,7 @@ describe('ToolItem', () => { expect(onInstall).toHaveBeenCalledTimes(2) }) - it('blocks unsupported MCP tools and still exposes error state', () => { + it('blocks unsupported MCP tools and still exposes error state', async () => { mcpAllowed = false const { rerender } = render( { />, ) - expect(screen.getByText('tool failed')).toBeInTheDocument() + await userEvent.hover(screen.getByLabelText('tool failed')) + expect(await screen.findByText('tool failed')).toBeInTheDocument() }) }) diff --git a/web/app/components/plugins/plugin-detail-panel/tool-selector/components/tool-item.tsx b/web/app/components/plugins/plugin-detail-panel/tool-selector/components/tool-item.tsx index 889243d507..ba85957108 100644 --- a/web/app/components/plugins/plugin-detail-panel/tool-selector/components/tool-item.tsx +++ b/web/app/components/plugins/plugin-detail-panel/tool-selector/components/tool-item.tsx @@ -2,6 +2,7 @@ import { Button } from '@langgenius/dify-ui/button' 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, RiEqualizer2Line, @@ -13,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 Tooltip from '@/app/components/base/tooltip' 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' @@ -167,12 +167,17 @@ const ToolItem = ({ /> )} {isError && ( - -
- -
+ + + + + )} + /> + + {errorTip} + )} diff --git a/web/app/components/plugins/plugin-page/index.tsx b/web/app/components/plugins/plugin-page/index.tsx index 61d5bfb387..d40a91e2b0 100644 --- a/web/app/components/plugins/plugin-page/index.tsx +++ b/web/app/components/plugins/plugin-page/index.tsx @@ -4,6 +4,7 @@ import type { Dependency, PluginDeclaration, PluginManifestInMarket } from '../t import type { PluginPageTab } from './context' import { Button } from '@langgenius/dify-ui/button' import { cn } from '@langgenius/dify-ui/cn' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { RiBookOpenLine, RiDragDropLine, @@ -15,7 +16,6 @@ import { noop } from 'es-toolkit/function' import { useEffect, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import TabSlider from '@/app/components/base/tab-slider' -import Tooltip from '@/app/components/base/tooltip' import ReferenceSettingModal from '@/app/components/plugins/reference-setting-modal' import { MARKETPLACE_API_PREFIX, SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS } from '@/config' import { useDocLink } from '@/context/i18n' @@ -218,16 +218,21 @@ const PluginPage = ({ } { canSetPermissions && ( - - + + + + + )} + /> + + {t('privilege.title', { ns: 'plugin' })} + ) } diff --git a/web/app/components/workflow/nodes/_base/components/config-vision.tsx b/web/app/components/workflow/nodes/_base/components/config-vision.tsx index d21e53368d..546cb1ac6b 100644 --- a/web/app/components/workflow/nodes/_base/components/config-vision.tsx +++ b/web/app/components/workflow/nodes/_base/components/config-vision.tsx @@ -2,11 +2,11 @@ import type { FC } from 'react' import type { ValueSelector, Var, VisionSetting } from '@/app/components/workflow/types' import { Switch } from '@langgenius/dify-ui/switch' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { produce } from 'immer' import * as React from 'react' import { useCallback } from 'react' import { useTranslation } from 'react-i18next' -import Tooltip from '@/app/components/base/tooltip' import Field from '@/app/components/workflow/nodes/_base/components/field' import ResolutionPicker from '@/app/components/workflow/nodes/llm/components/resolution-picker' import { VarType } from '@/app/components/workflow/types' @@ -61,11 +61,16 @@ const ConfigVision: FC = ({ title={t(`${i18nPrefix}.vision`, { ns: 'workflow' })} tooltip={t('vision.description', { ns: 'appDebug' })!} operations={( - - + + + )} + /> + + {t('vision.onlySupportVisionModelTip', { ns: 'appDebug' })!} + )} > diff --git a/web/app/components/workflow/nodes/_base/components/input-support-select-var.tsx b/web/app/components/workflow/nodes/_base/components/input-support-select-var.tsx index 8a09cd9366..930f40f76f 100644 --- a/web/app/components/workflow/nodes/_base/components/input-support-select-var.tsx +++ b/web/app/components/workflow/nodes/_base/components/input-support-select-var.tsx @@ -5,6 +5,7 @@ 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 { useBoolean } from 'ahooks' import { noop } from 'es-toolkit/function' import * as React from 'react' @@ -12,7 +13,6 @@ import { useEffect } from 'react' import { useTranslation } from 'react-i18next' import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' import PromptEditor from '@/app/components/base/prompt-editor' -import Tooltip from '@/app/components/base/tooltip' import { useStore } from '@/app/components/workflow/store' import { BlockEnum } from '@/app/components/workflow/types' @@ -119,12 +119,17 @@ const Editor: FC = ({ {readOnly &&
} {isFocus && (
- -
- -
+ + + +
+ )} + /> + + {`${t('common.insertVarTip', { ns: 'workflow' })}`} +
)} diff --git a/web/app/components/workflow/nodes/_base/components/setting-item.tsx b/web/app/components/workflow/nodes/_base/components/setting-item.tsx index feea50cd18..f8a20555dd 100644 --- a/web/app/components/workflow/nodes/_base/components/setting-item.tsx +++ b/web/app/components/workflow/nodes/_base/components/setting-item.tsx @@ -1,7 +1,7 @@ import type { ComponentProps, PropsWithChildren, ReactNode } from 'react' import { cn } from '@langgenius/dify-ui/cn' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { memo } from 'react' -import Tooltip from '@/app/components/base/tooltip' import Indicator from '@/app/components/header/indicator' type SettingItemProps = PropsWithChildren<{ @@ -18,10 +18,18 @@ export const SettingItem = memo(({ label, children, status, tooltip }: SettingIt
{label}
- -
- {children} -
+ + + {children} + + )} + /> + + {tooltip} + {indicator && } diff --git a/web/app/components/workflow/nodes/_base/components/variable/object-child-tree-panel/picker/field.tsx b/web/app/components/workflow/nodes/_base/components/variable/object-child-tree-panel/picker/field.tsx index 717d8afbe7..5b6811bc95 100644 --- a/web/app/components/workflow/nodes/_base/components/variable/object-child-tree-panel/picker/field.tsx +++ b/web/app/components/workflow/nodes/_base/components/variable/object-child-tree-panel/picker/field.tsx @@ -3,10 +3,10 @@ import type { FC } from 'react' import type { Field as FieldType } from '../../../../../llm/types' import type { ValueSelector } from '@/app/components/workflow/types' import { cn } from '@langgenius/dify-ui/cn' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { RiMoreFill } from '@remixicon/react' import * as React from 'react' import { useTranslation } from 'react-i18next' -import Tooltip from '@/app/components/base/tooltip' import { Type } from '../../../../../llm/types' import { getFieldType } from '../../../../../llm/utils' import TreeIndentLine from '../tree-indent-line' @@ -38,24 +38,32 @@ const Field: FC = ({ return null return (
- -
!readonly && onSelect?.([...valueSelector, name])} - > -
- - {depth === MAX_DEPTH + 1 - ? ( - - ) - : (
{name}
)} + + !readonly && onSelect?.([...valueSelector, name])} + > +
+ + {depth === MAX_DEPTH + 1 + ? ( + + ) + : (
{name}
)} -
- {depth < MAX_DEPTH + 1 && ( -
{getFieldType(payload)}
+
+ {depth < MAX_DEPTH + 1 && ( +
{getFieldType(payload)}
+ )} +
)} -
+ /> + + {t('structOutput.moreFillTip', { ns: 'app' })} +
{depth <= MAX_DEPTH && payload.type === Type.object && payload.properties && ( diff --git a/web/app/components/workflow/nodes/human-input/components/delivery-method/index.tsx b/web/app/components/workflow/nodes/human-input/components/delivery-method/index.tsx index aa5fd77d0e..cdfda74aeb 100644 --- a/web/app/components/workflow/nodes/human-input/components/delivery-method/index.tsx +++ b/web/app/components/workflow/nodes/human-input/components/delivery-method/index.tsx @@ -3,10 +3,10 @@ import type { Node, NodeOutPutVar, } from '@/app/components/workflow/types' +import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { produce } from 'immer' import * as React from 'react' import { useTranslation } from 'react-i18next' -import Tooltip from '@/app/components/base/tooltip' import { useNodesSyncDraft } from '@/app/components/workflow/hooks' import MethodItem from './method-item' import MethodSelector from './method-selector' @@ -71,9 +71,18 @@ const DeliveryMethodForm: React.FC = ({
{t(`${i18nPrefix}.deliveryMethod.title`, { ns: 'workflow' })}
- + + + + + )} + /> + + {t(`${i18nPrefix}.deliveryMethod.tooltip`, { ns: 'workflow' })} + +
{!readonly && (
diff --git a/web/app/components/workflow/nodes/knowledge-base/components/index-method.tsx b/web/app/components/workflow/nodes/knowledge-base/components/index-method.tsx index 70ff0e47eb..82ccf265ba 100644 --- a/web/app/components/workflow/nodes/knowledge-base/components/index-method.tsx +++ b/web/app/components/workflow/nodes/knowledge-base/components/index-method.tsx @@ -1,5 +1,6 @@ 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, @@ -11,7 +12,6 @@ import { HighQuality, } from '@/app/components/base/icons/src/vender/knowledge' import Input from '@/app/components/base/input' -import Tooltip from '@/app/components/base/tooltip' import { Field } from '@/app/components/workflow/nodes/_base/components/layout' import { ChunkStructureEnum, @@ -97,10 +97,13 @@ const IndexMethod = ({
{t('form.numberOfKeywords', { ns: 'datasetSettings' })}
- - + + } + /> + + number of keywords +
= ({
{t('nodes.llm.jsonSchema.instruction', { ns: 'workflow' })} - + + + + + )} + /> + + {t('nodes.llm.jsonSchema.promptTooltip', { ns: 'workflow' })} + +