mirror of
https://github.com/langgenius/dify.git
synced 2026-04-30 16:02:00 -04:00
refactor(web): migrate short tooltips to dify-ui (#35715)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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<PopupProps> = ({
|
||||
<>
|
||||
{providerAllNotConfigured
|
||||
? (
|
||||
<Tooltip
|
||||
popupContent={t(`${I18N_PREFIX}.disabledTip`, { ns: 'app' })}
|
||||
>
|
||||
{switchContent}
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={switchContent}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t(`${I18N_PREFIX}.disabledTip`, { ns: 'app' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
: switchContent}
|
||||
|
||||
@@ -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 }) => (
|
||||
<div data-testid="tooltip" data-content={popupContent}>{children}</div>
|
||||
),
|
||||
}))
|
||||
|
||||
const createModelAndParameter = (overrides: Partial<ModelAndParameter> = {}): 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', () => {
|
||||
|
||||
@@ -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<ModelParameterTriggerProps> = ({
|
||||
<span className={`i-ri-arrow-down-s-line h-3 w-3 ${isEmpty ? 'text-text-accent' : 'text-text-tertiary'}`} />
|
||||
{
|
||||
!isEmpty && !isActive && statusLabelKey && (
|
||||
<Tooltip popupContent={t((statusTooltipKey || statusLabelKey) as 'modelProvider.selector.incompatible', { ns: 'common' })}>
|
||||
<span className="i-custom-vender-line-alertsAndFeedback-alert-triangle h-4 w-4 text-[#F79009]" />
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<span
|
||||
aria-label={t((statusTooltipKey || statusLabelKey) as 'modelProvider.selector.incompatible', { ns: 'common' })}
|
||||
className="i-custom-vender-line-alertsAndFeedback-alert-triangle h-4 w-4 text-[#F79009]"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t((statusTooltipKey || statusLabelKey) as 'modelProvider.selector.incompatible', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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<IPromptValuePanelProps> = ({
|
||||
<div className="flex justify-between border-t border-divider-subtle p-4 pt-3">
|
||||
<Button className="w-[72px]" disabled={readonly} onClick={onClear}>{t('operation.clear', { ns: 'common' })}</Button>
|
||||
{canNotRun && (
|
||||
<Tooltip popupContent={t('otherError.promptNoBeEmpty', { ns: 'appDebug' })}>
|
||||
<Button
|
||||
variant="primary"
|
||||
disabled={canNotRun || readonly}
|
||||
onClick={() => onSend?.()}
|
||||
className="w-[96px]"
|
||||
>
|
||||
<RiPlayLargeFill className="mr-0.5 h-4 w-4 shrink-0" aria-hidden="true" />
|
||||
{t('inputs.run', { ns: 'appDebug' })}
|
||||
</Button>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<Button
|
||||
variant="primary"
|
||||
disabled={canNotRun || readonly}
|
||||
onClick={() => onSend?.()}
|
||||
className="w-[96px]"
|
||||
>
|
||||
<RiPlayLargeFill className="mr-0.5 h-4 w-4 shrink-0" aria-hidden="true" />
|
||||
{t('inputs.run', { ns: 'appDebug' })}
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('otherError.promptNoBeEmpty', { ns: 'appDebug' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{!canNotRun && (
|
||||
|
||||
@@ -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) {
|
||||
<div className="mb-0.5 system-xs-semibold-uppercase text-text-primary">{isChatMode ? t('detail.conversationId', { ns: 'appLog' }) : t('detail.time', { ns: 'appLog' })}</div>
|
||||
{isChatMode && (
|
||||
<div className="flex items-center system-2xs-regular-uppercase text-text-secondary">
|
||||
<Tooltip
|
||||
popupContent={detail.id}
|
||||
>
|
||||
<div className="truncate">{detail.id}</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="truncate">{detail.id}</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{detail.id}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<CopyIcon content={detail.id} />
|
||||
</div>
|
||||
@@ -769,18 +774,20 @@ const ConversationList: FC<IConversationList> = ({ logs, appDetail, onRefresh })
|
||||
// Annotated data needs to be highlighted
|
||||
const renderTdValue = (value: string | number | null, isEmptyStyle: boolean, isHighlight = false, annotation?: LogAnnotation) => {
|
||||
return (
|
||||
<Tooltip
|
||||
popupContent={(
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className={cn(isEmptyStyle ? 'text-text-quaternary' : 'text-text-secondary', !isHighlight ? '' : 'bg-orange-100', 'overflow-hidden system-sm-regular text-ellipsis whitespace-nowrap')}>
|
||||
{value || '-'}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent className={(isHighlight && !isChatMode) ? '' : 'hidden!'}>
|
||||
<span className="inline-flex items-center text-xs text-text-tertiary">
|
||||
<RiEditFill className="mr-1 h-3 w-3" />
|
||||
{`${t('detail.annotationTip', { ns: 'appLog', user: annotation?.account?.name })} ${formatTime(annotation?.created_at || dayjs().unix(), 'MM-DD hh:mm A')}`}
|
||||
</span>
|
||||
)}
|
||||
popupClassName={(isHighlight && !isChatMode) ? '' : 'hidden!'}
|
||||
>
|
||||
<div className={cn(isEmptyStyle ? 'text-text-quaternary' : 'text-text-secondary', !isHighlight ? '' : 'bg-orange-100', 'overflow-hidden system-sm-regular text-ellipsis whitespace-nowrap')}>
|
||||
{value || '-'}
|
||||
</div>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
<div className="shrink-0 grow system-sm-medium text-text-secondary">
|
||||
{t(`${prefixEmbedded}.${option}`, { ns: 'appOverview' })}
|
||||
</div>
|
||||
<Tooltip
|
||||
popupContent={
|
||||
(isCopied[option]
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton>
|
||||
<div
|
||||
onClick={onClickCopy}
|
||||
>
|
||||
{isCopied[option] && <RiClipboardFill className="h-4 w-4" />}
|
||||
{!isCopied[option] && <RiClipboardLine className="h-4 w-4" />}
|
||||
</div>
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{(isCopied[option]
|
||||
? t(`${prefixEmbedded}.copied`, { ns: 'appOverview' })
|
||||
: t(`${prefixEmbedded}.copy`, { ns: 'appOverview' })) || ''
|
||||
}
|
||||
>
|
||||
<ActionButton>
|
||||
<div
|
||||
onClick={onClickCopy}
|
||||
>
|
||||
{isCopied[option] && <RiClipboardFill className="h-4 w-4" />}
|
||||
{!isCopied[option] && <RiClipboardLine className="h-4 w-4" />}
|
||||
</div>
|
||||
</ActionButton>
|
||||
: t(`${prefixEmbedded}.copy`, { ns: 'appOverview' })) || ''}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="flex w-full items-start justify-start gap-2 overflow-x-auto p-3">
|
||||
|
||||
@@ -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 (
|
||||
<div className={`inline-flex items-center justify-center ${(audioState === 'loading' || audioState === 'playing') ? 'mr-1' : className}`}>
|
||||
<Tooltip
|
||||
popupContent={tooltipContent}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
disabled={audioState === 'loading'}
|
||||
className={`box-border flex h-6 w-6 cursor-pointer items-center justify-center ${isAudition ? 'p-0.5' : 'rounded-md bg-white p-0'}`}
|
||||
onClick={handleToggle}
|
||||
>
|
||||
{audioState === 'loading'
|
||||
? (
|
||||
<div className="flex h-full w-full items-center justify-center rounded-md">
|
||||
<Loading />
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
<div className="flex h-full w-full items-center justify-center rounded-md hover:bg-gray-50">
|
||||
<div className={`h-4 w-4 ${(audioState === 'playing') ? s.pauseIcon : s.playIcon}`}></div>
|
||||
</div>
|
||||
)}
|
||||
</button>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<span className="inline-flex">
|
||||
<button
|
||||
type="button"
|
||||
disabled={audioState === 'loading'}
|
||||
className={`box-border flex h-6 w-6 cursor-pointer items-center justify-center ${isAudition ? 'p-0.5' : 'rounded-md bg-white p-0'}`}
|
||||
onClick={handleToggle}
|
||||
>
|
||||
{audioState === 'loading'
|
||||
? (
|
||||
<div className="flex h-full w-full items-center justify-center rounded-md">
|
||||
<Loading />
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
<div className="flex h-full w-full items-center justify-center rounded-md hover:bg-gray-50">
|
||||
<div className={`h-4 w-4 ${(audioState === 'playing') ? s.pauseIcon : s.playIcon}`}></div>
|
||||
</div>
|
||||
)}
|
||||
</button>
|
||||
</span>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{tooltipContent}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -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 = () => {
|
||||
<div className="h-[14px] w-px bg-divider-regular"></div>
|
||||
</div>
|
||||
{isSidebarCollapsed && (
|
||||
<Tooltip
|
||||
disabled={!!currentConversationId}
|
||||
popupContent={t('chat.newChatTip', { ns: 'share' })}
|
||||
>
|
||||
<div>
|
||||
<ActionButton
|
||||
size="l"
|
||||
state={(!currentConversationId || isResponding) ? ActionButtonState.Disabled : ActionButtonState.Default}
|
||||
disabled={!currentConversationId || isResponding}
|
||||
onClick={handleNewConversation}
|
||||
>
|
||||
<RiEditBoxLine className="h-[18px] w-[18px]" />
|
||||
</ActionButton>
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
disabled={!!currentConversationId}
|
||||
render={(
|
||||
<div>
|
||||
<ActionButton
|
||||
size="l"
|
||||
state={(!currentConversationId || isResponding) ? ActionButtonState.Disabled : ActionButtonState.Default}
|
||||
disabled={!currentConversationId || isResponding}
|
||||
onClick={handleNewConversation}
|
||||
>
|
||||
<RiEditBoxLine className="h-[18px] w-[18px]" />
|
||||
</ActionButton>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('chat.newChatTip', { ns: 'share' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
{currentConversationId && (
|
||||
<Tooltip
|
||||
popupContent={t('chat.resetChat', { ns: 'share' })}
|
||||
>
|
||||
<ActionButton size="l" onClick={handleNewConversation}>
|
||||
<RiResetLeftLine className="h-[18px] w-[18px]" />
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton size="l" onClick={handleNewConversation}>
|
||||
<RiResetLeftLine className="h-[18px] w-[18px]" />
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('chat.resetChat', { ns: 'share' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{currentConversationId && inputsForms.length > 0 && (
|
||||
|
||||
@@ -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<IHeaderProps> = ({
|
||||
)}
|
||||
{
|
||||
showToggleExpandButton && (
|
||||
<Tooltip
|
||||
popupContent={expanded ? t('chat.collapse', { ns: 'share' }) : t('chat.expand', { ns: 'share' })}
|
||||
>
|
||||
<ActionButton size="l" onClick={handleToggleExpand} data-testid="expand-button">
|
||||
{
|
||||
expanded
|
||||
? <div className="i-ri-collapse-diagonal-2-line h-[18px] w-[18px]" />
|
||||
: <div className="i-ri-expand-diagonal-2-line h-[18px] w-[18px]" />
|
||||
}
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton size="l" onClick={handleToggleExpand} data-testid="expand-button">
|
||||
{
|
||||
expanded
|
||||
? <div className="i-ri-collapse-diagonal-2-line h-[18px] w-[18px]" />
|
||||
: <div className="i-ri-expand-diagonal-2-line h-[18px] w-[18px]" />
|
||||
}
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{expanded ? t('chat.collapse', { ns: 'share' }) : t('chat.expand', { ns: 'share' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
{currentConversationId && allowResetChat && (
|
||||
<Tooltip
|
||||
popupContent={t('chat.resetChat', { ns: 'share' })}
|
||||
>
|
||||
<ActionButton size="l" onClick={onCreateNewChat} data-testid="reset-chat-button">
|
||||
<div className="i-ri-reset-left-line h-[18px] w-[18px]" />
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton size="l" onClick={onCreateNewChat} data-testid="reset-chat-button">
|
||||
<div className="i-ri-reset-left-line h-[18px] w-[18px]" />
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('chat.resetChat', { ns: 'share' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{currentConversationId && inputsForms.length > 0 && !allInputsHidden && (
|
||||
@@ -158,26 +168,36 @@ const Header: FC<IHeaderProps> = ({
|
||||
<div className="flex items-center gap-1">
|
||||
{
|
||||
showToggleExpandButton && (
|
||||
<Tooltip
|
||||
popupContent={expanded ? t('chat.collapse', { ns: 'share' }) : t('chat.expand', { ns: 'share' })}
|
||||
>
|
||||
<ActionButton size="l" onClick={handleToggleExpand} data-testid="mobile-expand-button">
|
||||
{
|
||||
expanded
|
||||
? <div className={cn('i-ri-collapse-diagonal-2-line h-[18px] w-[18px]', theme?.colorPathOnHeader)} />
|
||||
: <div className={cn('i-ri-expand-diagonal-2-line h-[18px] w-[18px]', theme?.colorPathOnHeader)} />
|
||||
}
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton size="l" onClick={handleToggleExpand} data-testid="mobile-expand-button">
|
||||
{
|
||||
expanded
|
||||
? <div className={cn('i-ri-collapse-diagonal-2-line h-[18px] w-[18px]', theme?.colorPathOnHeader)} />
|
||||
: <div className={cn('i-ri-expand-diagonal-2-line h-[18px] w-[18px]', theme?.colorPathOnHeader)} />
|
||||
}
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{expanded ? t('chat.collapse', { ns: 'share' }) : t('chat.expand', { ns: 'share' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
{currentConversationId && allowResetChat && (
|
||||
<Tooltip
|
||||
popupContent={t('chat.resetChat', { ns: 'share' })}
|
||||
>
|
||||
<ActionButton size="l" onClick={onCreateNewChat} data-testid="mobile-reset-chat-button">
|
||||
<div className={cn('i-ri-reset-left-line h-[18px] w-[18px]', theme?.colorPathOnHeader)} />
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton size="l" onClick={onCreateNewChat} data-testid="mobile-reset-chat-button">
|
||||
<div className={cn('i-ri-reset-left-line h-[18px] w-[18px]', theme?.colorPathOnHeader)} />
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('chat.resetChat', { ns: 'share' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{currentConversationId && inputsForms.length > 0 && !allInputsHidden && (
|
||||
|
||||
@@ -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 (
|
||||
<Tooltip
|
||||
popupContent={safeText}
|
||||
>
|
||||
<ActionButton>
|
||||
<div onClick={handleCopy}>
|
||||
{copied && <RiClipboardFill className="h-4 w-4" />}
|
||||
{!copied && <RiClipboardLine className="h-4 w-4" />}
|
||||
</div>
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton>
|
||||
<div onClick={handleCopy}>
|
||||
{copied && <RiClipboardFill className="h-4 w-4" />}
|
||||
{!copied && <RiClipboardLine className="h-4 w-4" />}
|
||||
</div>
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{safeText}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
@@ -65,18 +70,23 @@ export const CopyFeedbackNew = ({ content, className }: Pick<Props, 'className'
|
||||
}, [copy, content])
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
popupContent={safeText}
|
||||
>
|
||||
<div
|
||||
className={`h-8 w-8 cursor-pointer rounded-lg hover:bg-components-button-ghost-bg-hover ${className ?? ''}`}
|
||||
>
|
||||
<div
|
||||
onClick={handleCopy}
|
||||
className={`h-full w-full ${copyStyle.copyIcon} ${copied ? copyStyle.copied : ''}`}
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div
|
||||
className={`h-8 w-8 cursor-pointer rounded-lg hover:bg-components-button-ghost-bg-hover ${className ?? ''}`}
|
||||
>
|
||||
<div
|
||||
onClick={handleCopy}
|
||||
className={`h-full w-full ${copyStyle.copyIcon} ${copied ? copyStyle.copied : ''}`}
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{safeText}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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<Props> = ({ cached, query, answer, appId, message
|
||||
return (
|
||||
<>
|
||||
{cached && (
|
||||
<Tooltip popupContent={t('feature.annotation.edit', { ns: 'appDebug' })}>
|
||||
<ActionButton onClick={onEdit}>
|
||||
<RiEditLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton onClick={onEdit}>
|
||||
<RiEditLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('feature.annotation.edit', { ns: 'appDebug' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{!cached && answer && (
|
||||
<Tooltip popupContent={t('feature.annotation.add', { ns: 'appDebug' })}>
|
||||
<ActionButton onClick={handleAdd}>
|
||||
<RiFileEditLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton onClick={handleAdd}>
|
||||
<RiFileEditLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('feature.annotation.add', { ns: 'appDebug' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -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 = ({
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex shrink-0 items-center gap-0.5">
|
||||
{!!features.moreLikeThis?.enabled && (
|
||||
<Tooltip
|
||||
popupContent={t('feature.moreLikeThis.title', { ns: 'appDebug' })}
|
||||
>
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-blue-light-blue-light-500 p-1 shadow-xs">
|
||||
<RiSparklingFill className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-blue-light-blue-light-500 p-1 shadow-xs">
|
||||
<RiSparklingFill className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('feature.moreLikeThis.title', { ns: 'appDebug' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{!!features.opening?.enabled && (
|
||||
<Tooltip
|
||||
popupContent={t('feature.conversationOpener.title', { ns: 'appDebug' })}
|
||||
>
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-blue-light-blue-light-500 p-1 shadow-xs">
|
||||
<LoveMessage className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-blue-light-blue-light-500 p-1 shadow-xs">
|
||||
<LoveMessage className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('feature.conversationOpener.title', { ns: 'appDebug' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{!!features.moderation?.enabled && (
|
||||
<Tooltip
|
||||
popupContent={t('feature.moderation.title', { ns: 'appDebug' })}
|
||||
>
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-text-success p-1 shadow-xs">
|
||||
<ContentModeration className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-text-success p-1 shadow-xs">
|
||||
<ContentModeration className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('feature.moderation.title', { ns: 'appDebug' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{!!features.speech2text?.enabled && (
|
||||
<Tooltip
|
||||
popupContent={t('feature.speechToText.title', { ns: 'appDebug' })}
|
||||
>
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-violet-violet-600 p-1 shadow-xs">
|
||||
<Microphone01 className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-violet-violet-600 p-1 shadow-xs">
|
||||
<Microphone01 className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('feature.speechToText.title', { ns: 'appDebug' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{!!features.text2speech?.enabled && (
|
||||
<VoiceSettings placementLeft={false} open={modalOpen && !disabled} onOpen={setModalOpen}>
|
||||
<Tooltip
|
||||
popupContent={t('feature.textToSpeech.title', { ns: 'appDebug' })}
|
||||
>
|
||||
<div className={cn('shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-violet-violet-600 p-1 shadow-xs', !disabled && 'cursor-pointer')}>
|
||||
<TextToAudio className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className={cn('shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-violet-violet-600 p-1 shadow-xs', !disabled && 'cursor-pointer')}>
|
||||
<TextToAudio className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('feature.textToSpeech.title', { ns: 'appDebug' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</VoiceSettings>
|
||||
)}
|
||||
{showFileUpload && !!features.file?.enabled && (
|
||||
<Tooltip
|
||||
popupContent={t('feature.fileUpload.title', { ns: 'appDebug' })}
|
||||
>
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-blue-blue-600 p-1 shadow-xs">
|
||||
<FolderUpload className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-blue-blue-600 p-1 shadow-xs">
|
||||
<FolderUpload className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('feature.fileUpload.title', { ns: 'appDebug' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{!!features.suggested?.enabled && (
|
||||
<Tooltip
|
||||
popupContent={t('feature.suggestedQuestionsAfterAnswer.title', { ns: 'appDebug' })}
|
||||
>
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-blue-light-blue-light-500 p-1 shadow-xs">
|
||||
<VirtualAssistant className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-blue-light-blue-light-500 p-1 shadow-xs">
|
||||
<VirtualAssistant className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('feature.suggestedQuestionsAfterAnswer.title', { ns: 'appDebug' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{isChatMode && !!features.citation?.enabled && (
|
||||
<Tooltip
|
||||
popupContent={t('feature.citation.title', { ns: 'appDebug' })}
|
||||
>
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-warning-warning-500 p-1 shadow-xs">
|
||||
<Citations className="h-4 w-4 text-text-primary-on-surface" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-warning-warning-500 p-1 shadow-xs">
|
||||
<Citations className="h-4 w-4 text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('feature.citation.title', { ns: 'appDebug' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{isChatMode && !!features.annotationReply?.enabled && (
|
||||
<Tooltip
|
||||
popupContent={t('feature.annotation.title', { ns: 'appDebug' })}
|
||||
>
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-indigo-indigo-600 p-1 shadow-xs">
|
||||
<MessageFast className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-indigo-indigo-600 p-1 shadow-xs">
|
||||
<MessageFast className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('feature.annotation.title', { ns: 'appDebug' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -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 = ({
|
||||
<div className="flex grow items-center system-sm-semibold text-text-secondary">
|
||||
{title}
|
||||
{tooltip && (
|
||||
<Tooltip
|
||||
popupContent={tooltip}
|
||||
>
|
||||
<div className="ml-0.5 p-px"><RiQuestionLine className="h-3.5 w-3.5 text-text-quaternary" /></div>
|
||||
<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>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -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 && (
|
||||
<Tooltip
|
||||
popupContent={name}
|
||||
>
|
||||
<div key={id}>
|
||||
<FileImageRender
|
||||
className="h-8 w-8"
|
||||
imageUrl={base64Url || url || ''}
|
||||
/>
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div key={id}>
|
||||
<FileImageRender
|
||||
className="h-8 w-8"
|
||||
imageUrl={base64Url || url || ''}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{name}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{!isImageFile && (
|
||||
<Tooltip
|
||||
popupContent={name}
|
||||
>
|
||||
<div key={id} className="rounded-md border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg p-1.5 shadow-xs">
|
||||
<FileTypeIcon
|
||||
type={getFileAppearanceType(name, type)}
|
||||
size="lg"
|
||||
/>
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div key={id} className="rounded-md border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg p-1.5 shadow-xs">
|
||||
<FileTypeIcon
|
||||
type={getFileAppearanceType(name, type)}
|
||||
size="lg"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{name}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -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<PdfPreviewProps> = ({
|
||||
}}
|
||||
</PdfLoader>
|
||||
</div>
|
||||
<Tooltip popupContent={t('operation.zoomOut', { ns: 'common' })}>
|
||||
<div
|
||||
className="absolute top-6 right-24 flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg"
|
||||
onClick={zoomOut}
|
||||
>
|
||||
<RiZoomOutLine className="h-4 w-4 text-gray-500" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div
|
||||
className="absolute top-6 right-24 flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg"
|
||||
onClick={zoomOut}
|
||||
>
|
||||
<RiZoomOutLine className="h-4 w-4 text-gray-500" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('operation.zoomOut', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip popupContent={t('operation.zoomIn', { ns: 'common' })}>
|
||||
<div
|
||||
className="absolute top-6 right-16 flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg"
|
||||
onClick={zoomIn}
|
||||
>
|
||||
<RiZoomInLine className="h-4 w-4 text-gray-500" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div
|
||||
className="absolute top-6 right-16 flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg"
|
||||
onClick={zoomIn}
|
||||
>
|
||||
<RiZoomInLine className="h-4 w-4 text-gray-500" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('operation.zoomIn', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip popupContent={t('operation.cancel', { ns: 'common' })}>
|
||||
<div
|
||||
className="absolute top-6 right-6 flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg bg-white/8 backdrop-blur-[2px]"
|
||||
onClick={onCancel}
|
||||
>
|
||||
<RiCloseLine className="h-4 w-4 text-gray-500" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div
|
||||
className="absolute top-6 right-6 flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg bg-white/8 backdrop-blur-[2px]"
|
||||
onClick={onCancel}
|
||||
>
|
||||
<RiCloseLine className="h-4 w-4 text-gray-500" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('operation.cancel', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>,
|
||||
document.body,
|
||||
|
||||
@@ -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<ImageListProps> = ({
|
||||
<span className="i-ri-loader-2-line h-5 w-5 animate-spin text-white" data-testid="image-loader" />
|
||||
)}
|
||||
{item.progress === -1 && (
|
||||
<Tooltip
|
||||
popupContent={t('imageUploader.pasteImageLinkInvalid', { ns: 'common' })}
|
||||
>
|
||||
<AlertTriangle className="h-4 w-4 text-[#DC6803]" />
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<AlertTriangle className="h-4 w-4 text-[#DC6803]" />
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('imageUploader.pasteImageLinkInvalid', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -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<ImagePreviewProps> = ({
|
||||
}}
|
||||
data-testid="image-preview-image"
|
||||
/>
|
||||
<Tooltip popupContent={t('operation.copyImage', { ns: 'common' })}>
|
||||
<div
|
||||
className="absolute top-6 right-48 flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg"
|
||||
onClick={imageCopy}
|
||||
>
|
||||
{isCopied
|
||||
? <span className="i-ri-file-copy-line h-4 w-4 text-green-500" data-testid="image-preview-copied-icon" />
|
||||
: <span className="i-ri-file-copy-line h-4 w-4 text-gray-500" data-testid="image-preview-copy-button" />}
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div
|
||||
className="absolute top-6 right-48 flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg"
|
||||
onClick={imageCopy}
|
||||
>
|
||||
{isCopied
|
||||
? <span className="i-ri-file-copy-line h-4 w-4 text-green-500" data-testid="image-preview-copied-icon" />
|
||||
: <span className="i-ri-file-copy-line h-4 w-4 text-gray-500" data-testid="image-preview-copy-button" />}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('operation.copyImage', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip popupContent={t('operation.zoomOut', { ns: 'common' })}>
|
||||
<div
|
||||
className="absolute top-6 right-40 flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg"
|
||||
onClick={zoomOut}
|
||||
>
|
||||
<span className="i-ri-zoom-out-line h-4 w-4 text-gray-500" data-testid="image-preview-zoom-out-button" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div
|
||||
className="absolute top-6 right-40 flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg"
|
||||
onClick={zoomOut}
|
||||
>
|
||||
<span className="i-ri-zoom-out-line h-4 w-4 text-gray-500" data-testid="image-preview-zoom-out-button" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('operation.zoomOut', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip popupContent={t('operation.zoomIn', { ns: 'common' })}>
|
||||
<div
|
||||
className="absolute top-6 right-32 flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg"
|
||||
onClick={zoomIn}
|
||||
>
|
||||
<span className="i-ri-zoom-in-line h-4 w-4 text-gray-500" data-testid="image-preview-zoom-in-button" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div
|
||||
className="absolute top-6 right-32 flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg"
|
||||
onClick={zoomIn}
|
||||
>
|
||||
<span className="i-ri-zoom-in-line h-4 w-4 text-gray-500" data-testid="image-preview-zoom-in-button" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('operation.zoomIn', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip popupContent={t('operation.download', { ns: 'common' })}>
|
||||
<div
|
||||
className="absolute top-6 right-24 flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg"
|
||||
onClick={downloadImage}
|
||||
>
|
||||
<span className="i-ri-download-cloud-2-line h-4 w-4 text-gray-500" data-testid="image-preview-download-button" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div
|
||||
className="absolute top-6 right-24 flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg"
|
||||
onClick={downloadImage}
|
||||
>
|
||||
<span className="i-ri-download-cloud-2-line h-4 w-4 text-gray-500" data-testid="image-preview-download-button" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('operation.download', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip popupContent={t('operation.openInNewTab', { ns: 'common' })}>
|
||||
<div
|
||||
className="absolute top-6 right-16 flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg"
|
||||
onClick={openInNewTab}
|
||||
>
|
||||
<span className="i-ri-add-box-line h-4 w-4 text-gray-500" data-testid="image-preview-open-in-tab-button" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div
|
||||
className="absolute top-6 right-16 flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg"
|
||||
onClick={openInNewTab}
|
||||
>
|
||||
<span className="i-ri-add-box-line h-4 w-4 text-gray-500" data-testid="image-preview-open-in-tab-button" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('operation.openInNewTab', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip popupContent={t('operation.cancel', { ns: 'common' })}>
|
||||
<div
|
||||
className="absolute top-6 right-6 flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg bg-white/8 backdrop-blur-[2px]"
|
||||
onClick={onCancel}
|
||||
>
|
||||
<span className="i-ri-close-line h-4 w-4 text-gray-500" data-testid="image-preview-close-button" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div
|
||||
className="absolute top-6 right-6 flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg bg-white/8 backdrop-blur-[2px]"
|
||||
onClick={onCancel}
|
||||
>
|
||||
<span className="i-ri-close-line h-4 w-4 text-gray-500" data-testid="image-preview-close-button" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('operation.cancel', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>,
|
||||
document.body,
|
||||
|
||||
@@ -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 (
|
||||
<Tooltip
|
||||
popupContent={tooltipContent}
|
||||
>
|
||||
<ActionButton
|
||||
state={
|
||||
audioState === 'loading' || audioState === 'playing'
|
||||
? ActionButtonState.Active
|
||||
: ActionButtonState.Default
|
||||
}
|
||||
onClick={handleToggle}
|
||||
disabled={audioState === 'loading'}
|
||||
>
|
||||
<RiVolumeUpLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<span className="inline-flex">
|
||||
<ActionButton
|
||||
state={
|
||||
audioState === 'loading' || audioState === 'playing'
|
||||
? ActionButtonState.Active
|
||||
: ActionButtonState.Default
|
||||
}
|
||||
onClick={handleToggle}
|
||||
disabled={audioState === 'loading'}
|
||||
>
|
||||
<RiVolumeUpLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
</span>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{tooltipContent}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
<Tooltip
|
||||
popupContent={safeTooltipText}
|
||||
>
|
||||
<div className="relative h-6 w-6" onClick={toggleQRCode} data-testid="qrcode-container">
|
||||
<ActionButton>
|
||||
<span className="i-ri-qr-code-line h-4 w-4" />
|
||||
</ActionButton>
|
||||
{isShow && (
|
||||
<div
|
||||
ref={qrCodeRef}
|
||||
className="absolute top-8 -right-8 z-10 flex w-[232px] flex-col items-center rounded-lg bg-components-panel-bg p-4 shadow-xs"
|
||||
onClick={handlePanelClick}
|
||||
>
|
||||
<QRCode size={160} value={content} className="mb-2" />
|
||||
<div className="flex items-center system-xs-regular">
|
||||
<div className="text-text-tertiary">{t('overview.appInfo.qrcode.scan', { ns: 'appOverview' })}</div>
|
||||
<div className="text-text-tertiary">·</div>
|
||||
<div className="cursor-pointer text-text-accent-secondary" onClick={downloadQR}>{t('overview.appInfo.qrcode.download', { ns: 'appOverview' })}</div>
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="relative h-6 w-6" onClick={toggleQRCode} data-testid="qrcode-container">
|
||||
<ActionButton>
|
||||
<span className="i-ri-qr-code-line h-4 w-4" />
|
||||
</ActionButton>
|
||||
{isShow && (
|
||||
<div
|
||||
ref={qrCodeRef}
|
||||
className="absolute top-8 -right-8 z-10 flex w-[232px] flex-col items-center rounded-lg bg-components-panel-bg p-4 shadow-xs"
|
||||
onClick={handlePanelClick}
|
||||
>
|
||||
<QRCode size={160} value={content} className="mb-2" />
|
||||
<div className="flex items-center system-xs-regular">
|
||||
<div className="text-text-tertiary">{t('overview.appInfo.qrcode.scan', { ns: 'appOverview' })}</div>
|
||||
<div className="text-text-tertiary">·</div>
|
||||
<div className="cursor-pointer text-text-accent-secondary" onClick={downloadQR}>{t('overview.appInfo.qrcode.download', { ns: 'appOverview' })}</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
/>
|
||||
<TooltipContent>
|
||||
{safeTooltipText}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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<GeneralChunkingOptionsProps> = ({
|
||||
onSelect={onDocLanguageChange}
|
||||
disabled={currentDocForm !== ChunkingMode.qa}
|
||||
/>
|
||||
<Tooltip popupContent={t('stepTwo.QATip', { ns: 'datasetCreation' })} />
|
||||
<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>
|
||||
</div>
|
||||
{currentDocForm === ChunkingMode.qa && (
|
||||
<div
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { FC } from 'react'
|
||||
import type { SimpleDocumentDetail } from '@/models/datasets'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { pick } from 'es-toolkit/object'
|
||||
import * as React from 'react'
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Checkbox from '@/app/components/base/checkbox'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import ChunkingModeLabel from '@/app/components/datasets/common/chunking-mode-label'
|
||||
import Operations from '@/app/components/datasets/documents/components/operations'
|
||||
import SummaryStatus from '@/app/components/datasets/documents/detail/completed/common/summary-status'
|
||||
@@ -101,8 +101,15 @@ const DocumentTableRow: FC<DocumentTableRowProps> = React.memo(({
|
||||
<div className="flex shrink-0 items-center">
|
||||
<DocumentSourceIcon doc={doc} fileType={fileType} />
|
||||
</div>
|
||||
<Tooltip popupContent={doc.name}>
|
||||
<span className="grow truncate text-sm">{doc.name}</span>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<span className="grow truncate text-sm">{doc.name}</span>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{doc.name}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
{doc.summary_index_status && (
|
||||
<div className="ml-1 hidden shrink-0 group-hover:flex">
|
||||
@@ -110,13 +117,20 @@ const DocumentTableRow: FC<DocumentTableRowProps> = React.memo(({
|
||||
</div>
|
||||
)}
|
||||
<div className="hidden shrink-0 group-hover:ml-auto group-hover:flex">
|
||||
<Tooltip popupContent={t('list.table.rename', { ns: 'datasetDocuments' })}>
|
||||
<div
|
||||
className="cursor-pointer rounded-md p-1 hover:bg-state-base-hover"
|
||||
onClick={handleRenameClick}
|
||||
>
|
||||
<span className="i-ri-edit-line h-4 w-4 text-text-tertiary" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div
|
||||
className="cursor-pointer rounded-md p-1 hover:bg-state-base-hover"
|
||||
onClick={handleRenameClick}
|
||||
>
|
||||
<span className="i-ri-edit-line h-4 w-4 text-text-tertiary" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('list.table.rename', { ns: 'datasetDocuments' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -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 (
|
||||
<Tooltip popupContent={metadataMap[type].text}>
|
||||
<button type="button" className={cn(s.iconWrapper, 'group', isChecked ? s.iconCheck : '')}>
|
||||
<TypeIcon
|
||||
iconName={metadataMap[type].iconName || ''}
|
||||
className={`group-hover:bg-primary-600 ${isChecked ? 'bg-primary-600!' : ''}`}
|
||||
/>
|
||||
</button>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<button type="button" className={cn(s.iconWrapper, 'group', isChecked ? s.iconCheck : '')}>
|
||||
<TypeIcon
|
||||
iconName={metadataMap[type].iconName || ''}
|
||||
className={`group-hover:bg-primary-600 ${isChecked ? 'bg-primary-600!' : ''}`}
|
||||
/>
|
||||
</button>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{metadataMap[type].text}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
? (
|
||||
<Tooltip
|
||||
popupContent={t('input.countWarning', { ns: 'datasetHitTesting' })}
|
||||
>
|
||||
<div
|
||||
className={cn('bg-util-colors-red-red-100 py-1 pr-2 system-2xs-medium-uppercase text-util-colors-red-red-600')}
|
||||
>
|
||||
{`${text.length}/200`}
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div
|
||||
className={cn('bg-util-colors-red-red-100 py-1 pr-2 system-2xs-medium-uppercase text-util-colors-red-red-600')}
|
||||
>
|
||||
{`${text.length}/200`}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('input.countWarning', { ns: 'datasetHitTesting' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
: (
|
||||
|
||||
@@ -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',
|
||||
)}
|
||||
>
|
||||
<Tooltip popupContent={documentCountTooltip}>
|
||||
<div className="flex items-center gap-x-1">
|
||||
<RiFileTextFill className="size-3 text-text-quaternary" />
|
||||
<span className="system-xs-medium">{documentCount}</span>
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="flex items-center gap-x-1">
|
||||
<RiFileTextFill className="size-3 text-text-quaternary" />
|
||||
<span className="system-xs-medium">{documentCount}</span>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{documentCountTooltip}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
{!isExternalProvider && (
|
||||
<Tooltip popupContent={`${dataset.app_count} ${t('appCount', { ns: 'dataset' })}`}>
|
||||
<div className="flex items-center gap-x-1">
|
||||
<RiRobot2Fill className="size-3 text-text-quaternary" />
|
||||
<span className="system-xs-medium">{dataset.app_count}</span>
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="flex items-center gap-x-1">
|
||||
<RiRobot2Fill className="size-3 text-text-quaternary" />
|
||||
<span className="system-xs-medium">{dataset.app_count}</span>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{`${dataset.app_count} ${t('appCount', { ns: 'dataset' })}`}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
<span className="system-xs-regular text-divider-deep">/</span>
|
||||
|
||||
@@ -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<Props> = ({
|
||||
<div ref={ref} className="size-4 cursor-pointer">
|
||||
{isHovering
|
||||
? (
|
||||
<Tooltip popupContent={t('operation.reset', { ns: 'common' })}>
|
||||
<div className="flex size-4 items-center justify-center rounded-full bg-text-accent-secondary" onClick={onReset}>
|
||||
<RiResetLeftLine className="size-[10px] text-text-primary-on-surface" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="flex size-4 items-center justify-center rounded-full bg-text-accent-secondary" onClick={onReset}>
|
||||
<RiResetLeftLine className="size-[10px] text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('operation.reset', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
: (
|
||||
|
||||
@@ -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 = ({
|
||||
<div className="truncate system-xs-medium text-text-secondary">
|
||||
{t('form.numberOfKeywords', { ns: 'datasetSettings' })}
|
||||
</div>
|
||||
<Tooltip
|
||||
popupContent={t('form.numberOfKeywords', { ns: 'datasetSettings' })}
|
||||
>
|
||||
<span className="i-ri-question-line h-3.5 w-3.5 text-text-quaternary" />
|
||||
<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>
|
||||
</div>
|
||||
<Slider
|
||||
|
||||
@@ -5,6 +5,7 @@ import type {
|
||||
} from '@/app/components/base/chat/embedded-chatbot/context'
|
||||
import type { TryAppInfo } from '@/service/try-app'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { RiResetLeftLine } from '@remixicon/react'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import * as React from 'react'
|
||||
@@ -21,7 +22,6 @@ import {
|
||||
useEmbeddedChatbot,
|
||||
} from '@/app/components/base/chat/embedded-chatbot/hooks'
|
||||
import ViewFormDropdown from '@/app/components/base/chat/embedded-chatbot/inputs-form/view-form-dropdown'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import { AppSourceType } from '@/service/share'
|
||||
import { useThemeContext } from '../../../base/chat/embedded-chatbot/theme/theme-context'
|
||||
@@ -78,12 +78,17 @@ const TryApp: FC<Props> = ({
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
{currentConversationId && (
|
||||
<Tooltip
|
||||
popupContent={t('chat.resetChat', { ns: 'share' })}
|
||||
>
|
||||
<ActionButton size="l" onClick={handleNewConversation}>
|
||||
<RiResetLeftLine className="h-[18px] w-[18px]" />
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton size="l" onClick={handleNewConversation}>
|
||||
<RiResetLeftLine className="h-[18px] w-[18px]" />
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('chat.resetChat', { ns: 'share' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{currentConversationId && inputsForms.length > 0 && (
|
||||
|
||||
@@ -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(<FeatureIcon feature={feature} />)
|
||||
fireEvent.mouseEnter(container.firstElementChild as HTMLElement)
|
||||
await userEvent.hover(container.firstElementChild as HTMLElement)
|
||||
expect(await screen.findByText(`common.modelProvider.featureSupported:{"feature":"${text}"}`))
|
||||
.toBeInTheDocument()
|
||||
unmount()
|
||||
|
||||
@@ -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<FeatureIconProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
popupContent={t('modelProvider.featureSupported', { ns: 'common', feature: ModelFeatureTextEnum.vision })}
|
||||
>
|
||||
<div className="inline-block cursor-help">
|
||||
<ModelBadge
|
||||
className={cn(
|
||||
'w-[18px] justify-center px-0!',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<RiImageCircleAiLine className="size-3" />
|
||||
</ModelBadge>
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="inline-block cursor-help">
|
||||
<ModelBadge
|
||||
className={cn(
|
||||
'w-[18px] justify-center px-0!',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<RiImageCircleAiLine className="size-3" />
|
||||
</ModelBadge>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('modelProvider.featureSupported', { ns: 'common', feature: ModelFeatureTextEnum.vision })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
@@ -105,19 +110,24 @@ const FeatureIcon: FC<FeatureIconProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
popupContent={t('modelProvider.featureSupported', { ns: 'common', feature: ModelFeatureTextEnum.document })}
|
||||
>
|
||||
<div className="inline-block cursor-help">
|
||||
<ModelBadge
|
||||
className={cn(
|
||||
'w-[18px] justify-center px-0!',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<RiFileTextLine className="size-3" />
|
||||
</ModelBadge>
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="inline-block cursor-help">
|
||||
<ModelBadge
|
||||
className={cn(
|
||||
'w-[18px] justify-center px-0!',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<RiFileTextLine className="size-3" />
|
||||
</ModelBadge>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('modelProvider.featureSupported', { ns: 'common', feature: ModelFeatureTextEnum.document })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
@@ -135,19 +145,24 @@ const FeatureIcon: FC<FeatureIconProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
popupContent={t('modelProvider.featureSupported', { ns: 'common', feature: ModelFeatureTextEnum.audio })}
|
||||
>
|
||||
<div className="inline-block cursor-help">
|
||||
<ModelBadge
|
||||
className={cn(
|
||||
'w-[18px] justify-center px-0!',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<RiVoiceAiFill className="size-3" />
|
||||
</ModelBadge>
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="inline-block cursor-help">
|
||||
<ModelBadge
|
||||
className={cn(
|
||||
'w-[18px] justify-center px-0!',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<RiVoiceAiFill className="size-3" />
|
||||
</ModelBadge>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('modelProvider.featureSupported', { ns: 'common', feature: ModelFeatureTextEnum.audio })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
@@ -165,19 +180,24 @@ const FeatureIcon: FC<FeatureIconProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
popupContent={t('modelProvider.featureSupported', { ns: 'common', feature: ModelFeatureTextEnum.video })}
|
||||
>
|
||||
<div className="inline-block cursor-help">
|
||||
<ModelBadge
|
||||
className={cn(
|
||||
'w-[18px] justify-center px-0!',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<RiFilmAiLine className="size-3" />
|
||||
</ModelBadge>
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="inline-block cursor-help">
|
||||
<ModelBadge
|
||||
className={cn(
|
||||
'w-[18px] justify-center px-0!',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<RiFilmAiLine className="size-3" />
|
||||
</ModelBadge>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('modelProvider.featureSupported', { ns: 'common', feature: ModelFeatureTextEnum.video })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
? (
|
||||
<Tooltip popupContent={t('modelProvider.apiKeyRateLimit', { ns: 'common', seconds: displayTime })}>
|
||||
<SimplePieChart percentage={Math.round(displayTime / 60 * 100)} className="h-3 w-3" />
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<SimplePieChart percentage={Math.round(displayTime / 60 * 100)} className="h-3 w-3" />
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('modelProvider.apiKeyRateLimit', { ns: 'common', seconds: displayTime })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
: null
|
||||
|
||||
@@ -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 = ({
|
||||
<div className="grow">
|
||||
<div className="flex items-center gap-1 text-sm text-text-primary">
|
||||
{t('modelProvider.loadBalancing', { ns: 'common' })}
|
||||
<Tooltip
|
||||
popupContent={t('modelProvider.loadBalancingInfo', { ns: 'common' })}
|
||||
popupClassName="max-w-[300px]"
|
||||
triggerClassName="w-3 h-3"
|
||||
/>
|
||||
<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>
|
||||
</div>
|
||||
<div className="text-xs text-text-tertiary">{t('modelProvider.loadBalancingDescription', { ns: 'common' })}</div>
|
||||
</div>
|
||||
@@ -187,8 +194,15 @@ const ModelLoadBalancingConfigs = ({
|
||||
<CooldownTimer secondsRemaining={config.ttl} onFinish={() => clearCountdown(index)} />
|
||||
)
|
||||
: (
|
||||
<Tooltip popupContent={t('modelProvider.apiKeyStatusNormal', { ns: 'common' })}>
|
||||
<Indicator color={credential?.not_allowed_to_use ? 'gray' : 'green'} />
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<Indicator color={credential?.not_allowed_to_use ? 'gray' : 'green'} />
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('modelProvider.apiKeyStatusNormal', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
@@ -208,14 +222,21 @@ const ModelLoadBalancingConfigs = ({
|
||||
{!isProviderManaged && (
|
||||
<>
|
||||
<div className="flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100">
|
||||
<Tooltip popupContent={t('operation.remove', { ns: 'common' })}>
|
||||
<span
|
||||
className="flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg bg-components-button-secondary-bg text-text-tertiary transition-colors hover:bg-components-button-secondary-bg-hover"
|
||||
onClick={() => updateConfigEntry(index, () => undefined)}
|
||||
data-testid={`load-balancing-remove-${config.id || index}`}
|
||||
>
|
||||
<div className="i-ri-indeterminate-circle-line h-4 w-4" />
|
||||
</span>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<span
|
||||
className="flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg bg-components-button-secondary-bg text-text-tertiary transition-colors hover:bg-components-button-secondary-bg-hover"
|
||||
onClick={() => updateConfigEntry(index, () => undefined)}
|
||||
data-testid={`load-balancing-remove-${config.id || index}`}
|
||||
>
|
||||
<div className="i-ri-indeterminate-circle-line h-4 w-4" />
|
||||
</span>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('operation.remove', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -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 (
|
||||
<Tooltip
|
||||
popupContent={t('modelProvider.priorityUsing', { ns: 'common' }) || ''}
|
||||
>
|
||||
<div className="absolute -top-[5px] -right-[5px] cursor-pointer rounded-[5px] border-[0.5px] border-components-panel-border-subtle bg-util-colors-indigo-indigo-50 shadow-xs">
|
||||
<ChevronDownDouble className="h-3 w-3 rotate-180 text-util-colors-indigo-indigo-600" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="absolute -top-[5px] -right-[5px] cursor-pointer rounded-[5px] border-[0.5px] border-components-panel-border-subtle bg-util-colors-indigo-indigo-50 shadow-xs">
|
||||
<ChevronDownDouble className="h-3 w-3 rotate-180 text-util-colors-indigo-indigo-600" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('modelProvider.priorityUsing', { ns: 'common' }) || ''}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
<Tooltip popupContent={t('auth.credentialUnavailable', { ns: 'plugin' })}>
|
||||
{Item}
|
||||
<Tooltip>
|
||||
<TooltipTrigger render={Item} />
|
||||
<TooltipContent>
|
||||
{t('auth.credentialUnavailable', { ns: 'plugin' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
@@ -100,8 +103,11 @@ const Authorize = ({
|
||||
|
||||
if (notAllowCustomCredential) {
|
||||
return (
|
||||
<Tooltip popupContent={t('auth.credentialUnavailable', { ns: 'plugin' })}>
|
||||
{Item}
|
||||
<Tooltip>
|
||||
<TooltipTrigger render={Item} />
|
||||
<TooltipContent>
|
||||
{t('auth.credentialUnavailable', { ns: 'plugin' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ describe('Item Component', () => {
|
||||
|
||||
const { container } = render(<Item credential={credential} />)
|
||||
|
||||
expect(container.querySelector('[data-state]')).toBeInTheDocument()
|
||||
expect(container.firstElementChild).toHaveClass('cursor-not-allowed', 'opacity-50')
|
||||
})
|
||||
|
||||
it('should not call onItemClick when disabled is true', () => {
|
||||
|
||||
@@ -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 && (
|
||||
<Tooltip popupContent={t('operation.rename', { ns: 'common' })}>
|
||||
<ActionButton
|
||||
disabled={disabled}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setRenaming(true)
|
||||
setRenameValue(credential.name)
|
||||
}}
|
||||
>
|
||||
<RiEditLine className="h-4 w-4 text-text-tertiary" />
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton
|
||||
disabled={disabled}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setRenaming(true)
|
||||
setRenameValue(credential.name)
|
||||
}}
|
||||
>
|
||||
<RiEditLine className="h-4 w-4 text-text-tertiary" />
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('operation.rename', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
{
|
||||
!isOAuth && !disableEdit && !credential.from_enterprise && !credential.not_allowed_to_use && (
|
||||
<Tooltip popupContent={t('operation.edit', { ns: 'common' })}>
|
||||
<ActionButton
|
||||
disabled={disabled}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
onEdit?.(
|
||||
credential.id,
|
||||
{
|
||||
...credential.credentials,
|
||||
__name__: credential.name,
|
||||
__credential_id__: credential.id,
|
||||
},
|
||||
)
|
||||
}}
|
||||
>
|
||||
<RiEqualizer2Line className="h-4 w-4 text-text-tertiary" />
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton
|
||||
disabled={disabled}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
onEdit?.(
|
||||
credential.id,
|
||||
{
|
||||
...credential.credentials,
|
||||
__name__: credential.name,
|
||||
__credential_id__: credential.id,
|
||||
},
|
||||
)
|
||||
}}
|
||||
>
|
||||
<RiEqualizer2Line className="h-4 w-4 text-text-tertiary" />
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('operation.edit', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
{
|
||||
!disableDelete && !credential.from_enterprise && (
|
||||
<Tooltip popupContent={t('operation.delete', { ns: 'common' })}>
|
||||
<ActionButton
|
||||
className="hover:bg-transparent"
|
||||
disabled={disabled}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
onDelete?.(credential.id)
|
||||
}}
|
||||
>
|
||||
<RiDeleteBinLine className="h-4 w-4 text-text-tertiary hover:text-text-destructive" />
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton
|
||||
className="hover:bg-transparent"
|
||||
disabled={disabled}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
onDelete?.(credential.id)
|
||||
}}
|
||||
>
|
||||
<RiDeleteBinLine className="h-4 w-4 text-text-tertiary hover:text-text-destructive" />
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('operation.delete', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
@@ -232,8 +253,11 @@ const Item = ({
|
||||
|
||||
if (credential.not_allowed_to_use) {
|
||||
return (
|
||||
<Tooltip popupContent={t('auth.customCredentialUnavailable', { ns: 'plugin' })}>
|
||||
{CredentialItem}
|
||||
<Tooltip>
|
||||
<TooltipTrigger render={CredentialItem} />
|
||||
<TooltipContent>
|
||||
{t('auth.customCredentialUnavailable', { ns: 'plugin' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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 = ({
|
||||
<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
|
||||
popupContent={tooltip}
|
||||
>
|
||||
<div><RiQuestionLine className="h-3.5 w-3.5 text-text-quaternary hover:text-text-tertiary" /></div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div><RiQuestionLine className="h-3.5 w-3.5 text-text-quaternary hover:text-text-tertiary" /></div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{tooltip}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{supportCollapse && (
|
||||
|
||||
@@ -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
|
||||
</Badge>
|
||||
),
|
||||
extra: (
|
||||
<Tooltip popupContent={t('subscription.addType.options.oauth.clientSettings', { ns: 'pluginTrigger' })}>
|
||||
<ActionButton onClick={onClickClientSettings}>
|
||||
<RiEqualizer2Line className="h-4 w-4 text-text-tertiary" />
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton onClick={onClickClientSettings}>
|
||||
<RiEqualizer2Line className="h-4 w-4 text-text-tertiary" />
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('subscription.addType.options.oauth.clientSettings', { ns: 'pluginTrigger' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
),
|
||||
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: <Tooltip popupContent={t('subscription.addType.options.manual.tip', { 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>
|
||||
),
|
||||
show: supportedMethods.includes(SupportedCreationMethods.MANUAL),
|
||||
},
|
||||
]
|
||||
@@ -196,30 +216,42 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU
|
||||
&& (
|
||||
<div className="ml-auto flex items-center">
|
||||
<div className="h-4 w-px bg-text-primary-on-surface opacity-15" />
|
||||
<Tooltip popupContent={t('subscription.addType.options.oauth.clientSettings', { ns: 'pluginTrigger' })}>
|
||||
<div onClick={onClickClientSettings} className="p-2">
|
||||
<RiEqualizer2Line className="size-4 text-components-button-primary-text" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div onClick={onClickClientSettings} className="p-2">
|
||||
<RiEqualizer2Line className="size-4 text-components-button-primary-text" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('subscription.addType.options.oauth.clientSettings', { ns: 'pluginTrigger' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
</Button>
|
||||
)
|
||||
: (
|
||||
<Tooltip
|
||||
popupContent={subscriptionCount >= MAX_COUNT ? t('subscription.maxCount', { ns: 'pluginTrigger', num: MAX_COUNT }) : t(`subscription.addType.options.${methodType!.toLowerCase() as Lowercase<SupportedCreationMethods>}.description`, { ns: 'pluginTrigger' })}
|
||||
disabled={!(supportedMethods?.length === 1 || subscriptionCount >= MAX_COUNT)}
|
||||
>
|
||||
<ActionButton
|
||||
onClick={onClickCreate}
|
||||
className={cn(
|
||||
'float-right',
|
||||
shape === 'circle' && 'rounded-full! border-[0.5px] border-components-button-secondary-border-hover bg-components-button-secondary-bg-hover text-components-button-secondary-accent-text shadow-xs hover:border-components-button-secondary-border-disabled hover:bg-components-button-secondary-bg-disabled hover:text-components-button-secondary-accent-text-disabled',
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
disabled={!(supportedMethods?.length === 1 || subscriptionCount >= MAX_COUNT)}
|
||||
render={(
|
||||
<ActionButton
|
||||
onClick={onClickCreate}
|
||||
className={cn(
|
||||
'float-right',
|
||||
shape === 'circle' && 'rounded-full! border-[0.5px] border-components-button-secondary-border-hover bg-components-button-secondary-bg-hover text-components-button-secondary-accent-text shadow-xs hover:border-components-button-secondary-border-disabled hover:bg-components-button-secondary-bg-disabled hover:text-components-button-secondary-accent-text-disabled',
|
||||
)}
|
||||
state={subscriptionCount >= MAX_COUNT ? ActionButtonState.Disabled : ActionButtonState.Default}
|
||||
>
|
||||
<RiAddLine className="size-4" />
|
||||
</ActionButton>
|
||||
)}
|
||||
state={subscriptionCount >= MAX_COUNT ? ActionButtonState.Disabled : ActionButtonState.Default}
|
||||
>
|
||||
<RiAddLine className="size-4" />
|
||||
</ActionButton>
|
||||
/>
|
||||
<TooltipContent>
|
||||
{subscriptionCount >= MAX_COUNT ? t('subscription.maxCount', { ns: 'pluginTrigger', num: MAX_COUNT }) : t(`subscription.addType.options.${methodType!.toLowerCase() as Lowercase<SupportedCreationMethods>}.description`, { ns: 'pluginTrigger' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</SelectTrigger>
|
||||
|
||||
@@ -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<SubscriptionListViewProps> = ({
|
||||
<span className="system-sm-semibold-uppercase text-text-secondary">
|
||||
{t('subscription.listNum', { ns: 'pluginTrigger', num: subscriptionCount })}
|
||||
</span>
|
||||
<Tooltip popupContent={t('subscription.list.tip', { ns: 'pluginTrigger' })} />
|
||||
<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>
|
||||
</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 Tooltip from '@/app/components/base/tooltip'
|
||||
import { CreateButtonType, CreateSubscriptionButton } from './create'
|
||||
import { DeleteConfirm } from './delete-confirm'
|
||||
import { useSubscriptionList } from './use-subscription-list'
|
||||
@@ -33,7 +33,18 @@ export const SubscriptionSelectorView: React.FC<SubscriptionSelectorProps> = ({
|
||||
<span className="system-sm-semibold-uppercase text-text-secondary">
|
||||
{t('subscription.listNum', { ns: 'pluginTrigger', num: subscriptionCount })}
|
||||
</span>
|
||||
<Tooltip popupContent={t('subscription.list.tip', { ns: 'pluginTrigger' })} />
|
||||
<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>
|
||||
</div>
|
||||
<CreateSubscriptionButton
|
||||
buttonType={CreateButtonType.ICON_BUTTON}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import ToolItem from '../tool-item'
|
||||
|
||||
@@ -26,21 +27,6 @@ vi.mock('@/app/components/workflow/nodes/_base/components/switch-plugin-version'
|
||||
),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/tooltip', () => ({
|
||||
default: ({
|
||||
children,
|
||||
popupContent,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
popupContent: React.ReactNode
|
||||
}) => (
|
||||
<div>
|
||||
{children}
|
||||
<div>{popupContent}</div>
|
||||
</div>
|
||||
),
|
||||
}))
|
||||
|
||||
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(
|
||||
<ToolItem
|
||||
@@ -125,6 +111,7 @@ describe('ToolItem', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('tool failed')).toBeInTheDocument()
|
||||
await userEvent.hover(screen.getByLabelText('tool failed'))
|
||||
expect(await screen.findByText('tool failed')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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 && (
|
||||
<Tooltip
|
||||
popupContent={errorTip}
|
||||
>
|
||||
<div>
|
||||
<RiErrorWarningFill className="h-4 w-4 text-text-destructive" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div aria-label={typeof errorTip === 'string' ? errorTip : undefined}>
|
||||
<RiErrorWarningFill className="h-4 w-4 text-text-destructive" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{errorTip}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -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 && (
|
||||
<Tooltip
|
||||
popupContent={t('privilege.title', { ns: 'plugin' })}
|
||||
>
|
||||
<Button
|
||||
data-testid="plugin-settings-button"
|
||||
className="group h-full w-full p-2 text-components-button-secondary-text"
|
||||
onClick={setShowPluginSettingModal}
|
||||
>
|
||||
<RiEqualizer2Line className="h-4 w-4" />
|
||||
</Button>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<Button
|
||||
data-testid="plugin-settings-button"
|
||||
className="group h-full w-full p-2 text-components-button-secondary-text"
|
||||
onClick={setShowPluginSettingModal}
|
||||
>
|
||||
<RiEqualizer2Line className="h-4 w-4" />
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('privilege.title', { ns: 'plugin' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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<Props> = ({
|
||||
title={t(`${i18nPrefix}.vision`, { ns: 'workflow' })}
|
||||
tooltip={t('vision.description', { ns: 'appDebug' })!}
|
||||
operations={(
|
||||
<Tooltip
|
||||
popupContent={t('vision.onlySupportVisionModelTip', { ns: 'appDebug' })!}
|
||||
disabled={isVisionModel}
|
||||
>
|
||||
<Switch disabled={readOnly || !isVisionModel} size="md" checked={!isVisionModel ? false : enabled} onCheckedChange={onEnabledChange} />
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
disabled={isVisionModel}
|
||||
render={(
|
||||
<Switch disabled={readOnly || !isVisionModel} size="md" checked={!isVisionModel ? false : enabled} onCheckedChange={onEnabledChange} />
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('vision.onlySupportVisionModelTip', { ns: 'appDebug' })!}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -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<Props> = ({
|
||||
{readOnly && <div className="absolute inset-0 z-10"></div>}
|
||||
{isFocus && (
|
||||
<div className={cn('absolute z-10', insertVarTipToLeft ? 'top-1.5 left-[-12px]' : 'top-[-9px] right-1')}>
|
||||
<Tooltip
|
||||
popupContent={`${t('common.insertVarTip', { ns: 'workflow' })}`}
|
||||
>
|
||||
<div className="cursor-pointer rounded-[5px] border-[0.5px] border-divider-regular bg-components-badge-white-to-dark p-0.5 shadow-lg">
|
||||
<Variable02 className="h-3.5 w-3.5 text-components-button-secondary-accent-text" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div className="cursor-pointer rounded-[5px] border-[0.5px] border-divider-regular bg-components-badge-white-to-dark p-0.5 shadow-lg">
|
||||
<Variable02 className="h-3.5 w-3.5 text-components-button-secondary-accent-text" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{`${t('common.insertVarTip', { ns: 'workflow' })}`}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -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
|
||||
<div className={cn('max-w-full shrink-0 truncate system-xs-medium-uppercase text-text-tertiary', !!children && 'max-w-[100px]')}>
|
||||
{label}
|
||||
</div>
|
||||
<Tooltip popupContent={tooltip} disabled={!needTooltip}>
|
||||
<div className="truncate text-right system-xs-medium text-text-secondary">
|
||||
{children}
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
disabled={!needTooltip}
|
||||
render={(
|
||||
<div className="truncate text-right system-xs-medium text-text-secondary">
|
||||
{children}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{tooltip}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
{indicator && <Indicator color={indicator} className="absolute -top-0.5 -right-0.5" />}
|
||||
</div>
|
||||
|
||||
@@ -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<Props> = ({
|
||||
return null
|
||||
return (
|
||||
<div>
|
||||
<Tooltip popupContent={t('structOutput.moreFillTip', { ns: 'app' })} disabled={depth !== MAX_DEPTH + 1}>
|
||||
<div
|
||||
className={cn('flex items-center justify-between rounded-md pr-2', !readonly && 'hover:bg-state-base-hover', depth !== MAX_DEPTH + 1 && 'cursor-pointer')}
|
||||
onMouseDown={() => !readonly && onSelect?.([...valueSelector, name])}
|
||||
>
|
||||
<div className="flex grow items-stretch">
|
||||
<TreeIndentLine depth={depth} />
|
||||
{depth === MAX_DEPTH + 1
|
||||
? (
|
||||
<RiMoreFill className="h-3 w-3 text-text-tertiary" />
|
||||
)
|
||||
: (<div className={cn('h-6 w-0 grow truncate system-sm-medium leading-6 text-text-secondary', isHighlight && 'text-text-accent')}>{name}</div>)}
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
disabled={depth !== MAX_DEPTH + 1}
|
||||
render={(
|
||||
<div
|
||||
className={cn('flex items-center justify-between rounded-md pr-2', !readonly && 'hover:bg-state-base-hover', depth !== MAX_DEPTH + 1 && 'cursor-pointer')}
|
||||
onMouseDown={() => !readonly && onSelect?.([...valueSelector, name])}
|
||||
>
|
||||
<div className="flex grow items-stretch">
|
||||
<TreeIndentLine depth={depth} />
|
||||
{depth === MAX_DEPTH + 1
|
||||
? (
|
||||
<RiMoreFill className="h-3 w-3 text-text-tertiary" />
|
||||
)
|
||||
: (<div className={cn('h-6 w-0 grow truncate system-sm-medium leading-6 text-text-secondary', isHighlight && 'text-text-accent')}>{name}</div>)}
|
||||
|
||||
</div>
|
||||
{depth < MAX_DEPTH + 1 && (
|
||||
<div className="ml-2 shrink-0 system-xs-regular text-text-tertiary">{getFieldType(payload)}</div>
|
||||
</div>
|
||||
{depth < MAX_DEPTH + 1 && (
|
||||
<div className="ml-2 shrink-0 system-xs-regular text-text-tertiary">{getFieldType(payload)}</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('structOutput.moreFillTip', { ns: 'app' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
{depth <= MAX_DEPTH && payload.type === Type.object && payload.properties && (
|
||||
|
||||
@@ -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<Props> = ({
|
||||
<div className="mb-1 flex items-center justify-between">
|
||||
<div className="flex items-center gap-0.5">
|
||||
<div className="system-sm-semibold-uppercase text-text-secondary">{t(`${i18nPrefix}.deliveryMethod.title`, { ns: 'workflow' })}</div>
|
||||
<Tooltip
|
||||
popupContent={t(`${i18nPrefix}.deliveryMethod.tooltip`, { ns: 'workflow' })}
|
||||
/>
|
||||
<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(`${i18nPrefix}.deliveryMethod.tooltip`, { ns: 'workflow' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
{!readonly && (
|
||||
<div className="flex items-center px-1">
|
||||
|
||||
@@ -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 = ({
|
||||
<div className="truncate system-xs-medium text-text-secondary">
|
||||
{t('form.numberOfKeywords', { ns: 'datasetSettings' })}
|
||||
</div>
|
||||
<Tooltip
|
||||
popupContent="number of keywords"
|
||||
>
|
||||
<RiQuestionLine className="ml-0.5 h-3.5 w-3.5 text-text-quaternary" />
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={<RiQuestionLine className="ml-0.5 h-3.5 w-3.5 text-text-quaternary" />}
|
||||
/>
|
||||
<TooltipContent>
|
||||
number of keywords
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<Slider
|
||||
|
||||
@@ -2,12 +2,12 @@ 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 Textarea from '@/app/components/base/textarea'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal'
|
||||
|
||||
type ModelInfo = {
|
||||
@@ -75,7 +75,18 @@ 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 popupContent={t('nodes.llm.jsonSchema.promptTooltip', { ns: 'workflow' })} />
|
||||
<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>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<Textarea
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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 Tooltip from '@/app/components/base/tooltip'
|
||||
|
||||
type MonthlyDaysSelectorProps = {
|
||||
selectedDays: (number | 'last')[]
|
||||
@@ -57,10 +57,15 @@ const MonthlyDaysSelector = ({ selectedDays, onChange }: MonthlyDaysSelectorProp
|
||||
? (
|
||||
<div className="flex items-center justify-center gap-1">
|
||||
<span>{t('nodes.triggerSchedule.lastDay', { ns: 'workflow' })}</span>
|
||||
<Tooltip
|
||||
popupContent={t('nodes.triggerSchedule.lastDayTooltip', { ns: 'workflow' })}
|
||||
>
|
||||
<RiQuestionLine className="h-3 w-3 text-text-quaternary" />
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<RiQuestionLine className="h-3 w-3 text-text-quaternary" />
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('nodes.triggerSchedule.lastDayTooltip', { ns: 'workflow' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { StartNodeType } from '../../nodes/start/types'
|
||||
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { RiCloseLine, RiEqualizer2Line } from '@remixicon/react'
|
||||
import { debounce } from 'es-toolkit/compat'
|
||||
import { noop } from 'es-toolkit/function'
|
||||
@@ -15,7 +16,6 @@ import { useTranslation } from 'react-i18next'
|
||||
import { useNodes } from 'reactflow'
|
||||
import ActionButton, { ActionButtonState } from '@/app/components/base/action-button'
|
||||
import { RefreshCcw01 } from '@/app/components/base/icons/src/vender/line/arrows'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { useEdgesInteractionsWithoutSync } from '@/app/components/workflow/hooks/use-edges-interactions-without-sync'
|
||||
import { useNodesInteractionsWithoutSync } from '@/app/components/workflow/hooks/use-nodes-interactions-without-sync'
|
||||
import { useStore } from '@/app/components/workflow/store'
|
||||
@@ -99,21 +99,31 @@ const DebugAndPreview = () => {
|
||||
<div className="flex shrink-0 items-center justify-between px-4 pt-3 pb-2 system-xl-semibold text-text-primary">
|
||||
<div className="h-8">{t('common.debugAndPreview', { ns: 'workflow' }).toLocaleUpperCase()}</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<Tooltip
|
||||
popupContent={t('operation.refresh', { ns: 'common' })}
|
||||
>
|
||||
<ActionButton onClick={() => handleRestartChat()}>
|
||||
<RefreshCcw01 className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton onClick={() => handleRestartChat()}>
|
||||
<RefreshCcw01 className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('operation.refresh', { ns: 'common' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
{visibleVariables.length > 0 && (
|
||||
<div className="relative">
|
||||
<Tooltip
|
||||
popupContent={t('panel.userInputField', { ns: 'workflow' })}
|
||||
>
|
||||
<ActionButton state={expanded ? ActionButtonState.Active : undefined} onClick={() => setExpanded(!expanded)}>
|
||||
<RiEqualizer2Line className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton state={expanded ? ActionButtonState.Active : undefined} onClick={() => setExpanded(!expanded)}>
|
||||
<RiEqualizer2Line className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('panel.userInputField', { ns: 'workflow' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
{expanded && <div className="absolute right-[5px] bottom-[-17px] z-10 h-3 w-3 rotate-45 border-t-[0.5px] border-l-[0.5px] border-components-panel-border-subtle bg-components-panel-on-panel-item-bg" />}
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { currentVarType } from './panel'
|
||||
import type { NodeWithVar, VarInInspect } from '@/types/workflow'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import {
|
||||
RiArrowRightSLine,
|
||||
RiDeleteBinLine,
|
||||
@@ -12,7 +13,6 @@ import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
// import { Button } from '@langgenius/dify-ui/button'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import BlockIcon from '@/app/components/workflow/block-icon'
|
||||
import { VariableIconWithColor } from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
|
||||
import { VarInInspectType } from '@/types/workflow'
|
||||
@@ -130,15 +130,29 @@ const Group = ({
|
||||
</div>
|
||||
{nodeData && !nodeData.isSingRunRunning && (
|
||||
<div className="hidden shrink-0 items-center group-hover:flex">
|
||||
<Tooltip popupContent={t('debug.variableInspect.view', { ns: 'workflow' })}>
|
||||
<ActionButton onClick={handleView}>
|
||||
<RiFileList3Line className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton onClick={handleView}>
|
||||
<RiFileList3Line className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('debug.variableInspect.view', { ns: 'workflow' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip popupContent={t('debug.variableInspect.clearNode', { ns: 'workflow' })}>
|
||||
<ActionButton onClick={handleClear}>
|
||||
<RiDeleteBinLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton onClick={handleClear}>
|
||||
<RiDeleteBinLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('debug.variableInspect.clearNode', { ns: 'workflow' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { currentVarType } from './panel'
|
||||
import type { GenRes } from '@/service/debug'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import {
|
||||
RiArrowGoBackLine,
|
||||
RiCloseLine,
|
||||
@@ -17,7 +18,6 @@ import ActionButton from '@/app/components/base/action-button'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
import CopyFeedback from '@/app/components/base/copy-feedback'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import BlockIcon from '@/app/components/workflow/block-icon'
|
||||
import { VariableIconWithColor } from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
@@ -217,25 +217,39 @@ const Right = ({
|
||||
{currentNodeVar && (
|
||||
<>
|
||||
{canShowPromptGenerator && (
|
||||
<Tooltip popupContent={t('generate.optimizePromptTooltip', { ns: 'appDebug' })}>
|
||||
<div
|
||||
className="cursor-pointer rounded-md p-1 hover:bg-state-accent-active"
|
||||
onClick={handleShowPromptGenerator}
|
||||
>
|
||||
<RiSparklingFill className="size-4 text-components-input-border-active-prompt-1" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div
|
||||
className="cursor-pointer rounded-md p-1 hover:bg-state-accent-active"
|
||||
onClick={handleShowPromptGenerator}
|
||||
>
|
||||
<RiSparklingFill className="size-4 text-components-input-border-active-prompt-1" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('generate.optimizePromptTooltip', { ns: 'appDebug' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{isTruncated && (
|
||||
<Tooltip popupContent={t('debug.variableInspect.exportToolTip', { ns: 'workflow' })}>
|
||||
<ActionButton>
|
||||
<a
|
||||
href={fullContent?.download_url}
|
||||
target="_blank"
|
||||
>
|
||||
<RiFileDownloadFill className="size-4" />
|
||||
</a>
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton>
|
||||
<a
|
||||
href={fullContent?.download_url}
|
||||
target="_blank"
|
||||
>
|
||||
<RiFileDownloadFill className="size-4" />
|
||||
</a>
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('debug.variableInspect.exportToolTip', { ns: 'workflow' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{!isTruncated && currentNodeVar.var.edited && (
|
||||
@@ -245,17 +259,31 @@ const Right = ({
|
||||
</Badge>
|
||||
)}
|
||||
{!isTruncated && currentNodeVar.var.edited && currentNodeVar.var.type !== VarInInspectType.conversation && (
|
||||
<Tooltip popupContent={t('debug.variableInspect.reset', { ns: 'workflow' })}>
|
||||
<ActionButton onClick={resetValue}>
|
||||
<RiArrowGoBackLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton onClick={resetValue}>
|
||||
<RiArrowGoBackLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('debug.variableInspect.reset', { ns: 'workflow' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{!isTruncated && currentNodeVar.var.edited && currentNodeVar.var.type === VarInInspectType.conversation && (
|
||||
<Tooltip popupContent={t('debug.variableInspect.resetConversationVar', { ns: 'workflow' })}>
|
||||
<ActionButton onClick={handleClear}>
|
||||
<RiArrowGoBackLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<ActionButton onClick={handleClear}>
|
||||
<RiArrowGoBackLine className="h-4 w-4" />
|
||||
</ActionButton>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('debug.variableInspect.resetConversationVar', { ns: 'workflow' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
{currentNodeVar.var.value_type !== 'secret' && (
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { FC } from 'react'
|
||||
import type { CommonNodeType } from '@/app/components/workflow/types'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
|
||||
import { RiLoader2Line, RiStopCircleFill } from '@remixicon/react'
|
||||
import { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNodes } from 'reactflow'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { NodeRunningStatus, WorkflowRunningStatus } from '@/app/components/workflow/types'
|
||||
import { EVENT_WORKFLOW_STOP } from '@/app/components/workflow/variable-inspect/types'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
@@ -108,15 +108,20 @@ const VariableInspectTrigger: FC = () => {
|
||||
<span className="text-text-accent">{t('debug.variableInspect.trigger.running', { ns: 'workflow' })}</span>
|
||||
</div>
|
||||
{isPreviewRunning && (
|
||||
<Tooltip
|
||||
popupContent={t('debug.variableInspect.trigger.stop', { ns: 'workflow' })}
|
||||
>
|
||||
<div
|
||||
className="flex h-6 cursor-pointer items-center rounded-md border-[0.5px] border-effects-highlight bg-components-actionbar-bg px-1 shadow-lg backdrop-blur-xs hover:bg-components-actionbar-bg-accent"
|
||||
onClick={handleStop}
|
||||
>
|
||||
<RiStopCircleFill className="h-4 w-4 text-text-accent" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={(
|
||||
<div
|
||||
className="flex h-6 cursor-pointer items-center rounded-md border-[0.5px] border-effects-highlight bg-components-actionbar-bg px-1 shadow-lg backdrop-blur-xs hover:bg-components-actionbar-bg-accent"
|
||||
onClick={handleStop}
|
||||
>
|
||||
<RiStopCircleFill className="h-4 w-4 text-text-accent" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<TooltipContent>
|
||||
{t('debug.variableInspect.trigger.stop', { ns: 'workflow' })}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user