| import ProviderConfigModal from './provider-config-modal' | import ProviderConfigModal from './provider-config-modal' | ||||
| import Indicator from '@/app/components/header/indicator' | import Indicator from '@/app/components/header/indicator' | ||||
| import Switch from '@/app/components/base/switch' | import Switch from '@/app/components/base/switch' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| const I18N_PREFIX = 'app.tracing' | const I18N_PREFIX = 'app.tracing' | ||||
| <> | <> | ||||
| {providerAllNotConfigured | {providerAllNotConfigured | ||||
| ? ( | ? ( | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={t(`${I18N_PREFIX}.disabledTip`)} | popupContent={t(`${I18N_PREFIX}.disabledTip`)} | ||||
| > | > | ||||
| {switchContent} | {switchContent} | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| ) | ) | ||||
| : switchContent} | : switchContent} | ||||
| </> | </> |
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import React, { useCallback } from 'react' | import React, { useCallback } from 'react' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| const I18N_PREFIX = 'app.tracing' | const I18N_PREFIX = 'app.tracing' | ||||
| return ( | return ( | ||||
| // text-[0px] to hide spacing between tooltip elements | // text-[0px] to hide spacing between tooltip elements | ||||
| <div className='shrink-0 cursor-pointer text-[0px]' onClick={handleFoldChange}> | <div className='shrink-0 cursor-pointer text-[0px]' onClick={handleFoldChange}> | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={t(`${I18N_PREFIX}.${isFold ? 'expand' : 'collapse'}`)} | popupContent={t(`${I18N_PREFIX}.${isFold ? 'expand' : 'collapse'}`)} | ||||
| hideArrow | |||||
| > | > | ||||
| {isFold && ( | {isFold && ( | ||||
| <div className='p-1 rounded-md text-gray-500 hover:text-gray-800 hover:bg-black/5'> | <div className='p-1 rounded-md text-gray-500 hover:text-gray-800 hover:bg-black/5'> | ||||
| <ChevronDoubleDownIcon className='w-4 h-4 transform rotate-180' /> | <ChevronDoubleDownIcon className='w-4 h-4 transform rotate-180' /> | ||||
| </div> | </div> | ||||
| )} | )} | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| </div> | </div> | ||||
| ) | ) | ||||
| } | } |
| import { useRouter } from 'next/navigation' | import { useRouter } from 'next/navigation' | ||||
| import { useCallback, useEffect, useState } from 'react' | import { useCallback, useEffect, useState } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { | |||||
| RiMoreFill, | |||||
| } from '@remixicon/react' | |||||
| import { RiMoreFill } from '@remixicon/react' | |||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import Confirm from '@/app/components/base/confirm' | import Confirm from '@/app/components/base/confirm' | ||||
| import { ToastContext } from '@/app/components/base/toast' | import { ToastContext } from '@/app/components/base/toast' | ||||
| <div className={cn('truncate', !dataset.embedding_available && 'opacity-50 hover:opacity-100')} title={dataset.name}>{dataset.name}</div> | <div className={cn('truncate', !dataset.embedding_available && 'opacity-50 hover:opacity-100')} title={dataset.name}>{dataset.name}</div> | ||||
| {!dataset.embedding_available && ( | {!dataset.embedding_available && ( | ||||
| <Tooltip | <Tooltip | ||||
| selector={`dataset-tag-${dataset.id}`} | |||||
| htmlContent={t('dataset.unavailableTip')} | |||||
| popupContent={t('dataset.unavailableTip')} | |||||
| > | > | ||||
| <span className='shrink-0 inline-flex w-max ml-1 px-1 border boder-gray-200 rounded-md text-gray-500 text-xs font-normal leading-[18px]'>{t('dataset.unavailable')}</span> | |||||
| <span className='shrink-0 inline-flex w-max ml-1 px-1 border border-gray-200 rounded-md text-gray-500 text-xs font-normal leading-[18px]'>{t('dataset.unavailable')}</span> | |||||
| </Tooltip> | </Tooltip> | ||||
| )} | )} | ||||
| </div> | </div> |
| import React from 'react' | import React from 'react' | ||||
| import { | |||||
| InformationCircleIcon, | |||||
| } from '@heroicons/react/24/outline' | |||||
| import Tooltip from '../base/tooltip' | |||||
| import AppIcon from '../base/app-icon' | import AppIcon from '../base/app-icon' | ||||
| import { randomString } from '@/utils' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| export type IAppBasicProps = { | export type IAppBasicProps = { | ||||
| iconType?: 'app' | 'api' | 'dataset' | 'webapp' | 'notion' | iconType?: 'app' | 'api' | 'dataset' | 'webapp' | 'notion' | ||||
| <div className={`flex flex-row items-center text-sm font-semibold text-gray-700 group-hover:text-gray-900 break-all ${textStyle?.main ?? ''}`}> | <div className={`flex flex-row items-center text-sm font-semibold text-gray-700 group-hover:text-gray-900 break-all ${textStyle?.main ?? ''}`}> | ||||
| {name} | {name} | ||||
| {hoverTip | {hoverTip | ||||
| && <Tooltip content={hoverTip} selector={`a${randomString(16)}`}> | |||||
| <InformationCircleIcon className='w-4 h-4 ml-1 text-gray-400' /> | |||||
| </Tooltip>} | |||||
| && <Tooltip | |||||
| popupContent={ | |||||
| <div className='w-[240px]'> | |||||
| {hoverTip} | |||||
| </div> | |||||
| } | |||||
| popupClassName='ml-1' | |||||
| triggerClassName='w-4 h-4 ml-1' | |||||
| position='top' | |||||
| /> | |||||
| } | |||||
| </div> | </div> | ||||
| <div className={`text-xs font-normal text-gray-500 group-hover:text-gray-700 break-all ${textStyle?.extra ?? ''}`}>{type}</div> | <div className={`text-xs font-normal text-gray-500 group-hover:text-gray-700 break-all ${textStyle?.extra ?? ''}`}>{type}</div> | ||||
| </div>} | </div>} |
| import { | import { | ||||
| RiDeleteBinLine, | RiDeleteBinLine, | ||||
| RiErrorWarningFill, | RiErrorWarningFill, | ||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | } from '@remixicon/react' | ||||
| import s from './style.module.css' | import s from './style.module.css' | ||||
| import MessageTypeSelector from './message-type-selector' | import MessageTypeSelector from './message-type-selector' | ||||
| <div className='text-sm font-semibold uppercase text-indigo-800'>{t('appDebug.pageTitle.line1')} | <div className='text-sm font-semibold uppercase text-indigo-800'>{t('appDebug.pageTitle.line1')} | ||||
| </div> | </div> | ||||
| <Tooltip | <Tooltip | ||||
| htmlContent={<div className='w-[180px]'> | |||||
| {t('appDebug.promptTip')} | |||||
| </div>} | |||||
| selector='config-prompt-tooltip'> | |||||
| <RiQuestionLine className='w-[14px] h-[14px] text-indigo-400' /> | |||||
| </Tooltip> | |||||
| popupContent={ | |||||
| <div className='w-[180px]'> | |||||
| {t('appDebug.promptTip')} | |||||
| </div> | |||||
| } | |||||
| /> | |||||
| </div>)} | </div>)} | ||||
| <div className={cn(s.optionWrap, 'items-center space-x-1')}> | <div className={cn(s.optionWrap, 'items-center space-x-1')}> | ||||
| {canDelete && ( | {canDelete && ( |
| import React, { useState } from 'react' | import React, { useState } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { useBoolean } from 'ahooks' | import { useBoolean } from 'ahooks' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import produce from 'immer' | import produce from 'immer' | ||||
| import { useContext } from 'use-context-selector' | import { useContext } from 'use-context-selector' | ||||
| import ConfirmAddVar from './confirm-add-var' | import ConfirmAddVar from './confirm-add-var' | ||||
| <div className='h2'>{mode !== AppType.completion ? t('appDebug.chatSubTitle') : t('appDebug.completionSubTitle')}</div> | <div className='h2'>{mode !== AppType.completion ? t('appDebug.chatSubTitle') : t('appDebug.completionSubTitle')}</div> | ||||
| {!readonly && ( | {!readonly && ( | ||||
| <Tooltip | <Tooltip | ||||
| htmlContent={<div className='w-[180px]'> | |||||
| {t('appDebug.promptTip')} | |||||
| </div>} | |||||
| selector='config-prompt-tooltip'> | |||||
| <RiQuestionLine className='w-[14px] h-[14px] text-indigo-400' /> | |||||
| </Tooltip> | |||||
| popupContent={ | |||||
| <div className='w-[180px]'> | |||||
| {t('appDebug.promptTip')} | |||||
| </div> | |||||
| } | |||||
| /> | |||||
| )} | )} | ||||
| </div> | </div> | ||||
| <div className='flex items-center'> | <div className='flex items-center'> |
| import produce from 'immer' | import produce from 'immer' | ||||
| import { | import { | ||||
| RiDeleteBinLine, | RiDeleteBinLine, | ||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | } from '@remixicon/react' | ||||
| import Panel from '../base/feature-panel' | import Panel from '../base/feature-panel' | ||||
| import EditModal from './config-modal' | import EditModal from './config-modal' | ||||
| <div className='flex items-center'> | <div className='flex items-center'> | ||||
| <div className='mr-1'>{t('appDebug.variableTitle')}</div> | <div className='mr-1'>{t('appDebug.variableTitle')}</div> | ||||
| {!readonly && ( | {!readonly && ( | ||||
| <Tooltip htmlContent={<div className='w-[180px]'> | |||||
| {t('appDebug.variableTip')} | |||||
| </div>} selector='config-var-tooltip'> | |||||
| <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' /> | |||||
| </Tooltip> | |||||
| <Tooltip | |||||
| popupContent={ | |||||
| <div className='w-[180px]'> | |||||
| {t('appDebug.variableTip')} | |||||
| </div> | |||||
| } | |||||
| /> | |||||
| )} | )} | ||||
| </div> | </div> | ||||
| } | } |
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import React from 'react' | import React from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import { useContext } from 'use-context-selector' | import { useContext } from 'use-context-selector' | ||||
| import Panel from '../base/feature-panel' | import Panel from '../base/feature-panel' | ||||
| import ParamConfig from './param-config' | import ParamConfig from './param-config' | ||||
| title={ | title={ | ||||
| <div className='flex items-center'> | <div className='flex items-center'> | ||||
| <div className='mr-1'>{t('appDebug.vision.name')}</div> | <div className='mr-1'>{t('appDebug.vision.name')}</div> | ||||
| <Tooltip htmlContent={<div className='w-[180px]' > | |||||
| {t('appDebug.vision.description')} | |||||
| </div>} selector='config-vision-tooltip'> | |||||
| <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' /> | |||||
| </Tooltip> | |||||
| <Tooltip | |||||
| popupContent={ | |||||
| <div className='w-[180px]' > | |||||
| {t('appDebug.vision.description')} | |||||
| </div> | |||||
| } | |||||
| /> | |||||
| </div> | </div> | ||||
| } | } | ||||
| headerRight={ | headerRight={ |
| import React from 'react' | import React from 'react' | ||||
| import { useContext } from 'use-context-selector' | import { useContext } from 'use-context-selector' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import RadioGroup from './radio-group' | import RadioGroup from './radio-group' | ||||
| import ConfigContext from '@/context/debug-configuration' | import ConfigContext from '@/context/debug-configuration' | ||||
| import { Resolution, TransferMethod } from '@/types/app' | import { Resolution, TransferMethod } from '@/types/app' | ||||
| <div> | <div> | ||||
| <div className='mb-2 flex items-center space-x-1'> | <div className='mb-2 flex items-center space-x-1'> | ||||
| <div className='leading-[18px] text-[13px] font-semibold text-gray-800'>{t('appDebug.vision.visionSettings.resolution')}</div> | <div className='leading-[18px] text-[13px] font-semibold text-gray-800'>{t('appDebug.vision.visionSettings.resolution')}</div> | ||||
| <Tooltip htmlContent={<div className='w-[180px]' > | |||||
| {t('appDebug.vision.visionSettings.resolutionTooltip').split('\n').map(item => ( | |||||
| <div key={item}>{item}</div> | |||||
| ))} | |||||
| </div>} selector='config-resolution-tooltip'> | |||||
| <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' /> | |||||
| </Tooltip> | |||||
| <Tooltip | |||||
| popupContent={ | |||||
| <div className='w-[180px]' > | |||||
| {t('appDebug.vision.visionSettings.resolutionTooltip').split('\n').map(item => ( | |||||
| <div key={item}>{item}</div> | |||||
| ))} | |||||
| </div> | |||||
| } | |||||
| /> | |||||
| </div> | </div> | ||||
| <RadioGroup | <RadioGroup | ||||
| className='space-x-3' | className='space-x-3' |
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import { useContext } from 'use-context-selector' | import { useContext } from 'use-context-selector' | ||||
| import React, { Fragment } from 'react' | import React, { Fragment } from 'react' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import { usePathname } from 'next/navigation' | import { usePathname } from 'next/navigation' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { Listbox, Transition } from '@headlessui/react' | import { Listbox, Transition } from '@headlessui/react' | ||||
| <div className='mb-2 flex items-center space-x-1'> | <div className='mb-2 flex items-center space-x-1'> | ||||
| <div | <div | ||||
| className='leading-[18px] text-[13px] font-semibold text-gray-800'>{t('appDebug.voice.voiceSettings.language')}</div> | className='leading-[18px] text-[13px] font-semibold text-gray-800'>{t('appDebug.voice.voiceSettings.language')}</div> | ||||
| <Tooltip htmlContent={<div className='w-[180px]'> | |||||
| {t('appDebug.voice.voiceSettings.resolutionTooltip').split('\n').map(item => ( | |||||
| <div key={item}>{item}</div> | |||||
| ))} | |||||
| </div>} selector='config-resolution-tooltip'> | |||||
| <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' /> | |||||
| </Tooltip> | |||||
| <Tooltip | |||||
| popupContent={ | |||||
| <div className='w-[180px]'> | |||||
| {t('appDebug.voice.voiceSettings.resolutionTooltip').split('\n').map(item => ( | |||||
| <div key={item}>{item}</div> | |||||
| ))} | |||||
| </div> | |||||
| } | |||||
| /> | |||||
| </div> | </div> | ||||
| <Listbox | <Listbox | ||||
| value={languageItem} | value={languageItem} |
| 'use client' | 'use client' | ||||
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import React from 'react' | import React from 'react' | ||||
| import { RiQuestionLine } from '@remixicon/react' | |||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import Tooltip from '@/app/components/base/tooltip' | import Tooltip from '@/app/components/base/tooltip' | ||||
| type Props = { | type Props = { | ||||
| {icon} | {icon} | ||||
| <div className='ml-3 mr-1 leading-6 text-sm font-semibold text-gray-800'>{name}</div> | <div className='ml-3 mr-1 leading-6 text-sm font-semibold text-gray-800'>{name}</div> | ||||
| <Tooltip | <Tooltip | ||||
| htmlContent={ | |||||
| popupContent={ | |||||
| <div className='w-[180px]'> | <div className='w-[180px]'> | ||||
| {description} | {description} | ||||
| </div> | </div> | ||||
| } | } | ||||
| selector={`agent-setting-tooltip-${name}`} | |||||
| > | > | ||||
| <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' /> | |||||
| </Tooltip> | </Tooltip> | ||||
| </div> | </div> | ||||
| <div> | <div> |
| import { | import { | ||||
| RiDeleteBinLine, | RiDeleteBinLine, | ||||
| RiHammerFill, | RiHammerFill, | ||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | } from '@remixicon/react' | ||||
| import { useFormattingChangedDispatcher } from '../../../debug/hooks' | import { useFormattingChangedDispatcher } from '../../../debug/hooks' | ||||
| import SettingBuiltInTool from './setting-built-in-tool' | import SettingBuiltInTool from './setting-built-in-tool' | ||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import Panel from '@/app/components/app/configuration/base/feature-panel' | import Panel from '@/app/components/app/configuration/base/feature-panel' | ||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import { InfoCircle } from '@/app/components/base/icons/src/vender/line/general' | import { InfoCircle } from '@/app/components/base/icons/src/vender/line/general' | ||||
| import OperationBtn from '@/app/components/app/configuration/base/operation-btn' | import OperationBtn from '@/app/components/app/configuration/base/operation-btn' | ||||
| import AppIcon from '@/app/components/base/app-icon' | import AppIcon from '@/app/components/base/app-icon' | ||||
| import { type Collection, CollectionType } from '@/app/components/tools/types' | import { type Collection, CollectionType } from '@/app/components/tools/types' | ||||
| import { MAX_TOOLS_NUM } from '@/config' | import { MAX_TOOLS_NUM } from '@/config' | ||||
| import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback' | import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import { DefaultToolIcon } from '@/app/components/base/icons/src/public/other' | import { DefaultToolIcon } from '@/app/components/base/icons/src/public/other' | ||||
| import AddToolModal from '@/app/components/tools/add-tool-modal' | import AddToolModal from '@/app/components/tools/add-tool-modal' | ||||
| title={ | title={ | ||||
| <div className='flex items-center'> | <div className='flex items-center'> | ||||
| <div className='mr-1'>{t('appDebug.agent.tools.name')}</div> | <div className='mr-1'>{t('appDebug.agent.tools.name')}</div> | ||||
| <Tooltip htmlContent={<div className='w-[180px]'> | |||||
| {t('appDebug.agent.tools.description')} | |||||
| </div>} selector='config-tools-tooltip'> | |||||
| <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' /> | |||||
| </Tooltip> | |||||
| <Tooltip | |||||
| popupContent={ | |||||
| <div className='w-[180px]'> | |||||
| {t('appDebug.agent.tools.description')} | |||||
| </div> | |||||
| } | |||||
| /> | |||||
| </div> | </div> | ||||
| } | } | ||||
| headerRight={ | headerRight={ | ||||
| className={cn((item.isDeleted || item.notAuthor) ? 'line-through opacity-50' : '', 'grow w-0 ml-2 leading-[18px] text-[13px] font-medium text-gray-800 truncate')} | className={cn((item.isDeleted || item.notAuthor) ? 'line-through opacity-50' : '', 'grow w-0 ml-2 leading-[18px] text-[13px] font-medium text-gray-800 truncate')} | ||||
| > | > | ||||
| <span className='text-gray-800 pr-2'>{item.provider_type === CollectionType.builtIn ? item.provider_name : item.tool_label}</span> | <span className='text-gray-800 pr-2'>{item.provider_type === CollectionType.builtIn ? item.provider_name : item.tool_label}</span> | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={t('tools.toolNameUsageTip')} | popupContent={t('tools.toolNameUsageTip')} | ||||
| > | > | ||||
| <span className='text-gray-500'>{item.tool_name}</span> | <span className='text-gray-500'>{item.tool_name}</span> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div className='shrink-0 ml-1 flex items-center'> | <div className='shrink-0 ml-1 flex items-center'> | ||||
| {(item.isDeleted || item.notAuthor) | {(item.isDeleted || item.notAuthor) | ||||
| ? ( | ? ( | ||||
| <div className='flex items-center'> | <div className='flex items-center'> | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={t(`tools.${item.isDeleted ? 'toolRemoved' : 'notAuthorized'}`)} | popupContent={t(`tools.${item.isDeleted ? 'toolRemoved' : 'notAuthorized'}`)} | ||||
| needsDelay | |||||
| > | > | ||||
| <div className='mr-1 p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => { | <div className='mr-1 p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => { | ||||
| if (item.notAuthor) | if (item.notAuthor) | ||||
| }}> | }}> | ||||
| <AlertTriangle className='w-4 h-4 text-[#F79009]' /> | <AlertTriangle className='w-4 h-4 text-[#F79009]' /> | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| <div className='p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => { | <div className='p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => { | ||||
| const newModelConfig = produce(modelConfig, (draft) => { | const newModelConfig = produce(modelConfig, (draft) => { | ||||
| ) | ) | ||||
| : ( | : ( | ||||
| <div className='hidden group-hover:flex items-center'> | <div className='hidden group-hover:flex items-center'> | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={t('tools.setBuiltInTools.infoAndSetting')} | popupContent={t('tools.setBuiltInTools.infoAndSetting')} | ||||
| needsDelay | |||||
| > | > | ||||
| <div className='mr-1 p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => { | |||||
| <div className='p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => { | |||||
| setCurrentTool(item) | setCurrentTool(item) | ||||
| setIsShowSettingTool(true) | setIsShowSettingTool(true) | ||||
| }}> | }}> | ||||
| <InfoCircle className='w-4 h-4 text-gray-500' /> | <InfoCircle className='w-4 h-4 text-gray-500' /> | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| <div className='p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => { | <div className='p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => { | ||||
| const newModelConfig = produce(modelConfig, (draft) => { | const newModelConfig = produce(modelConfig, (draft) => { |
| <div className={cn('text-[13px] leading-[18px] font-medium text-gray-800 overflow-hidden text-ellipsis whitespace-nowrap', !config.embedding_available && 'opacity-50')}>{config.name}</div> | <div className={cn('text-[13px] leading-[18px] font-medium text-gray-800 overflow-hidden text-ellipsis whitespace-nowrap', !config.embedding_available && 'opacity-50')}>{config.name}</div> | ||||
| {!config.embedding_available && ( | {!config.embedding_available && ( | ||||
| <Tooltip | <Tooltip | ||||
| selector={`unavailable-tag-${config.id}`} | |||||
| htmlContent={t('dataset.unavailableTip')} | |||||
| popupContent={t('dataset.unavailableTip')} | |||||
| > | > | ||||
| <span className='shrink-0 inline-flex whitespace-nowrap px-1 border boder-gray-200 rounded-md text-gray-500 text-xs font-normal leading-[18px]'>{t('dataset.unavailable')}</span> | |||||
| <span className='shrink-0 inline-flex whitespace-nowrap px-1 border border-gray-200 rounded-md text-gray-500 text-xs font-normal leading-[18px]'>{t('dataset.unavailable')}</span> | |||||
| </Tooltip> | </Tooltip> | ||||
| )} | )} | ||||
| </div> | </div> |
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import React from 'react' | import React from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import type { Props } from './var-picker' | import type { Props } from './var-picker' | ||||
| import VarPicker from './var-picker' | import VarPicker from './var-picker' | ||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| </div> | </div> | ||||
| <div className='mr-1 text-sm font-medium text-gray-800'>{t('appDebug.feature.dataSet.queryVariable.title')}</div> | <div className='mr-1 text-sm font-medium text-gray-800'>{t('appDebug.feature.dataSet.queryVariable.title')}</div> | ||||
| <Tooltip | <Tooltip | ||||
| htmlContent={<div className='w-[180px]'> | |||||
| {t('appDebug.feature.dataSet.queryVariable.tip')} | |||||
| </div>} | |||||
| selector='context-var-tooltip' | |||||
| > | |||||
| <RiQuestionLine className='w-3.5 h-3.5 text-gray-400' /> | |||||
| </Tooltip> | |||||
| popupContent={ | |||||
| <div className='w-[180px]'> | |||||
| {t('appDebug.feature.dataSet.queryVariable.tip')} | |||||
| </div> | |||||
| } | |||||
| /> | |||||
| </div> | </div> | ||||
| <VarPicker {...props} /> | <VarPicker {...props} /> |
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { | import { | ||||
| RiAlertFill, | RiAlertFill, | ||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | } from '@remixicon/react' | ||||
| import WeightedScore from './weighted-score' | import WeightedScore from './weighted-score' | ||||
| import TopKItem from '@/app/components/base/param-item/top-k-item' | import TopKItem from '@/app/components/base/param-item/top-k-item' | ||||
| import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks' | import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks' | ||||
| import type { ModelConfig } from '@/app/components/workflow/types' | import type { ModelConfig } from '@/app/components/workflow/types' | ||||
| import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal' | import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' | import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' | ||||
| import type { | import type { | ||||
| DataSet, | DataSet, | ||||
| title={( | title={( | ||||
| <div className='flex items-center'> | <div className='flex items-center'> | ||||
| {t('appDebug.datasetConfig.retrieveOneWay.title')} | {t('appDebug.datasetConfig.retrieveOneWay.title')} | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={( | popupContent={( | ||||
| <div className='w-[320px]'> | <div className='w-[320px]'> | ||||
| {t('dataset.nTo1RetrievalLegacy')} | {t('dataset.nTo1RetrievalLegacy')} | ||||
| )} | )} | ||||
| > | > | ||||
| <div className='ml-1 flex items-center px-[5px] h-[18px] rounded-[5px] border border-text-accent-secondary system-2xs-medium-uppercase text-text-accent-secondary'>legacy</div> | <div className='ml-1 flex items-center px-[5px] h-[18px] rounded-[5px] border border-text-accent-secondary system-2xs-medium-uppercase text-text-accent-secondary'>legacy</div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| </div> | </div> | ||||
| )} | )} | ||||
| description={t('appDebug.datasetConfig.retrieveOneWay.description')} | description={t('appDebug.datasetConfig.retrieveOneWay.description')} | ||||
| onClick={() => handleRerankModeChange(option.value)} | onClick={() => handleRerankModeChange(option.value)} | ||||
| > | > | ||||
| <div className='truncate'>{option.label}</div> | <div className='truncate'>{option.label}</div> | ||||
| <TooltipPlus | |||||
| popupContent={<div className='w-[200px]'>{option.tips}</div>} | |||||
| hideArrow | |||||
| > | |||||
| <RiQuestionLine className='ml-0.5 w-3.5 h-4.5 text-text-quaternary' /> | |||||
| </TooltipPlus> | |||||
| <Tooltip | |||||
| popupContent={ | |||||
| <div className='w-[200px]'> | |||||
| {option.tips} | |||||
| </div> | |||||
| } | |||||
| popupClassName='ml-0.5' | |||||
| triggerClassName='ml-0.5 w-3.5 h-3.5' | |||||
| /> | |||||
| </div> | </div> | ||||
| )) | )) | ||||
| } | } | ||||
| ) | ) | ||||
| } | } | ||||
| <div className='ml-2 leading-[32px] text-[13px] font-medium text-gray-900'>{t('common.modelProvider.rerankModel.key')}</div> | <div className='ml-2 leading-[32px] text-[13px] font-medium text-gray-900'>{t('common.modelProvider.rerankModel.key')}</div> | ||||
| <TooltipPlus popupContent={<div className="w-[200px]">{t('common.modelProvider.rerankModel.tip')}</div>}> | |||||
| <RiQuestionLine className='ml-0.5 w-[14px] h-[14px] text-gray-400' /> | |||||
| </TooltipPlus> | |||||
| <Tooltip | |||||
| popupContent={ | |||||
| <div className="w-[200px]"> | |||||
| {t('common.modelProvider.rerankModel.tip')} | |||||
| </div> | |||||
| } | |||||
| popupClassName='ml-0.5' | |||||
| triggerClassName='ml-0.5 w-3.5 h-3.5' | |||||
| /> | |||||
| </div> | </div> | ||||
| <div> | <div> | ||||
| <ModelSelector | <ModelSelector | ||||
| <div className='mt-4'> | <div className='mt-4'> | ||||
| <div className='flex items-center space-x-0.5'> | <div className='flex items-center space-x-0.5'> | ||||
| <div className='leading-[32px] text-[13px] font-medium text-gray-900'>{t('common.modelProvider.systemReasoningModel.key')}</div> | <div className='leading-[32px] text-[13px] font-medium text-gray-900'>{t('common.modelProvider.systemReasoningModel.key')}</div> | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={t('common.modelProvider.systemReasoningModel.tip')} | popupContent={t('common.modelProvider.systemReasoningModel.tip')} | ||||
| > | |||||
| <RiQuestionLine className='w-3.5 h-4.5 text-gray-400' /> | |||||
| </TooltipPlus> | |||||
| /> | |||||
| </div> | </div> | ||||
| <ModelParameterModal | <ModelParameterModal | ||||
| isInWorkflow={isInWorkflow} | isInWorkflow={isInWorkflow} |
| } from '@/app/components/header/account-setting/model-provider-page/declarations' | } from '@/app/components/header/account-setting/model-provider-page/declarations' | ||||
| import { useDebugConfigurationContext } from '@/context/debug-configuration' | import { useDebugConfigurationContext } from '@/context/debug-configuration' | ||||
| import { CubeOutline } from '@/app/components/base/icons/src/vender/line/shapes' | import { CubeOutline } from '@/app/components/base/icons/src/vender/line/shapes' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback' | import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback' | ||||
| import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks' | import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks' | ||||
| <RiArrowDownSLine className={`w-3 h-3 ${(currentModel && currentProvider) ? 'text-gray-800' : 'text-primary-600'}`} /> | <RiArrowDownSLine className={`w-3 h-3 ${(currentModel && currentProvider) ? 'text-gray-800' : 'text-primary-600'}`} /> | ||||
| { | { | ||||
| currentModel && currentModel.status !== ModelStatusEnum.active && ( | currentModel && currentModel.status !== ModelStatusEnum.active && ( | ||||
| <TooltipPlus popupContent={MODEL_STATUS_TEXT[currentModel.status][language]}> | |||||
| <Tooltip popupContent={MODEL_STATUS_TEXT[currentModel.status][language]}> | |||||
| <AlertTriangle className='w-4 h-4 text-[#F79009]' /> | <AlertTriangle className='w-4 h-4 text-[#F79009]' /> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| ) | ) | ||||
| } | } | ||||
| </div> | </div> |
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import React from 'react' | import React from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import Panel from '@/app/components/app/configuration/base/feature-panel' | import Panel from '@/app/components/app/configuration/base/feature-panel' | ||||
| import SuggestedQuestionsAfterAnswerIcon from '@/app/components/app/configuration/base/icons/suggested-questions-after-answer-icon' | import SuggestedQuestionsAfterAnswerIcon from '@/app/components/app/configuration/base/icons/suggested-questions-after-answer-icon' | ||||
| import Tooltip from '@/app/components/base/tooltip' | import Tooltip from '@/app/components/base/tooltip' | ||||
| return ( | return ( | ||||
| <Panel | <Panel | ||||
| title={ | title={ | ||||
| <div className='flex items-center gap-2'> | |||||
| <div className='flex items-center gap-1'> | |||||
| <div>{t('appDebug.feature.suggestedQuestionsAfterAnswer.title')}</div> | <div>{t('appDebug.feature.suggestedQuestionsAfterAnswer.title')}</div> | ||||
| <Tooltip htmlContent={<div className='w-[180px]'> | |||||
| {t('appDebug.feature.suggestedQuestionsAfterAnswer.description')} | |||||
| </div>} selector='suggestion-question-tooltip'> | |||||
| <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' /> | |||||
| </Tooltip> | |||||
| <Tooltip | |||||
| popupContent={ | |||||
| <div className='w-[180px]'> | |||||
| {t('appDebug.feature.suggestedQuestionsAfterAnswer.description')} | |||||
| </div> | |||||
| } | |||||
| /> | |||||
| </div> | </div> | ||||
| } | } | ||||
| headerIcon={<SuggestedQuestionsAfterAnswerIcon />} | headerIcon={<SuggestedQuestionsAfterAnswerIcon />} |
| import Select from '@/app/components/base/select' | import Select from '@/app/components/base/select' | ||||
| import { DEFAULT_VALUE_MAX_LEN } from '@/config' | import { DEFAULT_VALUE_MAX_LEN } from '@/config' | ||||
| import Button from '@/app/components/base/button' | import Button from '@/app/components/base/button' | ||||
| import Tooltip from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import TextGenerationImageUploader from '@/app/components/base/image-uploader/text-generation-image-uploader' | import TextGenerationImageUploader from '@/app/components/base/image-uploader/text-generation-image-uploader' | ||||
| import type { VisionFile, VisionSettings } from '@/types/app' | import type { VisionFile, VisionSettings } from '@/types/app' | ||||
| {canNotRun | {canNotRun | ||||
| ? (<Tooltip | ? (<Tooltip | ||||
| popupContent={t('appDebug.otherError.promptNoBeEmpty')} | popupContent={t('appDebug.otherError.promptNoBeEmpty')} | ||||
| needsDelay | |||||
| > | > | ||||
| {renderRunButton()} | {renderRunButton()} | ||||
| </Tooltip>) | </Tooltip>) |
| import { MessageFast } from '@/app/components/base/icons/src/vender/solid/communication' | import { MessageFast } from '@/app/components/base/icons/src/vender/solid/communication' | ||||
| import { Edit04 } from '@/app/components/base/icons/src/vender/line/general' | import { Edit04 } from '@/app/components/base/icons/src/vender/line/general' | ||||
| import RemoveAnnotationConfirmModal from '@/app/components/app/annotation/remove-annotation-confirm-modal' | import RemoveAnnotationConfirmModal from '@/app/components/app/annotation/remove-annotation-confirm-modal' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import { addAnnotation, delAnnotation } from '@/service/annotation' | import { addAnnotation, delAnnotation } from '@/service/annotation' | ||||
| import Toast from '@/app/components/base/toast' | import Toast from '@/app/components/base/toast' | ||||
| import { useProviderContext } from '@/context/provider-context' | import { useProviderContext } from '@/context/provider-context' | ||||
| ) | ) | ||||
| : answer | : answer | ||||
| ? ( | ? ( | ||||
| <TooltipPlus | |||||
| popupContent={t('appDebug.feature.annotation.add') as string} | |||||
| <Tooltip | |||||
| popupContent={t('appDebug.feature.annotation.add')} | |||||
| needsDelay | |||||
| > | > | ||||
| <div | <div | ||||
| className='p-1 rounded-md hover:bg-[#EEF4FF] hover:text-[#444CE7] cursor-pointer' | className='p-1 rounded-md hover:bg-[#EEF4FF] hover:text-[#444CE7] cursor-pointer' | ||||
| > | > | ||||
| <MessageFastPlus className='w-4 h-4' /> | <MessageFastPlus className='w-4 h-4' /> | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| ) | ) | ||||
| : null | : null | ||||
| } | } | ||||
| <TooltipPlus | |||||
| popupContent={t('appDebug.feature.annotation.edit') as string} | |||||
| <Tooltip | |||||
| popupContent={t('appDebug.feature.annotation.edit')} | |||||
| needsDelay | |||||
| > | > | ||||
| <div | <div | ||||
| className='p-1 cursor-pointer rounded-md hover:bg-black/5' | className='p-1 cursor-pointer rounded-md hover:bg-black/5' | ||||
| > | > | ||||
| <Edit04 className='w-4 h-4' /> | <Edit04 className='w-4 h-4' /> | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| </div> | </div> | ||||
| <RemoveAnnotationConfirmModal | <RemoveAnnotationConfirmModal |
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { useContext } from 'use-context-selector' | import { useContext } from 'use-context-selector' | ||||
| import { usePathname, useRouter } from 'next/navigation' | import { usePathname, useRouter } from 'next/navigation' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import ConfigParamModal from './config-param-modal' | import ConfigParamModal from './config-param-modal' | ||||
| import Panel from '@/app/components/app/configuration/base/feature-panel' | import Panel from '@/app/components/app/configuration/base/feature-panel' | ||||
| import { MessageFast } from '@/app/components/base/icons/src/vender/solid/communication' | import { MessageFast } from '@/app/components/base/icons/src/vender/solid/communication' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import { LinkExternal02, Settings04 } from '@/app/components/base/icons/src/vender/line/general' | import { LinkExternal02, Settings04 } from '@/app/components/base/icons/src/vender/line/general' | ||||
| import ConfigContext from '@/context/debug-configuration' | import ConfigContext from '@/context/debug-configuration' | ||||
| import type { EmbeddingModelConfig } from '@/app/components/app/annotation/type' | import type { EmbeddingModelConfig } from '@/app/components/app/annotation/type' | ||||
| <div> | <div> | ||||
| <div className='flex items-center space-x-1'> | <div className='flex items-center space-x-1'> | ||||
| <div>{title}</div> | <div>{title}</div> | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={ | popupContent={ | ||||
| <div className='max-w-[200px] leading-[18px] text-[13px] font-medium text-gray-800'>{tooltip}</div> | <div className='max-w-[200px] leading-[18px] text-[13px] font-medium text-gray-800'>{tooltip}</div> | ||||
| } | } | ||||
| > | |||||
| <RiQuestionLine className='w-3.5 h-3.5 text-gray-400' /> | |||||
| </TooltipPlus> | |||||
| /> | |||||
| </div> | </div> | ||||
| <div>{children}</div> | <div>{children}</div> | ||||
| </div> | </div> |
| RiAddLine, | RiAddLine, | ||||
| RiArrowDownSLine, | RiArrowDownSLine, | ||||
| RiDeleteBinLine, | RiDeleteBinLine, | ||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | } from '@remixicon/react' | ||||
| import ConfigContext from '@/context/debug-configuration' | import ConfigContext from '@/context/debug-configuration' | ||||
| import Switch from '@/app/components/base/switch' | import Switch from '@/app/components/base/switch' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import { Tool03 } from '@/app/components/base/icons/src/vender/solid/general' | import { Tool03 } from '@/app/components/base/icons/src/vender/solid/general' | ||||
| import { | import { | ||||
| Settings01, | Settings01, | ||||
| <div className='mr-1 text-sm font-semibold text-gray-800'> | <div className='mr-1 text-sm font-semibold text-gray-800'> | ||||
| {t('appDebug.feature.tools.title')} | {t('appDebug.feature.tools.title')} | ||||
| </div> | </div> | ||||
| <TooltipPlus popupContent={<div className='max-w-[160px]'>{t('appDebug.feature.tools.tips')}</div>}> | |||||
| <RiQuestionLine className='w-3.5 h-3.5 text-gray-400' /> | |||||
| </TooltipPlus> | |||||
| <Tooltip | |||||
| popupContent={ | |||||
| <div className='max-w-[160px]'> | |||||
| {t('appDebug.feature.tools.tips')} | |||||
| </div> | |||||
| } | |||||
| /> | |||||
| </div> | </div> | ||||
| { | { | ||||
| !expanded && !!externalDataToolsConfig.length && ( | !expanded && !!externalDataToolsConfig.length && ( | ||||
| background={item.icon_background} | background={item.icon_background} | ||||
| /> | /> | ||||
| <div className='mr-2 text-[13px] font-medium text-gray-800'>{item.label}</div> | <div className='mr-2 text-[13px] font-medium text-gray-800'>{item.label}</div> | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={copied ? t('appApi.copied') : `${item.variable}, ${t('appApi.copy')}`} | popupContent={copied ? t('appApi.copied') : `${item.variable}, ${t('appApi.copy')}`} | ||||
| > | > | ||||
| <div | <div | ||||
| > | > | ||||
| {item.variable} | {item.variable} | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| </div> | </div> | ||||
| <div | <div | ||||
| className='hidden group-hover:flex items-center justify-center mr-1 w-6 h-6 hover:bg-black/5 rounded-md cursor-pointer' | className='hidden group-hover:flex items-center justify-center mr-1 w-6 h-6 hover:bg-black/5 rounded-md cursor-pointer' |
| import AppsFull from '@/app/components/billing/apps-full-in-dialog' | import AppsFull from '@/app/components/billing/apps-full-in-dialog' | ||||
| import { AiText, ChatBot, CuteRobote } from '@/app/components/base/icons/src/vender/solid/communication' | import { AiText, ChatBot, CuteRobote } from '@/app/components/base/icons/src/vender/solid/communication' | ||||
| import { Route } from '@/app/components/base/icons/src/vender/solid/mapsAndTravel' | import { Route } from '@/app/components/base/icons/src/vender/solid/mapsAndTravel' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import { NEED_REFRESH_APP_LIST_KEY } from '@/config' | import { NEED_REFRESH_APP_LIST_KEY } from '@/config' | ||||
| import { getRedirection } from '@/utils/app-redirection' | import { getRedirection } from '@/utils/app-redirection' | ||||
| <div className='py-2 px-8'> | <div className='py-2 px-8'> | ||||
| <div className='py-2 text-sm leading-[20px] font-medium text-gray-900'>{t('app.newApp.captionAppType')}</div> | <div className='py-2 text-sm leading-[20px] font-medium text-gray-900'>{t('app.newApp.captionAppType')}</div> | ||||
| <div className='flex'> | <div className='flex'> | ||||
| <TooltipPlus | |||||
| hideArrow | |||||
| <Tooltip | |||||
| popupContent={ | popupContent={ | ||||
| <div className='max-w-[280px] leading-[18px] text-xs text-gray-700'>{t('app.newApp.chatbotDescription')}</div> | <div className='max-w-[280px] leading-[18px] text-xs text-gray-700'>{t('app.newApp.chatbotDescription')}</div> | ||||
| } | } | ||||
| <ChatBot className='w-6 h-6 text-[#1570EF]' /> | <ChatBot className='w-6 h-6 text-[#1570EF]' /> | ||||
| <div className='h-5 text-[13px] font-medium leading-[18px]'>{t('app.types.chatbot')}</div> | <div className='h-5 text-[13px] font-medium leading-[18px]'>{t('app.types.chatbot')}</div> | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| <TooltipPlus | |||||
| hideArrow | |||||
| </Tooltip> | |||||
| <Tooltip | |||||
| popupContent={ | popupContent={ | ||||
| <div className='flex flex-col max-w-[320px] leading-[18px] text-xs'> | <div className='flex flex-col max-w-[320px] leading-[18px] text-xs'> | ||||
| <div className='text-gray-700'>{t('app.newApp.completionDescription')}</div> | <div className='text-gray-700'>{t('app.newApp.completionDescription')}</div> | ||||
| <AiText className='w-6 h-6 text-[#0E9384]' /> | <AiText className='w-6 h-6 text-[#0E9384]' /> | ||||
| <div className='h-5 text-[13px] font-medium leading-[18px]'>{t('app.newApp.completeApp')}</div> | <div className='h-5 text-[13px] font-medium leading-[18px]'>{t('app.newApp.completeApp')}</div> | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| <TooltipPlus | |||||
| hideArrow | |||||
| </Tooltip> | |||||
| <Tooltip | |||||
| popupContent={ | popupContent={ | ||||
| <div className='max-w-[280px] leading-[18px] text-xs text-gray-700'>{t('app.newApp.agentDescription')}</div> | <div className='max-w-[280px] leading-[18px] text-xs text-gray-700'>{t('app.newApp.agentDescription')}</div> | ||||
| } | } | ||||
| <CuteRobote className='w-6 h-6 text-indigo-600' /> | <CuteRobote className='w-6 h-6 text-indigo-600' /> | ||||
| <div className='h-5 text-[13px] font-medium leading-[18px]'>{t('app.types.agent')}</div> | <div className='h-5 text-[13px] font-medium leading-[18px]'>{t('app.types.agent')}</div> | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| <TooltipPlus | |||||
| hideArrow | |||||
| </Tooltip> | |||||
| <Tooltip | |||||
| popupContent={ | popupContent={ | ||||
| <div className='flex flex-col max-w-[320px] leading-[18px] text-xs'> | <div className='flex flex-col max-w-[320px] leading-[18px] text-xs'> | ||||
| <div className='text-gray-700'>{t('app.newApp.workflowDescription')}</div> | <div className='text-gray-700'>{t('app.newApp.workflowDescription')}</div> | ||||
| <div className='h-5 text-[13px] font-medium leading-[18px]'>{t('app.types.workflow')}</div> | <div className='h-5 text-[13px] font-medium leading-[18px]'>{t('app.types.workflow')}</div> | ||||
| <span className='absolute top-[-3px] right-[-3px] px-1 rounded-[5px] bg-white border border-black/8 text-gray-500 text-[10px] leading-[18px] font-medium'>BETA</span> | <span className='absolute top-[-3px] right-[-3px] px-1 rounded-[5px] bg-white border border-black/8 text-gray-500 text-[10px] leading-[18px] font-medium'>BETA</span> | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| {showChatBotType && ( | {showChatBotType && ( |
| import { | import { | ||||
| HandThumbDownIcon, | HandThumbDownIcon, | ||||
| HandThumbUpIcon, | HandThumbUpIcon, | ||||
| InformationCircleIcon, | |||||
| XMarkIcon, | XMarkIcon, | ||||
| } from '@heroicons/react/24/outline' | } from '@heroicons/react/24/outline' | ||||
| import { RiEditFill } from '@remixicon/react' | |||||
| import { RiEditFill, RiQuestionLine } from '@remixicon/react' | |||||
| import { get } from 'lodash-es' | import { get } from 'lodash-es' | ||||
| import InfiniteScroll from 'react-infinite-scroll-component' | import InfiniteScroll from 'react-infinite-scroll-component' | ||||
| import dayjs from 'dayjs' | import dayjs from 'dayjs' | ||||
| import s from './style.module.css' | import s from './style.module.css' | ||||
| import VarPanel from './var-panel' | import VarPanel from './var-panel' | ||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import { randomString } from '@/utils' | |||||
| import type { FeedbackFunc, Feedbacktype, IChatItem, SubmitAnnotationFunc } from '@/app/components/base/chat/chat/type' | import type { FeedbackFunc, Feedbacktype, IChatItem, SubmitAnnotationFunc } from '@/app/components/base/chat/chat/type' | ||||
| import type { Annotation, ChatConversationFullDetailResponse, ChatConversationGeneralDetail, ChatConversationsResponse, ChatMessage, ChatMessagesRequest, CompletionConversationFullDetailResponse, CompletionConversationGeneralDetail, CompletionConversationsResponse, LogAnnotation } from '@/models/log' | import type { Annotation, ChatConversationFullDetailResponse, ChatConversationGeneralDetail, ChatConversationsResponse, ChatMessage, ChatMessagesRequest, CompletionConversationFullDetailResponse, CompletionConversationGeneralDetail, CompletionConversationsResponse, LogAnnotation } from '@/models/log' | ||||
| import type { App } from '@/types/app' | import type { App } from '@/types/app' | ||||
| import Drawer from '@/app/components/base/drawer' | import Drawer from '@/app/components/base/drawer' | ||||
| import Popover from '@/app/components/base/popover' | import Popover from '@/app/components/base/popover' | ||||
| import Chat from '@/app/components/base/chat/chat' | import Chat from '@/app/components/base/chat/chat' | ||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import { ToastContext } from '@/app/components/base/toast' | import { ToastContext } from '@/app/components/base/toast' | ||||
| import { fetchChatConversationDetail, fetchChatMessages, fetchCompletionConversationDetail, updateLogMessageAnnotations, updateLogMessageFeedbacks } from '@/service/log' | import { fetchChatConversationDetail, fetchChatMessages, fetchCompletionConversationDetail, updateLogMessageAnnotations, updateLogMessageFeedbacks } from '@/service/log' | ||||
| import { TONE_LIST } from '@/config' | import { TONE_LIST } from '@/config' | ||||
| import { useStore as useAppStore } from '@/app/components/app/store' | import { useStore as useAppStore } from '@/app/components/app/store' | ||||
| import { useAppContext } from '@/context/app-context' | import { useAppContext } from '@/context/app-context' | ||||
| import useTimestamp from '@/hooks/use-timestamp' | import useTimestamp from '@/hooks/use-timestamp' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import { CopyIcon } from '@/app/components/base/copy-icon' | import { CopyIcon } from '@/app/components/base/copy-icon' | ||||
| dayjs.extend(utc) | dayjs.extend(utc) | ||||
| <div className='text-gray-500 text-[10px] leading-[14px]'>{isChatMode ? t('appLog.detail.conversationId') : t('appLog.detail.time')}</div> | <div className='text-gray-500 text-[10px] leading-[14px]'>{isChatMode ? t('appLog.detail.conversationId') : t('appLog.detail.time')}</div> | ||||
| {isChatMode && ( | {isChatMode && ( | ||||
| <div className='flex items-center text-gray-700 text-[13px] leading-[18px]'> | <div className='flex items-center text-gray-700 text-[13px] leading-[18px]'> | ||||
| <TooltipPlus | |||||
| hideArrow | |||||
| popupContent={detail.id}> | |||||
| <Tooltip | |||||
| popupContent={detail.id} | |||||
| > | |||||
| <div className='max-w-[105px] truncate'>{detail.id}</div> | <div className='max-w-[105px] truncate'>{detail.id}</div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| <CopyIcon content={detail.id} /> | <CopyIcon content={detail.id} /> | ||||
| </div> | </div> | ||||
| )} | )} | ||||
| btnClassName='mr-4 !bg-gray-50 !py-1.5 !px-2.5 border-none font-normal' | btnClassName='mr-4 !bg-gray-50 !py-1.5 !px-2.5 border-none font-normal' | ||||
| btnElement={<> | btnElement={<> | ||||
| <span className='text-[13px]'>{targetTone}</span> | <span className='text-[13px]'>{targetTone}</span> | ||||
| <InformationCircleIcon className='h-4 w-4 text-gray-800 ml-1.5' /> | |||||
| <RiQuestionLine className='h-4 w-4 text-gray-800 ml-1.5' /> | |||||
| </>} | </>} | ||||
| htmlContent={<div className='w-[280px]'> | htmlContent={<div className='w-[280px]'> | ||||
| <div className='flex justify-between py-2 px-4 font-medium text-sm text-gray-700'> | <div className='flex justify-between py-2 px-4 font-medium text-sm text-gray-700'> | ||||
| const renderTdValue = (value: string | number | null, isEmptyStyle: boolean, isHighlight = false, annotation?: LogAnnotation) => { | const renderTdValue = (value: string | number | null, isEmptyStyle: boolean, isHighlight = false, annotation?: LogAnnotation) => { | ||||
| return ( | return ( | ||||
| <Tooltip | <Tooltip | ||||
| htmlContent={ | |||||
| popupContent={ | |||||
| <span className='text-xs text-gray-500 inline-flex items-center'> | <span className='text-xs text-gray-500 inline-flex items-center'> | ||||
| <RiEditFill className='w-3 h-3 mr-1' />{`${t('appLog.detail.annotationTip', { user: annotation?.account?.name })} ${formatTime(annotation?.created_at || dayjs().unix(), 'MM-DD hh:mm A')}`} | <RiEditFill className='w-3 h-3 mr-1' />{`${t('appLog.detail.annotationTip', { user: annotation?.account?.name })} ${formatTime(annotation?.created_at || dayjs().unix(), 'MM-DD hh:mm A')}`} | ||||
| </span> | </span> | ||||
| } | } | ||||
| className={(isHighlight && !isChatMode) ? '' : '!hidden'} | |||||
| selector={`highlight-${randomString(16)}`} | |||||
| popupClassName={(isHighlight && !isChatMode) ? '' : '!hidden'} | |||||
| > | > | ||||
| <div className={cn(isEmptyStyle ? 'text-gray-400' : 'text-gray-700', !isHighlight ? '' : 'bg-orange-100', 'text-sm overflow-hidden text-ellipsis whitespace-nowrap')}> | <div className={cn(isEmptyStyle ? 'text-gray-400' : 'text-gray-700', !isHighlight ? '' : 'bg-orange-100', 'text-sm overflow-hidden text-ellipsis whitespace-nowrap')}> | ||||
| {value || '-'} | {value || '-'} |
| )} | )} | ||||
| {isApp && isCurrentWorkspaceManager && ( | {isApp && isCurrentWorkspaceManager && ( | ||||
| <Tooltip | <Tooltip | ||||
| content={t('appOverview.overview.appInfo.regenerate') || ''} | |||||
| selector={`code-generate-${randomString(8)}`} | |||||
| popupContent={t('appOverview.overview.appInfo.regenerate') || ''} | |||||
| > | > | ||||
| <div | <div | ||||
| className="w-8 h-8 ml-0.5 cursor-pointer hover:bg-gray-200 rounded-lg" | className="w-8 h-8 ml-0.5 cursor-pointer hover:bg-gray-200 rounded-lg" | ||||
| disabled={disabled} | disabled={disabled} | ||||
| > | > | ||||
| <Tooltip | <Tooltip | ||||
| content={ | |||||
| popupContent={ | |||||
| t('appOverview.overview.appInfo.preUseReminder') ?? '' | t('appOverview.overview.appInfo.preUseReminder') ?? '' | ||||
| } | } | ||||
| selector={`op-btn-${randomString(16)}`} | |||||
| className={disabled ? 'mt-[-8px]' : '!hidden'} | |||||
| popupClassName={disabled ? 'mt-[-8px]' : '!hidden'} | |||||
| > | > | ||||
| <div className="flex flex-row items-center"> | <div className="flex flex-row items-center"> | ||||
| <op.opIcon className="h-4 w-4 mr-1.5 stroke-[1.8px]" /> | <op.opIcon className="h-4 w-4 mr-1.5 stroke-[1.8px]" /> |
| </div> | </div> | ||||
| <div className="flex items-center justify-center gap-1 p-2 rounded-lg"> | <div className="flex items-center justify-center gap-1 p-2 rounded-lg"> | ||||
| <Tooltip | <Tooltip | ||||
| selector={'code-copy-feedback'} | |||||
| content={(isCopied[option] ? t(`${prefixEmbedded}.copied`) : t(`${prefixEmbedded}.copy`)) || ''} | |||||
| popupContent={(isCopied[option] ? t(`${prefixEmbedded}.copied`) : t(`${prefixEmbedded}.copy`)) || ''} | |||||
| > | > | ||||
| <div className="w-8 h-8 rounded-lg cursor-pointer hover:bg-gray-100"> | <div className="w-8 h-8 rounded-lg cursor-pointer hover:bg-gray-100"> | ||||
| <div onClick={onClickCopy} className={`w-full h-full ${copyStyle.copyIcon} ${isCopied[option] ? copyStyle.copied : ''}`}></div> | <div onClick={onClickCopy} className={`w-full h-full ${copyStyle.copyIcon} ${isCopied[option] ? copyStyle.copied : ''}`}></div> |
| import type { AppIconType, AppSSO, Language } from '@/types/app' | import type { AppIconType, AppSSO, Language } from '@/types/app' | ||||
| import { useToastContext } from '@/app/components/base/toast' | import { useToastContext } from '@/app/components/base/toast' | ||||
| import { languages } from '@/i18n/language' | import { languages } from '@/i18n/language' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import AppContext from '@/context/app-context' | import AppContext from '@/context/app-context' | ||||
| import type { AppIconSelection } from '@/app/components/base/app-icon-picker' | import type { AppIconSelection } from '@/app/components/base/app-icon-picker' | ||||
| import AppIconPicker from '@/app/components/base/app-icon-picker' | import AppIconPicker from '@/app/components/base/app-icon-picker' | ||||
| <p className='system-xs-medium text-gray-500'>{t(`${prefixSettings}.sso.label`)}</p> | <p className='system-xs-medium text-gray-500'>{t(`${prefixSettings}.sso.label`)}</p> | ||||
| <div className='flex justify-between items-center'> | <div className='flex justify-between items-center'> | ||||
| <div className='font-medium system-sm-semibold flex-grow text-gray-900'>{t(`${prefixSettings}.sso.title`)}</div> | <div className='font-medium system-sm-semibold flex-grow text-gray-900'>{t(`${prefixSettings}.sso.title`)}</div> | ||||
| <TooltipPlus disabled={systemFeatures.sso_enforced_for_web} popupContent={<div className='w-[180px]'>{t(`${prefixSettings}.sso.tooltip`)}</div>}> | |||||
| <Tooltip | |||||
| disabled={systemFeatures.sso_enforced_for_web} | |||||
| popupContent={ | |||||
| <div className='w-[180px]'>{t(`${prefixSettings}.sso.tooltip`)}</div> | |||||
| } | |||||
| asChild={false} | |||||
| > | |||||
| <Switch disabled={!systemFeatures.sso_enforced_for_web} defaultValue={systemFeatures.sso_enforced_for_web && inputInfo.enable_sso} onChange={v => setInputInfo({ ...inputInfo, enable_sso: v })}></Switch> | <Switch disabled={!systemFeatures.sso_enforced_for_web} defaultValue={systemFeatures.sso_enforced_for_web && inputInfo.enable_sso} onChange={v => setInputInfo({ ...inputInfo, enable_sso: v })}></Switch> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| </div> | </div> | ||||
| <p className='body-xs-regular text-gray-500'>{t(`${prefixSettings}.sso.description`)}</p> | <p className='body-xs-regular text-gray-500'>{t(`${prefixSettings}.sso.description`)}</p> | ||||
| </div>} | </div>} |
| }[audioState] | }[audioState] | ||||
| return ( | return ( | ||||
| <div className={`${(audioState === 'loading' || audioState === 'playing') ? 'mr-1' : className}`}> | |||||
| <div className={`inline-flex items-center justify-center ${(audioState === 'loading' || audioState === 'playing') ? 'mr-1' : className}`}> | |||||
| <Tooltip | <Tooltip | ||||
| selector={selector.current} | |||||
| content={tooltipContent} | |||||
| className='z-10' | |||||
| popupContent={tooltipContent} | |||||
| > | > | ||||
| <button | <button | ||||
| disabled={audioState === 'loading'} | disabled={audioState === 'loading'} | ||||
| className={`box-border p-0.5 flex items-center justify-center cursor-pointer ${isAudition || '!p-0 rounded-md bg-white'}`} | |||||
| className={`box-border w-6 h-6 flex items-center justify-center cursor-pointer ${isAudition ? 'p-0.5' : 'p-0 rounded-md bg-white'}`} | |||||
| onClick={handleToggle} | onClick={handleToggle} | ||||
| > | > | ||||
| {audioState === 'loading' | {audioState === 'loading' | ||||
| ? ( | ? ( | ||||
| <div className='w-6 h-6 rounded-md flex items-center justify-center p-2'> | |||||
| <div className='w-full h-full rounded-md flex items-center justify-center'> | |||||
| <Loading /> | <Loading /> | ||||
| </div> | </div> | ||||
| ) | ) | ||||
| : ( | : ( | ||||
| <div className={`w-6 h-6 rounded-md ${!isAudition ? 'w-4 h-4 hover:bg-gray-50' : 'hover:bg-gray-50'} ${(audioState === 'playing') ? s.pauseIcon : s.playIcon}`}></div> | |||||
| <div className={`w-full h-full rounded-md flex items-center justify-center ${!isAudition ? 'hover:bg-gray-50' : 'hover:bg-gray-50'}`}> | |||||
| <div className={`w-4 h-4 ${(audioState === 'playing') ? s.pauseIcon : s.playIcon}`}></div> | |||||
| </div> | |||||
| )} | )} | ||||
| </button> | </button> | ||||
| </Tooltip> | </Tooltip> |
| ThumbsDown, | ThumbsDown, | ||||
| ThumbsUp, | ThumbsUp, | ||||
| } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback' | } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import Log from '@/app/components/base/chat/chat/log' | import Log from '@/app/components/base/chat/chat/log' | ||||
| type OperationProps = { | type OperationProps = { | ||||
| { | { | ||||
| config?.supportFeedback && !localFeedback?.rating && onFeedback && !isOpeningStatement && ( | config?.supportFeedback && !localFeedback?.rating && onFeedback && !isOpeningStatement && ( | ||||
| <div className='hidden group-hover:flex ml-1 shrink-0 items-center px-0.5 bg-white border-[0.5px] border-gray-100 shadow-md text-gray-500 rounded-lg'> | <div className='hidden group-hover:flex ml-1 shrink-0 items-center px-0.5 bg-white border-[0.5px] border-gray-100 shadow-md text-gray-500 rounded-lg'> | ||||
| <TooltipPlus popupContent={t('appDebug.operation.agree')}> | |||||
| <Tooltip | |||||
| popupContent={t('appDebug.operation.agree')} | |||||
| > | |||||
| <div | <div | ||||
| className='flex items-center justify-center mr-0.5 w-6 h-6 rounded-md hover:bg-black/5 hover:text-gray-800 cursor-pointer' | className='flex items-center justify-center mr-0.5 w-6 h-6 rounded-md hover:bg-black/5 hover:text-gray-800 cursor-pointer' | ||||
| onClick={() => handleFeedback('like')} | onClick={() => handleFeedback('like')} | ||||
| > | > | ||||
| <ThumbsUp className='w-4 h-4' /> | <ThumbsUp className='w-4 h-4' /> | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| <TooltipPlus popupContent={t('appDebug.operation.disagree')}> | |||||
| </Tooltip> | |||||
| <Tooltip | |||||
| popupContent={t('appDebug.operation.disagree')} | |||||
| > | |||||
| <div | <div | ||||
| className='flex items-center justify-center w-6 h-6 rounded-md hover:bg-black/5 hover:text-gray-800 cursor-pointer' | className='flex items-center justify-center w-6 h-6 rounded-md hover:bg-black/5 hover:text-gray-800 cursor-pointer' | ||||
| onClick={() => handleFeedback('dislike')} | onClick={() => handleFeedback('dislike')} | ||||
| > | > | ||||
| <ThumbsDown className='w-4 h-4' /> | <ThumbsDown className='w-4 h-4' /> | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| </div> | </div> | ||||
| ) | ) | ||||
| } | } | ||||
| { | { | ||||
| config?.supportFeedback && localFeedback?.rating && onFeedback && !isOpeningStatement && ( | config?.supportFeedback && localFeedback?.rating && onFeedback && !isOpeningStatement && ( | ||||
| <TooltipPlus popupContent={localFeedback.rating === 'like' ? t('appDebug.operation.cancelAgree') : t('appDebug.operation.cancelDisagree')}> | |||||
| <Tooltip | |||||
| popupContent={localFeedback.rating === 'like' ? t('appDebug.operation.cancelAgree') : t('appDebug.operation.cancelDisagree')} | |||||
| > | |||||
| <div | <div | ||||
| className={` | className={` | ||||
| flex items-center justify-center w-7 h-7 rounded-[10px] border-[2px] border-white cursor-pointer | flex items-center justify-center w-7 h-7 rounded-[10px] border-[2px] border-white cursor-pointer | ||||
| ) | ) | ||||
| } | } | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| ) | ) | ||||
| } | } | ||||
| </div> | </div> |
| import { useChatWithHistoryContext } from '../chat-with-history/context' | import { useChatWithHistoryContext } from '../chat-with-history/context' | ||||
| import type { Theme } from '../embedded-chatbot/theme/theme-context' | import type { Theme } from '../embedded-chatbot/theme/theme-context' | ||||
| import { CssTransform } from '../embedded-chatbot/theme/utils' | import { CssTransform } from '../embedded-chatbot/theme/utils' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import { ToastContext } from '@/app/components/base/toast' | import { ToastContext } from '@/app/components/base/toast' | ||||
| import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' | import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' | ||||
| import VoiceInput from '@/app/components/base/voice-input' | import VoiceInput from '@/app/components/base/voice-input' | ||||
| {isMobile | {isMobile | ||||
| ? sendBtn | ? sendBtn | ||||
| : ( | : ( | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={ | popupContent={ | ||||
| <div> | <div> | ||||
| <div>{t('common.operation.send')} Enter</div> | <div>{t('common.operation.send')} Enter</div> | ||||
| } | } | ||||
| > | > | ||||
| {sendBtn} | {sendBtn} | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| )} | )} | ||||
| </div> | </div> | ||||
| { | { |
| </div> | </div> | ||||
| </div> | </div> | ||||
| <Tooltip | <Tooltip | ||||
| selector={'embed-scene-restart-button'} | |||||
| htmlContent={t('share.chat.resetChat')} | |||||
| position='top' | |||||
| popupContent={t('share.chat.resetChat')} | |||||
| > | > | ||||
| <div className='flex cursor-pointer hover:rounded-lg hover:bg-black/5 w-8 h-8 items-center justify-center' onClick={() => { | <div className='flex cursor-pointer hover:rounded-lg hover:bg-black/5 w-8 h-8 items-center justify-center' onClick={() => { | ||||
| onCreateNewChat?.() | onCreateNewChat?.() |
| {!isMobile && ( | {!isMobile && ( | ||||
| <div className='absolute top-2.5 right-3 z-20'> | <div className='absolute top-2.5 right-3 z-20'> | ||||
| <Tooltip | <Tooltip | ||||
| selector={'embed-scene-restart-button'} | |||||
| htmlContent={t('share.chat.resetChat')} | |||||
| position='top' | |||||
| popupContent={t('share.chat.resetChat')} | |||||
| > | > | ||||
| <div className='p-1.5 bg-white border-[0.5px] border-gray-100 rounded-lg shadow-md cursor-pointer' onClick={handleNewConversation}> | <div className='p-1.5 bg-white border-[0.5px] border-gray-100 rounded-lg shadow-md cursor-pointer' onClick={handleNewConversation}> | ||||
| <RiLoopLeftLine className="h-4 w-4 text-gray-500"/> | <RiLoopLeftLine className="h-4 w-4 text-gray-500"/> |
| 'use client' | 'use client' | ||||
| import { useRef, useState } from 'react' | |||||
| import { useState } from 'react' | |||||
| import { t } from 'i18next' | import { t } from 'i18next' | ||||
| import copy from 'copy-to-clipboard' | import copy from 'copy-to-clipboard' | ||||
| import s from './style.module.css' | import s from './style.module.css' | ||||
| import Tooltip from '@/app/components/base/tooltip' | import Tooltip from '@/app/components/base/tooltip' | ||||
| import { randomString } from '@/utils' | |||||
| type ICopyBtnProps = { | type ICopyBtnProps = { | ||||
| value: string | value: string | ||||
| isPlain, | isPlain, | ||||
| }: ICopyBtnProps) => { | }: ICopyBtnProps) => { | ||||
| const [isCopied, setIsCopied] = useState(false) | const [isCopied, setIsCopied] = useState(false) | ||||
| const selector = useRef(`copy-tooltip-${randomString(4)}`) | |||||
| return ( | return ( | ||||
| <div className={`${className}`}> | <div className={`${className}`}> | ||||
| <Tooltip | <Tooltip | ||||
| selector={selector.current} | |||||
| content={(isCopied ? t('appApi.copied') : t('appApi.copy')) as string} | |||||
| className='z-10' | |||||
| popupContent={(isCopied ? t('appApi.copied') : t('appApi.copy'))} | |||||
| > | > | ||||
| <div | <div | ||||
| className={'box-border p-0.5 flex items-center justify-center rounded-md bg-white cursor-pointer'} | className={'box-border p-0.5 flex items-center justify-center rounded-md bg-white cursor-pointer'} |
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { debounce } from 'lodash-es' | import { debounce } from 'lodash-es' | ||||
| import copy from 'copy-to-clipboard' | import copy from 'copy-to-clipboard' | ||||
| import Tooltip from '../tooltip' | |||||
| import TooltipPlus from '../tooltip-plus' | |||||
| import copyStyle from './style.module.css' | import copyStyle from './style.module.css' | ||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| type Props = { | type Props = { | ||||
| content: string | content: string | ||||
| selectorId: string | |||||
| className?: string | className?: string | ||||
| } | } | ||||
| const prefixEmbedded = 'appOverview.overview.appInfo.embedded' | const prefixEmbedded = 'appOverview.overview.appInfo.embedded' | ||||
| const CopyFeedback = ({ content, selectorId, className }: Props) => { | |||||
| const CopyFeedback = ({ content, className }: Props) => { | |||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| const [isCopied, setIsCopied] = useState<boolean>(false) | const [isCopied, setIsCopied] = useState<boolean>(false) | ||||
| return ( | return ( | ||||
| <Tooltip | <Tooltip | ||||
| selector={`common-copy-feedback-${selectorId}`} | |||||
| content={ | |||||
| popupContent={ | |||||
| (isCopied | (isCopied | ||||
| ? t(`${prefixEmbedded}.copied`) | ? t(`${prefixEmbedded}.copied`) | ||||
| : t(`${prefixEmbedded}.copy`)) || '' | : t(`${prefixEmbedded}.copy`)) || '' | ||||
| className={`w-8 h-8 cursor-pointer hover:bg-gray-100 rounded-lg ${ | className={`w-8 h-8 cursor-pointer hover:bg-gray-100 rounded-lg ${ | ||||
| className ?? '' | className ?? '' | ||||
| }`} | }`} | ||||
| onMouseLeave={onMouseLeave} | |||||
| > | > | ||||
| <div | <div | ||||
| onClick={onClickCopy} | onClick={onClickCopy} | ||||
| onMouseLeave={onMouseLeave} | |||||
| className={`w-full h-full ${copyStyle.copyIcon} ${ | className={`w-full h-full ${copyStyle.copyIcon} ${ | ||||
| isCopied ? copyStyle.copied : '' | isCopied ? copyStyle.copied : '' | ||||
| }`} | }`} | ||||
| }, 100) | }, 100) | ||||
| return ( | return ( | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={ | popupContent={ | ||||
| (isCopied | (isCopied | ||||
| ? t(`${prefixEmbedded}.copied`) | ? t(`${prefixEmbedded}.copied`) | ||||
| className={`w-8 h-8 cursor-pointer hover:bg-gray-100 rounded-lg ${ | className={`w-8 h-8 cursor-pointer hover:bg-gray-100 rounded-lg ${ | ||||
| className ?? '' | className ?? '' | ||||
| }`} | }`} | ||||
| onMouseLeave={onMouseLeave} | |||||
| > | > | ||||
| <div | <div | ||||
| onClick={onClickCopy} | onClick={onClickCopy} | ||||
| onMouseLeave={onMouseLeave} | |||||
| className={`w-full h-full ${copyStyle.copyIcon} ${ | className={`w-full h-full ${copyStyle.copyIcon} ${ | ||||
| isCopied ? copyStyle.copied : '' | isCopied ? copyStyle.copied : '' | ||||
| }`} | }`} | ||||
| ></div> | ></div> | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| ) | ) | ||||
| } | } |
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { debounce } from 'lodash-es' | import { debounce } from 'lodash-es' | ||||
| import copy from 'copy-to-clipboard' | import copy from 'copy-to-clipboard' | ||||
| import TooltipPlus from '../tooltip-plus' | |||||
| import Tooltip from '../tooltip' | |||||
| import { | import { | ||||
| Clipboard, | Clipboard, | ||||
| ClipboardCheck, | ClipboardCheck, | ||||
| }, 100) | }, 100) | ||||
| return ( | return ( | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={ | popupContent={ | ||||
| (isCopied | (isCopied | ||||
| ? t(`${prefixEmbedded}.copied`) | ? t(`${prefixEmbedded}.copied`) | ||||
| ) | ) | ||||
| } | } | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| ) | ) | ||||
| } | } | ||||
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import React from 'react' | import React from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import { MessageSmileSquare } from '@/app/components/base/icons/src/vender/solid/communication' | import { MessageSmileSquare } from '@/app/components/base/icons/src/vender/solid/communication' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| const SuggestedQuestionsAfterAnswer: FC = () => { | const SuggestedQuestionsAfterAnswer: FC = () => { | ||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| </div> | </div> | ||||
| <div className='shrink-0 mr-2 flex items-center whitespace-nowrap text-sm text-gray-800 font-semibold'> | <div className='shrink-0 mr-2 flex items-center whitespace-nowrap text-sm text-gray-800 font-semibold'> | ||||
| <div className='mr-2'>{t('appDebug.feature.suggestedQuestionsAfterAnswer.title')}</div> | <div className='mr-2'>{t('appDebug.feature.suggestedQuestionsAfterAnswer.title')}</div> | ||||
| <TooltipPlus popupContent={t('appDebug.feature.suggestedQuestionsAfterAnswer.description')}> | |||||
| <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' /> | |||||
| </TooltipPlus> | |||||
| <Tooltip popupContent={t('appDebug.feature.suggestedQuestionsAfterAnswer.description')}/> | |||||
| </div> | </div> | ||||
| <div className='grow'></div> | <div className='grow'></div> | ||||
| <div className='text-xs text-gray-500'>{t('appDebug.feature.suggestedQuestionsAfterAnswer.resDes')}</div> | <div className='text-xs text-gray-500'>{t('appDebug.feature.suggestedQuestionsAfterAnswer.resDes')}</div> |
| import useSWR from 'swr' | import useSWR from 'swr' | ||||
| import produce from 'immer' | import produce from 'immer' | ||||
| import React, { Fragment } from 'react' | import React, { Fragment } from 'react' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import { usePathname } from 'next/navigation' | import { usePathname } from 'next/navigation' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { Listbox, Transition } from '@headlessui/react' | import { Listbox, Transition } from '@headlessui/react' | ||||
| <div className='mb-2 flex items-center space-x-1'> | <div className='mb-2 flex items-center space-x-1'> | ||||
| <div | <div | ||||
| className='leading-[18px] text-[13px] font-semibold text-gray-800'>{t('appDebug.voice.voiceSettings.language')}</div> | className='leading-[18px] text-[13px] font-semibold text-gray-800'>{t('appDebug.voice.voiceSettings.language')}</div> | ||||
| <Tooltip htmlContent={<div className='w-[180px]'> | |||||
| {t('appDebug.voice.voiceSettings.resolutionTooltip').split('\n').map(item => ( | |||||
| <div key={item}>{item}</div> | |||||
| ))} | |||||
| </div>} selector='config-resolution-tooltip'> | |||||
| <RiQuestionLine className='w-[14px] h-[14px] text-gray-400'/> | |||||
| </Tooltip> | |||||
| <Tooltip | |||||
| popupContent={ | |||||
| <div className='w-[180px]'> | |||||
| {t('appDebug.voice.voiceSettings.resolutionTooltip').split('\n').map(item => ( | |||||
| <div key={item}>{item} | |||||
| </div> | |||||
| ))} | |||||
| </div> | |||||
| } | |||||
| /> | |||||
| </div> | </div> | ||||
| <Listbox | <Listbox | ||||
| value={languageItem} | value={languageItem} |
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import { RefreshCcw01 } from '@/app/components/base/icons/src/vender/line/arrows' | import { RefreshCcw01 } from '@/app/components/base/icons/src/vender/line/arrows' | ||||
| import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback' | import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import type { ImageFile } from '@/types/app' | import type { ImageFile } from '@/types/app' | ||||
| import { TransferMethod } from '@/types/app' | import { TransferMethod } from '@/types/app' | ||||
| import ImagePreview from '@/app/components/base/image-uploader/image-preview' | import ImagePreview from '@/app/components/base/image-uploader/image-preview' | ||||
| <RiLoader2Line className="animate-spin w-5 h-5 text-white" /> | <RiLoader2Line className="animate-spin w-5 h-5 text-white" /> | ||||
| )} | )} | ||||
| {item.progress === -1 && ( | {item.progress === -1 && ( | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={t('common.imageUploader.pasteImageLinkInvalid')} | popupContent={t('common.imageUploader.pasteImageLinkInvalid')} | ||||
| > | > | ||||
| <AlertTriangle className="w-4 h-4 text-[#DC6803]" /> | <AlertTriangle className="w-4 h-4 text-[#DC6803]" /> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| )} | )} | ||||
| </div> | </div> | ||||
| )} | )} |
| 'use client' | 'use client' | ||||
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import Tooltip from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import Slider from '@/app/components/base/slider' | import Slider from '@/app/components/base/slider' | ||||
| import Switch from '@/app/components/base/switch' | import Switch from '@/app/components/base/switch' | ||||
| )} | )} | ||||
| <span className="mx-1 text-gray-900 text-[13px] leading-[18px] font-medium">{name}</span> | <span className="mx-1 text-gray-900 text-[13px] leading-[18px] font-medium">{name}</span> | ||||
| {!noTooltip && ( | {!noTooltip && ( | ||||
| <Tooltip popupContent={<div className="w-[200px]">{tip}</div>}> | |||||
| <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' /> | |||||
| </Tooltip> | |||||
| <Tooltip | |||||
| popupContent={<div className="w-[200px]">{tip}</div>} | |||||
| /> | |||||
| )} | )} | ||||
| </div> | </div> |
| import { VarBlockIcon } from '@/app/components/workflow/block-icon' | import { VarBlockIcon } from '@/app/components/workflow/block-icon' | ||||
| import { Line3 } from '@/app/components/base/icons/src/public/common' | import { Line3 } from '@/app/components/base/icons/src/public/common' | ||||
| import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| type WorkflowVariableBlockComponentProps = { | type WorkflowVariableBlockComponentProps = { | ||||
| nodeKey: string | nodeKey: string | ||||
| if (!node && !isEnv && !isChatVar) { | if (!node && !isEnv && !isChatVar) { | ||||
| return ( | return ( | ||||
| <TooltipPlus popupContent={t('workflow.errorMsg.invalidVariable')}> | |||||
| <Tooltip popupContent={t('workflow.errorMsg.invalidVariable')}> | |||||
| {Item} | {Item} | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| ) | ) | ||||
| } | } | ||||
| import React, { useEffect, useRef, useState } from 'react' | import React, { useEffect, useRef, useState } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import QRCode from 'qrcode.react' | import QRCode from 'qrcode.react' | ||||
| import Tooltip from '../tooltip' | |||||
| import QrcodeStyle from './style.module.css' | import QrcodeStyle from './style.module.css' | ||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| type Props = { | type Props = { | ||||
| content: string | content: string | ||||
| return ( | return ( | ||||
| <Tooltip | <Tooltip | ||||
| selector={`common-qrcode-show-${selectorId}`} | |||||
| content={t(`${prefixEmbedded}`) || ''} | |||||
| popupContent={t(`${prefixEmbedded}`) || ''} | |||||
| > | > | ||||
| <div | <div | ||||
| className={`w-8 h-8 cursor-pointer rounded-lg ${className ?? ''}`} | className={`w-8 h-8 cursor-pointer rounded-lg ${className ?? ''}`} |
| 'use client' | |||||
| import type { FC } from 'react' | |||||
| import React, { useEffect, useRef, useState } from 'react' | |||||
| import { useBoolean } from 'ahooks' | |||||
| import type { OffsetOptions, Placement } from '@floating-ui/react' | |||||
| import cn from '@/utils/classnames' | |||||
| import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '@/app/components/base/portal-to-follow-elem' | |||||
| export type TooltipProps = { | |||||
| position?: Placement | |||||
| triggerMethod?: 'hover' | 'click' | |||||
| disabled?: boolean | |||||
| popupContent: React.ReactNode | |||||
| children: React.ReactNode | |||||
| hideArrow?: boolean | |||||
| popupClassName?: string | |||||
| offset?: OffsetOptions | |||||
| asChild?: boolean | |||||
| } | |||||
| const arrow = ( | |||||
| <svg className="absolute text-white h-2 w-full left-0 top-full" x="0px" y="0px" viewBox="0 0 255 255"><polygon className="fill-current" points="0,0 127.5,127.5 255,0"></polygon></svg> | |||||
| ) | |||||
| const Tooltip: FC<TooltipProps> = ({ | |||||
| position = 'top', | |||||
| triggerMethod = 'hover', | |||||
| disabled = false, | |||||
| popupContent, | |||||
| children, | |||||
| hideArrow, | |||||
| popupClassName, | |||||
| offset, | |||||
| asChild, | |||||
| }) => { | |||||
| const [open, setOpen] = useState(false) | |||||
| const [isHoverPopup, { | |||||
| setTrue: setHoverPopup, | |||||
| setFalse: setNotHoverPopup, | |||||
| }] = useBoolean(false) | |||||
| const isHoverPopupRef = useRef(isHoverPopup) | |||||
| useEffect(() => { | |||||
| isHoverPopupRef.current = isHoverPopup | |||||
| }, [isHoverPopup]) | |||||
| const [isHoverTrigger, { | |||||
| setTrue: setHoverTrigger, | |||||
| setFalse: setNotHoverTrigger, | |||||
| }] = useBoolean(false) | |||||
| const isHoverTriggerRef = useRef(isHoverTrigger) | |||||
| useEffect(() => { | |||||
| isHoverTriggerRef.current = isHoverTrigger | |||||
| }, [isHoverTrigger]) | |||||
| const handleLeave = (isTrigger: boolean) => { | |||||
| if (isTrigger) | |||||
| setNotHoverTrigger() | |||||
| else | |||||
| setNotHoverPopup() | |||||
| // give time to move to the popup | |||||
| setTimeout(() => { | |||||
| if (!isHoverPopupRef.current && !isHoverTriggerRef.current) | |||||
| setOpen(false) | |||||
| }, 500) | |||||
| } | |||||
| return ( | |||||
| <PortalToFollowElem | |||||
| open={disabled ? false : open} | |||||
| onOpenChange={setOpen} | |||||
| placement={position} | |||||
| offset={offset ?? 10} | |||||
| > | |||||
| <PortalToFollowElemTrigger | |||||
| onClick={() => triggerMethod === 'click' && setOpen(v => !v)} | |||||
| onMouseEnter={() => { | |||||
| if (triggerMethod === 'hover') { | |||||
| setHoverTrigger() | |||||
| setOpen(true) | |||||
| } | |||||
| }} | |||||
| onMouseLeave={() => triggerMethod === 'hover' && handleLeave(true)} | |||||
| asChild={asChild} | |||||
| > | |||||
| {children} | |||||
| </PortalToFollowElemTrigger> | |||||
| <PortalToFollowElemContent | |||||
| className="z-[9999]" | |||||
| > | |||||
| <div | |||||
| className={cn( | |||||
| 'relative px-3 py-2 text-xs font-normal text-gray-700 bg-white rounded-md shadow-lg', | |||||
| popupClassName, | |||||
| )} | |||||
| onMouseEnter={() => triggerMethod === 'hover' && setHoverPopup()} | |||||
| onMouseLeave={() => triggerMethod === 'hover' && handleLeave(false)} | |||||
| > | |||||
| {popupContent} | |||||
| {!hideArrow && arrow} | |||||
| </div> | |||||
| </PortalToFollowElemContent> | |||||
| </PortalToFollowElem> | |||||
| ) | |||||
| } | |||||
| export default React.memo(Tooltip) |
| 'use client' | 'use client' | ||||
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import React from 'react' | |||||
| import { Tooltip as ReactTooltip } from 'react-tooltip' // fixed version to 5.8.3 https://github.com/ReactTooltip/react-tooltip/issues/972 | |||||
| import classNames from '@/utils/classnames' | |||||
| import 'react-tooltip/dist/react-tooltip.css' | |||||
| type TooltipProps = { | |||||
| selector: string | |||||
| content?: string | |||||
| import React, { useEffect, useRef, useState } from 'react' | |||||
| import { useBoolean } from 'ahooks' | |||||
| import type { OffsetOptions, Placement } from '@floating-ui/react' | |||||
| import { RiQuestionLine } from '@remixicon/react' | |||||
| import cn from '@/utils/classnames' | |||||
| import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '@/app/components/base/portal-to-follow-elem' | |||||
| export type TooltipProps = { | |||||
| position?: Placement | |||||
| triggerMethod?: 'hover' | 'click' | |||||
| triggerClassName?: string | |||||
| disabled?: boolean | disabled?: boolean | ||||
| htmlContent?: React.ReactNode | |||||
| className?: string // This should use !impornant to override the default styles eg: '!bg-white' | |||||
| position?: 'top' | 'right' | 'bottom' | 'left' | |||||
| clickable?: boolean | |||||
| children: React.ReactNode | |||||
| noArrow?: boolean | |||||
| popupContent?: React.ReactNode | |||||
| children?: React.ReactNode | |||||
| popupClassName?: string | |||||
| offset?: OffsetOptions | |||||
| needsDelay?: boolean | |||||
| asChild?: boolean | |||||
| } | } | ||||
| const Tooltip: FC<TooltipProps> = ({ | const Tooltip: FC<TooltipProps> = ({ | ||||
| selector, | |||||
| content, | |||||
| disabled, | |||||
| position = 'top', | position = 'top', | ||||
| triggerMethod = 'hover', | |||||
| triggerClassName, | |||||
| disabled = false, | |||||
| popupContent, | |||||
| children, | children, | ||||
| htmlContent, | |||||
| className, | |||||
| clickable, | |||||
| noArrow, | |||||
| popupClassName, | |||||
| offset, | |||||
| asChild = true, | |||||
| needsDelay = false, | |||||
| }) => { | }) => { | ||||
| const [open, setOpen] = useState(false) | |||||
| const [isHoverPopup, { | |||||
| setTrue: setHoverPopup, | |||||
| setFalse: setNotHoverPopup, | |||||
| }] = useBoolean(false) | |||||
| const isHoverPopupRef = useRef(isHoverPopup) | |||||
| useEffect(() => { | |||||
| isHoverPopupRef.current = isHoverPopup | |||||
| }, [isHoverPopup]) | |||||
| const [isHoverTrigger, { | |||||
| setTrue: setHoverTrigger, | |||||
| setFalse: setNotHoverTrigger, | |||||
| }] = useBoolean(false) | |||||
| const isHoverTriggerRef = useRef(isHoverTrigger) | |||||
| useEffect(() => { | |||||
| isHoverTriggerRef.current = isHoverTrigger | |||||
| }, [isHoverTrigger]) | |||||
| const handleLeave = (isTrigger: boolean) => { | |||||
| if (isTrigger) | |||||
| setNotHoverTrigger() | |||||
| else | |||||
| setNotHoverPopup() | |||||
| // give time to move to the popup | |||||
| if (needsDelay) { | |||||
| setTimeout(() => { | |||||
| if (!isHoverPopupRef.current && !isHoverTriggerRef.current) | |||||
| setOpen(false) | |||||
| }, 500) | |||||
| } | |||||
| else { | |||||
| setOpen(false) | |||||
| } | |||||
| } | |||||
| return ( | return ( | ||||
| <div className='tooltip-container'> | |||||
| {React.cloneElement(children as React.ReactElement, { | |||||
| 'data-tooltip-id': selector, | |||||
| }) | |||||
| } | |||||
| <ReactTooltip | |||||
| id={selector} | |||||
| content={content} | |||||
| className={classNames('!z-[999] !bg-white !text-xs !font-normal !text-gray-700 !shadow-lg !opacity-100', className)} | |||||
| place={position} | |||||
| clickable={clickable} | |||||
| isOpen={disabled ? false : undefined} | |||||
| noArrow={noArrow} | |||||
| <PortalToFollowElem | |||||
| open={disabled ? false : open} | |||||
| onOpenChange={setOpen} | |||||
| placement={position} | |||||
| offset={offset ?? 8} | |||||
| > | |||||
| <PortalToFollowElemTrigger | |||||
| onClick={() => triggerMethod === 'click' && setOpen(v => !v)} | |||||
| onMouseEnter={() => { | |||||
| if (triggerMethod === 'hover') { | |||||
| setHoverTrigger() | |||||
| setOpen(true) | |||||
| } | |||||
| }} | |||||
| onMouseLeave={() => triggerMethod === 'hover' && handleLeave(true)} | |||||
| asChild={asChild} | |||||
| > | |||||
| {children || <div className={triggerClassName || 'p-[1px] w-3.5 h-3.5 shrink-0'}><RiQuestionLine className='text-text-quaternary hover:text-text-tertiary w-full h-full' /></div>} | |||||
| </PortalToFollowElemTrigger> | |||||
| <PortalToFollowElemContent | |||||
| className="z-[9999]" | |||||
| > | > | ||||
| {htmlContent && htmlContent} | |||||
| </ReactTooltip> | |||||
| </div> | |||||
| {popupContent && (<div | |||||
| className={cn( | |||||
| 'relative px-3 py-2 text-xs font-normal text-gray-700 bg-white rounded-md shadow-lg break-words', | |||||
| popupClassName, | |||||
| )} | |||||
| onMouseEnter={() => triggerMethod === 'hover' && setHoverPopup()} | |||||
| onMouseLeave={() => triggerMethod === 'hover' && handleLeave(false)} | |||||
| > | |||||
| {popupContent} | |||||
| </div>)} | |||||
| </PortalToFollowElemContent> | |||||
| </PortalToFollowElem> | |||||
| ) | ) | ||||
| } | } | ||||
| export default Tooltip | |||||
| export default React.memo(Tooltip) |
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import React from 'react' | import React from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import { useContext } from 'use-context-selector' | import { useContext } from 'use-context-selector' | ||||
| import { Plan } from '../type' | import { Plan } from '../type' | ||||
| import { ALL_PLANS, NUM_INFINITE, contactSalesUrl, contractSales, unAvailable } from '../config' | import { ALL_PLANS, NUM_INFINITE, contactSalesUrl, contractSales, unAvailable } from '../config' | ||||
| import Toast from '../../base/toast' | import Toast from '../../base/toast' | ||||
| import TooltipPlus from '../../base/tooltip-plus' | |||||
| import Tooltip from '../../base/tooltip' | |||||
| import { PlanRange } from './select-plan-range' | import { PlanRange } from './select-plan-range' | ||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import { useAppContext } from '@/context/app-context' | import { useAppContext } from '@/context/app-context' | ||||
| <div className='flex items-center text-gray-500 space-x-1'> | <div className='flex items-center text-gray-500 space-x-1'> | ||||
| <div>{label}</div> | <div>{label}</div> | ||||
| {tooltip && ( | {tooltip && ( | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={ | popupContent={ | ||||
| <div className='w-[200px]'>{tooltip}</div> | <div className='w-[200px]'>{tooltip}</div> | ||||
| } | } | ||||
| > | |||||
| <RiQuestionLine className='w-3 h-3 text-gray-400' /> | |||||
| </TooltipPlus> | |||||
| /> | |||||
| )} | )} | ||||
| </div> | </div> | ||||
| <div className='mt-0.5 text-gray-900'>{value}</div> | <div className='mt-0.5 text-gray-900'>{value}</div> | ||||
| <div className='mt-3.5 flex items-center space-x-1'> | <div className='mt-3.5 flex items-center space-x-1'> | ||||
| <span>+ </span> | <span>+ </span> | ||||
| <div>{t('billing.plansCommon.supportItems.llmLoadingBalancing')}</div> | <div>{t('billing.plansCommon.supportItems.llmLoadingBalancing')}</div> | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={ | popupContent={ | ||||
| <div className='w-[200px]'>{t('billing.plansCommon.supportItems.llmLoadingBalancingTooltip')}</div> | <div className='w-[200px]'>{t('billing.plansCommon.supportItems.llmLoadingBalancingTooltip')}</div> | ||||
| } | } | ||||
| > | |||||
| <RiQuestionLine className='w-3 h-3 text-gray-400' /> | |||||
| </TooltipPlus> | |||||
| /> | |||||
| </div> | </div> | ||||
| <div className='mt-3.5 flex items-center space-x-1'> | <div className='mt-3.5 flex items-center space-x-1'> | ||||
| <div className='flex items-center'> | <div className='flex items-center'> | ||||
| + | + | ||||
| <div className='mr-0.5'> {t('billing.plansCommon.supportItems.ragAPIRequest')}</div> | <div className='mr-0.5'> {t('billing.plansCommon.supportItems.ragAPIRequest')}</div> | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={ | popupContent={ | ||||
| <div className='w-[200px]'>{t('billing.plansCommon.ragAPIRequestTooltip')}</div> | <div className='w-[200px]'>{t('billing.plansCommon.ragAPIRequestTooltip')}</div> | ||||
| } | } | ||||
| > | |||||
| <RiQuestionLine className='w-3 h-3 text-gray-400' /> | |||||
| </TooltipPlus> | |||||
| /> | |||||
| </div> | </div> | ||||
| <div>{comingSoon}</div> | <div>{comingSoon}</div> | ||||
| </div> | </div> |
| ZapFast, | ZapFast, | ||||
| ZapNarrow, | ZapNarrow, | ||||
| } from '@/app/components/base/icons/src/vender/solid/general' | } from '@/app/components/base/icons/src/vender/solid/general' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| const PriorityLabel = () => { | const PriorityLabel = () => { | ||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| }, [plan]) | }, [plan]) | ||||
| return ( | return ( | ||||
| <TooltipPlus popupContent={ | |||||
| <Tooltip popupContent={ | |||||
| <div> | <div> | ||||
| <div className='mb-1 text-xs font-semibold text-gray-700'>{`${t('billing.plansCommon.documentProcessingPriority')}: ${t(`billing.plansCommon.priority.${priority}`)}`}</div> | <div className='mb-1 text-xs font-semibold text-gray-700'>{`${t('billing.plansCommon.documentProcessingPriority')}: ${t(`billing.plansCommon.priority.${priority}`)}`}</div> | ||||
| { | { | ||||
| } | } | ||||
| {t(`billing.plansCommon.priority.${priority}`)} | {t(`billing.plansCommon.priority.${priority}`)} | ||||
| </span> | </span> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| ) | ) | ||||
| } | } | ||||
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import React from 'react' | import React from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { InfoCircle } from '../../base/icons/src/vender/line/general' | |||||
| import ProgressBar from '../progress-bar' | import ProgressBar from '../progress-bar' | ||||
| import { NUM_INFINITE } from '../config' | import { NUM_INFINITE } from '../config' | ||||
| import Tooltip from '@/app/components/base/tooltip' | import Tooltip from '@/app/components/base/tooltip' | ||||
| <Icon className='w-4 h-4 text-gray-700' /> | <Icon className='w-4 h-4 text-gray-700' /> | ||||
| <div className='mx-1 leading-5 text-sm font-medium text-gray-700'>{name}</div> | <div className='mx-1 leading-5 text-sm font-medium text-gray-700'>{name}</div> | ||||
| {tooltip && ( | {tooltip && ( | ||||
| <Tooltip htmlContent={<div className='w-[180px]'> | |||||
| {tooltip} | |||||
| </div>} selector='config-var-tooltip'> | |||||
| <InfoCircle className='w-[14px] h-[14px] text-gray-400' /> | |||||
| </Tooltip> | |||||
| <Tooltip | |||||
| popupContent={ | |||||
| <div className='w-[180px]'> | |||||
| {tooltip} | |||||
| </div> | |||||
| } | |||||
| /> | |||||
| )} | )} | ||||
| </div> | </div> | ||||
| <div className='flex items-center leading-[18px] text-[13px] font-normal'> | <div className='flex items-center leading-[18px] text-[13px] font-normal'> |
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import React from 'react' | import React from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import TopKItem from '@/app/components/base/param-item/top-k-item' | import TopKItem from '@/app/components/base/param-item/top-k-item' | ||||
| import ScoreThresholdItem from '@/app/components/base/param-item/score-threshold-item' | import ScoreThresholdItem from '@/app/components/base/param-item/score-threshold-item' | ||||
| import { RETRIEVE_METHOD } from '@/types/app' | import { RETRIEVE_METHOD } from '@/types/app' | ||||
| import Switch from '@/app/components/base/switch' | import Switch from '@/app/components/base/switch' | ||||
| import Tooltip from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import type { RetrievalConfig } from '@/types/app' | import type { RetrievalConfig } from '@/types/app' | ||||
| import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector' | import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector' | ||||
| import { useModelListAndDefaultModel } from '@/app/components/header/account-setting/model-provider-page/hooks' | import { useModelListAndDefaultModel } from '@/app/components/header/account-setting/model-provider-page/hooks' | ||||
| )} | )} | ||||
| <div className='flex items-center'> | <div className='flex items-center'> | ||||
| <span className='mr-0.5'>{t('common.modelProvider.rerankModel.key')}</span> | <span className='mr-0.5'>{t('common.modelProvider.rerankModel.key')}</span> | ||||
| <Tooltip popupContent={<div className="w-[200px]">{t('common.modelProvider.rerankModel.tip')}</div>}> | |||||
| <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' /> | |||||
| </Tooltip> | |||||
| <Tooltip | |||||
| popupContent={ | |||||
| <div className="w-[200px]">{t('common.modelProvider.rerankModel.tip')}</div> | |||||
| } | |||||
| /> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <ModelSelector | <ModelSelector | ||||
| <div className='truncate'>{option.label}</div> | <div className='truncate'>{option.label}</div> | ||||
| <Tooltip | <Tooltip | ||||
| popupContent={<div className='w-[200px]'>{option.tips}</div>} | popupContent={<div className='w-[200px]'>{option.tips}</div>} | ||||
| hideArrow | |||||
| > | |||||
| <RiQuestionLine className='ml-0.5 w-3.5 h-4.5 text-text-quaternary' /> | |||||
| </Tooltip> | |||||
| triggerClassName='ml-0.5 w-3.5 h-4.5' | |||||
| /> | |||||
| </div> | </div> | ||||
| )) | )) | ||||
| } | } |
| import { ZapFast } from '@/app/components/base/icons/src/vender/solid/general' | import { ZapFast } from '@/app/components/base/icons/src/vender/solid/general' | ||||
| import UpgradeBtn from '@/app/components/billing/upgrade-btn' | import UpgradeBtn from '@/app/components/billing/upgrade-btn' | ||||
| import { useProviderContext } from '@/context/provider-context' | import { useProviderContext } from '@/context/provider-context' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import { sleep } from '@/utils' | import { sleep } from '@/utils' | ||||
| type Props = { | type Props = { | ||||
| <div className={s.percent}>{`${getSourcePercent(indexingStatusDetail)}%`}</div> | <div className={s.percent}>{`${getSourcePercent(indexingStatusDetail)}%`}</div> | ||||
| )} | )} | ||||
| {indexingStatusDetail.indexing_status === 'error' && indexingStatusDetail.error && ( | {indexingStatusDetail.indexing_status === 'error' && indexingStatusDetail.error && ( | ||||
| <TooltipPlus popupContent={( | |||||
| <div className='max-w-[400px]'> | |||||
| {indexingStatusDetail.error} | |||||
| </div> | |||||
| )}> | |||||
| <Tooltip | |||||
| popupContent={( | |||||
| <div className='max-w-[400px]'> | |||||
| {indexingStatusDetail.error} | |||||
| </div> | |||||
| )} | |||||
| > | |||||
| <div className={cn(s.percent, s.error, 'flex items-center')}> | <div className={cn(s.percent, s.error, 'flex items-center')}> | ||||
| Error | Error | ||||
| <RiErrorWarningFill className='ml-1 w-4 h-4' /> | <RiErrorWarningFill className='ml-1 w-4 h-4' /> | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| )} | )} | ||||
| {indexingStatusDetail.indexing_status === 'error' && !indexingStatusDetail.error && ( | {indexingStatusDetail.indexing_status === 'error' && !indexingStatusDetail.error && ( | ||||
| <div className={cn(s.percent, s.error, 'flex items-center')}> | <div className={cn(s.percent, s.error, 'flex items-center')}> |
| import { RocketLaunchIcon } from '@heroicons/react/24/outline' | import { RocketLaunchIcon } from '@heroicons/react/24/outline' | ||||
| import { | import { | ||||
| RiCloseLine, | RiCloseLine, | ||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | } from '@remixicon/react' | ||||
| import Link from 'next/link' | import Link from 'next/link' | ||||
| import { groupBy } from 'lodash-es' | import { groupBy } from 'lodash-es' | ||||
| import { RETRIEVE_METHOD } from '@/types/app' | import { RETRIEVE_METHOD } from '@/types/app' | ||||
| import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' | import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' | ||||
| import Tooltip from '@/app/components/base/tooltip' | import Tooltip from '@/app/components/base/tooltip' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks' | import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks' | ||||
| import { LanguagesSupported } from '@/i18n/language' | import { LanguagesSupported } from '@/i18n/language' | ||||
| import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' | import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' | ||||
| className='border-[0.5px] !h-8 hover:outline hover:outline-[0.5px] hover:outline-gray-300 text-gray-700 font-medium bg-white shadow-[0px_1px_2px_0px_rgba(16,24,40,0.05)]' | className='border-[0.5px] !h-8 hover:outline hover:outline-[0.5px] hover:outline-gray-300 text-gray-700 font-medium bg-white shadow-[0px_1px_2px_0px_rgba(16,24,40,0.05)]' | ||||
| onClick={setShowPreview} | onClick={setShowPreview} | ||||
| > | > | ||||
| <Tooltip selector='data-preview-toggle'> | |||||
| <Tooltip> | |||||
| <div className="flex flex-row items-center"> | <div className="flex flex-row items-center"> | ||||
| <RocketLaunchIcon className="h-4 w-4 mr-1.5 stroke-[1.8px]" /> | <RocketLaunchIcon className="h-4 w-4 mr-1.5 stroke-[1.8px]" /> | ||||
| <span className="text-[13px]">{t('datasetCreation.stepTwo.previewTitleButton')}</span> | <span className="text-[13px]">{t('datasetCreation.stepTwo.previewTitleButton')}</span> | ||||
| <div className='w-full'> | <div className='w-full'> | ||||
| <div className={s.label}> | <div className={s.label}> | ||||
| {t('datasetCreation.stepTwo.overlap')} | {t('datasetCreation.stepTwo.overlap')} | ||||
| <TooltipPlus popupContent={ | |||||
| <div className='max-w-[200px]'> | |||||
| {t('datasetCreation.stepTwo.overlapTip')} | |||||
| </div> | |||||
| }> | |||||
| <RiQuestionLine className='ml-1 w-3.5 h-3.5 text-gray-400' /> | |||||
| </TooltipPlus> | |||||
| <Tooltip | |||||
| popupContent={ | |||||
| <div className='max-w-[200px]'> | |||||
| {t('datasetCreation.stepTwo.overlapTip')} | |||||
| </div> | |||||
| } | |||||
| /> | |||||
| </div> | </div> | ||||
| <input | <input | ||||
| type="number" | type="number" |
| 'use client' | 'use client' | ||||
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import React from 'react' | import React from 'react' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import Input from './input' | import Input from './input' | ||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| type Props = { | type Props = { | ||||
| className?: string | className?: string | ||||
| <div className={cn(labelClassName, 'flex items-center h-[18px] text-[13px] font-medium text-gray-900')}>{label} </div> | <div className={cn(labelClassName, 'flex items-center h-[18px] text-[13px] font-medium text-gray-900')}>{label} </div> | ||||
| {isRequired && <span className='ml-0.5 text-xs font-semibold text-[#D92D20]'>*</span>} | {isRequired && <span className='ml-0.5 text-xs font-semibold text-[#D92D20]'>*</span>} | ||||
| {tooltip && ( | {tooltip && ( | ||||
| <TooltipPlus popupContent={ | |||||
| <div className='w-[200px]'>{tooltip}</div> | |||||
| }> | |||||
| <RiQuestionLine className='relative top-[3px] w-3 h-3 ml-1 text-gray-500' /> | |||||
| </TooltipPlus> | |||||
| <Tooltip | |||||
| popupContent={ | |||||
| <div className='w-[200px]'>{tooltip}</div> | |||||
| } | |||||
| popupClassName='relative top-[3px] w-3 h-3 ml-1' | |||||
| /> | |||||
| )} | )} | ||||
| </div> | </div> | ||||
| <Input | <Input |
| const metadataMap = useMetadataMap() | const metadataMap = useMetadataMap() | ||||
| return ( | return ( | ||||
| <Tooltip content={metadataMap[type].text} selector={`doc-metadata-${type}`}> | |||||
| <Tooltip | |||||
| popupContent={metadataMap[type].text} | |||||
| > | |||||
| <button className={cn(s.iconWrapper, 'group', isChecked ? s.iconCheck : '')}> | <button className={cn(s.iconWrapper, 'group', isChecked ? s.iconCheck : '')}> | ||||
| <TypeIcon | <TypeIcon | ||||
| iconName={metadataMap[type].iconName || ''} | iconName={metadataMap[type].iconName || ''} |
| import { pick } from 'lodash-es' | import { pick } from 'lodash-es' | ||||
| import { | import { | ||||
| RiMoreFill, | RiMoreFill, | ||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | } from '@remixicon/react' | ||||
| import { useContext } from 'use-context-selector' | import { useContext } from 'use-context-selector' | ||||
| import { useRouter } from 'next/navigation' | import { useRouter } from 'next/navigation' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import dayjs from 'dayjs' | import dayjs from 'dayjs' | ||||
| import { Edit03 } from '../../base/icons/src/vender/solid/general' | import { Edit03 } from '../../base/icons/src/vender/solid/general' | ||||
| import TooltipPlus from '../../base/tooltip-plus' | |||||
| import { Globe01 } from '../../base/icons/src/vender/line/mapsAndTravel' | import { Globe01 } from '../../base/icons/src/vender/line/mapsAndTravel' | ||||
| import s from './style.module.css' | import s from './style.module.css' | ||||
| import RenameModal from './rename-modal' | import RenameModal from './rename-modal' | ||||
| { | { | ||||
| errorMessage && ( | errorMessage && ( | ||||
| <Tooltip | <Tooltip | ||||
| selector='dataset-document-detail-item-status' | |||||
| htmlContent={ | |||||
| popupContent={ | |||||
| <div className='max-w-[260px] break-all'>{errorMessage}</div> | <div className='max-w-[260px] break-all'>{errorMessage}</div> | ||||
| } | } | ||||
| > | |||||
| <RiQuestionLine className='ml-1 w-[14px] h-[14px] text-gray-700' /> | |||||
| </Tooltip> | |||||
| triggerClassName='ml-1 w-4 h-4' | |||||
| /> | |||||
| ) | ) | ||||
| } | } | ||||
| </div> | </div> | ||||
| {isListScene && embeddingAvailable && ( | {isListScene && embeddingAvailable && ( | ||||
| <> | <> | ||||
| {archived | {archived | ||||
| ? <Tooltip selector={`list-switch-${id}`} content={t('datasetDocuments.list.action.enableWarning') as string} className='!font-semibold'> | |||||
| ? <Tooltip | |||||
| popupContent={t('datasetDocuments.list.action.enableWarning')} | |||||
| popupClassName='!font-semibold' | |||||
| needsDelay | |||||
| > | |||||
| <div> | <div> | ||||
| <Switch defaultValue={false} onChange={() => { }} disabled={true} size='md' /> | <Switch defaultValue={false} onChange={() => { }} disabled={true} size='md' /> | ||||
| </div> | </div> | ||||
| {!archived && enabled ? t('datasetDocuments.list.index.enable') : t('datasetDocuments.list.index.disable')} | {!archived && enabled ? t('datasetDocuments.list.index.enable') : t('datasetDocuments.list.index.disable')} | ||||
| </span> | </span> | ||||
| <Tooltip | <Tooltip | ||||
| selector={`detail-switch-${id}`} | |||||
| content={t('datasetDocuments.list.action.enableWarning') as string} | |||||
| className='!font-semibold' | |||||
| popupContent={t('datasetDocuments.list.action.enableWarning')} | |||||
| popupClassName='!font-semibold' | |||||
| needsDelay | |||||
| disabled={!archived} | disabled={!archived} | ||||
| > | > | ||||
| <div> | <div> | ||||
| } | } | ||||
| </span> | </span> | ||||
| <div className='group-hover:flex hidden'> | <div className='group-hover:flex hidden'> | ||||
| <TooltipPlus popupContent={t('datasetDocuments.list.table.rename')}> | |||||
| <Tooltip | |||||
| popupContent={t('datasetDocuments.list.table.rename')} | |||||
| > | |||||
| <div | <div | ||||
| className='p-1 rounded-md cursor-pointer hover:bg-black/5' | className='p-1 rounded-md cursor-pointer hover:bg-black/5' | ||||
| onClick={(e) => { | onClick={(e) => { | ||||
| > | > | ||||
| <Edit03 className='w-4 h-4 text-gray-500' /> | <Edit03 className='w-4 h-4 text-gray-500' /> | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import Button from '../../base/button' | import Button from '../../base/button' | ||||
| import Tag from '../../base/tag' | import Tag from '../../base/tag' | ||||
| import Tooltip from '../../base/tooltip' | |||||
| import { getIcon } from '../common/retrieval-method-info' | import { getIcon } from '../common/retrieval-method-info' | ||||
| import s from './style.module.css' | import s from './style.module.css' | ||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import type { HitTestingResponse } from '@/models/datasets' | import type { HitTestingResponse } from '@/models/datasets' | ||||
| import { hitTesting } from '@/service/datasets' | import { hitTesting } from '@/service/datasets' | ||||
| {t('datasetHitTesting.input.title')} | {t('datasetHitTesting.input.title')} | ||||
| </span> | </span> | ||||
| <Tooltip | <Tooltip | ||||
| selector={'change-retrieval-method'} | |||||
| htmlContent={t('dataset.retrieval.changeRetrievalMethod')} | |||||
| popupContent={t('dataset.retrieval.changeRetrievalMethod')} | |||||
| > | > | ||||
| <div | <div | ||||
| onClick={onClickRetrievalMethod} | onClick={onClickRetrievalMethod} | ||||
| {text?.length > 200 | {text?.length > 200 | ||||
| ? ( | ? ( | ||||
| <Tooltip | <Tooltip | ||||
| content={t('datasetHitTesting.input.countWarning') as string} | |||||
| selector="hit-testing-warning" | |||||
| popupContent={t('datasetHitTesting.input.countWarning')} | |||||
| > | > | ||||
| <div> | <div> | ||||
| <Tag color="red" className="!text-red-600"> | <Tag color="red" className="!text-red-600"> |
| 'use client' | 'use client' | ||||
| import React, { useEffect, useRef, useState } from 'react' | |||||
| import React, { useEffect, useState } from 'react' | |||||
| import copy from 'copy-to-clipboard' | import copy from 'copy-to-clipboard' | ||||
| import { t } from 'i18next' | import { t } from 'i18next' | ||||
| import s from './style.module.css' | import s from './style.module.css' | ||||
| import { randomString } from '@/utils' | |||||
| import Tooltip from '@/app/components/base/tooltip' | import Tooltip from '@/app/components/base/tooltip' | ||||
| type IInputCopyProps = { | type IInputCopyProps = { | ||||
| }: IInputCopyProps) => { | }: IInputCopyProps) => { | ||||
| const [isCopied, setIsCopied] = useState(false) | const [isCopied, setIsCopied] = useState(false) | ||||
| const selector = useRef(`input-tooltip-${randomString(4)}`) | |||||
| useEffect(() => { | useEffect(() => { | ||||
| if (isCopied) { | if (isCopied) { | ||||
| const timeout = setTimeout(() => { | const timeout = setTimeout(() => { | ||||
| <div className="flex items-center flex-grow h-5"> | <div className="flex items-center flex-grow h-5"> | ||||
| {children} | {children} | ||||
| <div className='flex-grow bg-gray-50 text-[13px] relative h-full'> | <div className='flex-grow bg-gray-50 text-[13px] relative h-full'> | ||||
| <Tooltip | |||||
| selector={selector.current} | |||||
| content={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`} | |||||
| className='z-10' | |||||
| > | |||||
| <div className='absolute top-0 left-0 w-full pl-2 pr-2 truncate cursor-pointer r-0' onClick={() => { | |||||
| copy(value) | |||||
| setIsCopied(true) | |||||
| }}>{value}</div> | |||||
| </Tooltip> | |||||
| <div className='absolute top-0 left-0 w-full pl-2 pr-2 truncate cursor-pointer r-0' onClick={() => { | |||||
| copy(value) | |||||
| setIsCopied(true) | |||||
| }}> | |||||
| <Tooltip | |||||
| popupContent={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`} | |||||
| position='bottom' | |||||
| > | |||||
| {value} | |||||
| </Tooltip> | |||||
| </div> | |||||
| </div> | </div> | ||||
| <div className="flex-shrink-0 h-4 bg-gray-200 border" /> | <div className="flex-shrink-0 h-4 bg-gray-200 border" /> | ||||
| <Tooltip | <Tooltip | ||||
| selector={selector.current} | |||||
| content={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`} | |||||
| className='z-10' | |||||
| popupContent={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`} | |||||
| position='bottom' | |||||
| > | > | ||||
| <div className="px-0.5 flex-shrink-0"> | <div className="px-0.5 flex-shrink-0"> | ||||
| <div className={`box-border w-[30px] h-[30px] flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer ${s.copyIcon} ${isCopied ? s.copied : ''}`} onClick={() => { | <div className={`box-border w-[30px] h-[30px] flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer ${s.copyIcon} ${isCopied ? s.copied : ''}`} onClick={() => { |
| <div className='flex-shrink-0 px-3 truncate w-[200px]'>{api.last_used_at ? formatTime(Number(api.last_used_at), t('appLog.dateTimeFormat') as string) : t('appApi.never')}</div> | <div className='flex-shrink-0 px-3 truncate w-[200px]'>{api.last_used_at ? formatTime(Number(api.last_used_at), t('appLog.dateTimeFormat') as string) : t('appApi.never')}</div> | ||||
| <div className='flex flex-grow px-3'> | <div className='flex flex-grow px-3'> | ||||
| <Tooltip | <Tooltip | ||||
| selector={`key-${api.token}`} | |||||
| content={copyValue === api.token ? `${t('appApi.copied')}` : `${t('appApi.copy')}`} | |||||
| className='z-10' | |||||
| popupContent={copyValue === api.token ? `${t('appApi.copied')}` : `${t('appApi.copy')}`} | |||||
| popupClassName='mr-1' | |||||
| > | > | ||||
| <div className={`flex items-center justify-center flex-shrink-0 w-6 h-6 mr-1 rounded-lg cursor-pointer hover:bg-gray-100 ${s.copyIcon} ${copyValue === api.token ? s.copied : ''}`} onClick={() => { | <div className={`flex items-center justify-center flex-shrink-0 w-6 h-6 mr-1 rounded-lg cursor-pointer hover:bg-gray-100 ${s.copyIcon} ${copyValue === api.token ? s.copied : ''}`} onClick={() => { | ||||
| // setIsCopied(true) | // setIsCopied(true) |
| import { CheckCircleIcon } from '@heroicons/react/24/solid' | import { CheckCircleIcon } from '@heroicons/react/24/solid' | ||||
| import { QuestionMarkCircleIcon, XMarkIcon } from '@heroicons/react/24/outline' | |||||
| import { XMarkIcon } from '@heroicons/react/24/outline' | |||||
| import { RiQuestionLine } from '@remixicon/react' | |||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { useMemo } from 'react' | import { useMemo } from 'react' | ||||
| import InvitationLink from './invitation-link' | import InvitationLink from './invitation-link' | ||||
| failedInvationResults.map(item => | failedInvationResults.map(item => | ||||
| <div key={item.email} className='flex justify-center border border-red-300 rounded-md px-1 bg-orange-50'> | <div key={item.email} className='flex justify-center border border-red-300 rounded-md px-1 bg-orange-50'> | ||||
| <Tooltip | <Tooltip | ||||
| selector={`invitation-tag-${item.email}`} | |||||
| htmlContent={item.message} | |||||
| popupContent={item.message} | |||||
| > | > | ||||
| <div className='flex justify-center items-center text-sm gap-1'> | <div className='flex justify-center items-center text-sm gap-1'> | ||||
| {item.email} | {item.email} | ||||
| <QuestionMarkCircleIcon className='w-4 h-4 text-red-300' /> | |||||
| <RiQuestionLine className='w-4 h-4 text-red-300' /> | |||||
| </div> | </div> | ||||
| </Tooltip> | </Tooltip> | ||||
| </div>, | </div>, |
| <div className="flex items-center flex-grow h-5"> | <div className="flex items-center flex-grow h-5"> | ||||
| <div className='flex-grow bg-gray-100 text-[13px] relative h-full'> | <div className='flex-grow bg-gray-100 text-[13px] relative h-full'> | ||||
| <Tooltip | <Tooltip | ||||
| selector={selector.current} | |||||
| content={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`} | |||||
| className='z-10' | |||||
| popupContent={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`} | |||||
| > | > | ||||
| <div className='absolute top-0 left-0 w-full pl-2 pr-2 truncate cursor-pointer r-0' onClick={copyHandle}>{value.url}</div> | <div className='absolute top-0 left-0 w-full pl-2 pr-2 truncate cursor-pointer r-0' onClick={copyHandle}>{value.url}</div> | ||||
| </Tooltip> | </Tooltip> | ||||
| </div> | </div> | ||||
| <div className="flex-shrink-0 h-4 bg-gray-200 border" /> | <div className="flex-shrink-0 h-4 bg-gray-200 border" /> | ||||
| <Tooltip | <Tooltip | ||||
| selector={selector.current} | |||||
| content={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`} | |||||
| className='z-10' | |||||
| popupContent={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`} | |||||
| > | > | ||||
| <div className="px-0.5 flex-shrink-0"> | <div className="px-0.5 flex-shrink-0"> | ||||
| <div className={`box-border w-[30px] h-[30px] flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer ${s.copyIcon} ${isCopied ? s.copied : ''}`} onClick={copyHandle}> | <div className={`box-border w-[30px] h-[30px] flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer ${s.copyIcon} ${isCopied ? s.copied : ''}`} onClick={copyHandle}> |
| import { Fragment, useState } from 'react' | import { Fragment, useState } from 'react' | ||||
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import { RiQuestionLine } from '@remixicon/react' | |||||
| import { ValidatingTip } from '../../key-validator/ValidateStatus' | import { ValidatingTip } from '../../key-validator/ValidateStatus' | ||||
| import type { | import type { | ||||
| CredentialFormSchema, | CredentialFormSchema, | ||||
| import Input from './Input' | import Input from './Input' | ||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import { SimpleSelect } from '@/app/components/base/select' | import { SimpleSelect } from '@/app/components/base/select' | ||||
| import Tooltip from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import Radio from '@/app/components/base/radio' | import Radio from '@/app/components/base/radio' | ||||
| type FormProps = { | type FormProps = { | ||||
| className?: string | className?: string |
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import { useEffect, useRef, useState } from 'react' | import { useEffect, useRef, useState } from 'react' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import type { ModelParameterRule } from '../declarations' | import type { ModelParameterRule } from '../declarations' | ||||
| import { useLanguage } from '../hooks' | import { useLanguage } from '../hooks' | ||||
| import { isNullOrUndefined } from '../utils' | import { isNullOrUndefined } from '../utils' | ||||
| { | { | ||||
| parameterRule.help && ( | parameterRule.help && ( | ||||
| <Tooltip | <Tooltip | ||||
| selector={`model-parameter-rule-${parameterRule.name}`} | |||||
| htmlContent={( | |||||
| popupContent={( | |||||
| <div className='w-[200px] whitespace-pre-wrap'>{parameterRule.help[language] || parameterRule.help.en_US}</div> | <div className='w-[200px] whitespace-pre-wrap'>{parameterRule.help[language] || parameterRule.help.en_US}</div> | ||||
| )} | )} | ||||
| > | |||||
| <RiQuestionLine className='mr-1.5 w-3.5 h-3.5 text-gray-400' /> | |||||
| </Tooltip> | |||||
| popupClassName='mr-1' | |||||
| triggerClassName='mr-1 w-4 h-4 shrink-0' | |||||
| /> | |||||
| ) | ) | ||||
| } | } | ||||
| { | { | ||||
| !parameterRule.required && parameterRule.name !== 'stop' && ( | !parameterRule.required && parameterRule.name !== 'stop' && ( | ||||
| <Switch | <Switch | ||||
| className='mr-1' | |||||
| defaultValue={!isNullOrUndefined(value)} | defaultValue={!isNullOrUndefined(value)} | ||||
| onChange={handleSwitch} | onChange={handleSwitch} | ||||
| size='md' | size='md' |
| import { useProviderContext } from '@/context/provider-context' | import { useProviderContext } from '@/context/provider-context' | ||||
| import { SlidersH } from '@/app/components/base/icons/src/vender/line/mediaAndDevices' | import { SlidersH } from '@/app/components/base/icons/src/vender/line/mediaAndDevices' | ||||
| import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback' | import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| export type TriggerProps = { | export type TriggerProps = { | ||||
| open?: boolean | open?: boolean | ||||
| { | { | ||||
| disabled | disabled | ||||
| ? ( | ? ( | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={ | popupContent={ | ||||
| hasDeprecated | hasDeprecated | ||||
| ? t('common.modelProvider.deprecated') | ? t('common.modelProvider.deprecated') | ||||
| } | } | ||||
| > | > | ||||
| <AlertTriangle className='w-4 h-4 text-[#F79009]' /> | <AlertTriangle className='w-4 h-4 text-[#F79009]' /> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| ) | ) | ||||
| : ( | : ( | ||||
| <SlidersH className={cn(!isInWorkflow ? 'text-indigo-600' : 'text-gray-500', 'shrink-0 w-4 h-4')} /> | <SlidersH className={cn(!isInWorkflow ? 'text-indigo-600' : 'text-gray-500', 'shrink-0 w-4 h-4')} /> |
| import ModelIcon from '../model-icon' | import ModelIcon from '../model-icon' | ||||
| import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback' | import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback' | ||||
| import { useProviderContext } from '@/context/provider-context' | import { useProviderContext } from '@/context/provider-context' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| type ModelTriggerProps = { | type ModelTriggerProps = { | ||||
| modelName: string | modelName: string | ||||
| {modelName} | {modelName} | ||||
| </div> | </div> | ||||
| <div className='shrink-0 flex items-center justify-center w-4 h-4'> | <div className='shrink-0 flex items-center justify-center w-4 h-4'> | ||||
| <TooltipPlus popupContent={t('common.modelProvider.deprecated')}> | |||||
| <Tooltip popupContent={t('common.modelProvider.deprecated')}> | |||||
| <AlertTriangle className='w-4 h-4 text-[#F79009]' /> | <AlertTriangle className='w-4 h-4 text-[#F79009]' /> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| ) | ) |
| // MagicWand, | // MagicWand, | ||||
| // Robot, | // Robot, | ||||
| } from '@/app/components/base/icons/src/vender/solid/mediaAndDevices' | } from '@/app/components/base/icons/src/vender/solid/mediaAndDevices' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| type FeatureIconProps = { | type FeatureIconProps = { | ||||
| feature: ModelFeatureEnum | feature: ModelFeatureEnum | ||||
| // if (feature === ModelFeatureEnum.agentThought) { | // if (feature === ModelFeatureEnum.agentThought) { | ||||
| // return ( | // return ( | ||||
| // <TooltipPlus | |||||
| // <Tooltip | |||||
| // popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.agentThought })} | // popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.agentThought })} | ||||
| // > | // > | ||||
| // <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}> | // <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}> | ||||
| // <Robot className='w-3 h-3' /> | // <Robot className='w-3 h-3' /> | ||||
| // </ModelBadge> | // </ModelBadge> | ||||
| // </TooltipPlus> | |||||
| // </Tooltip> | |||||
| // ) | // ) | ||||
| // } | // } | ||||
| // if (feature === ModelFeatureEnum.toolCall) { | // if (feature === ModelFeatureEnum.toolCall) { | ||||
| // return ( | // return ( | ||||
| // <TooltipPlus | |||||
| // <Tooltip | |||||
| // popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.toolCall })} | // popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.toolCall })} | ||||
| // > | // > | ||||
| // <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}> | // <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}> | ||||
| // <MagicWand className='w-3 h-3' /> | // <MagicWand className='w-3 h-3' /> | ||||
| // </ModelBadge> | // </ModelBadge> | ||||
| // </TooltipPlus> | |||||
| // </Tooltip> | |||||
| // ) | // ) | ||||
| // } | // } | ||||
| // if (feature === ModelFeatureEnum.multiToolCall) { | // if (feature === ModelFeatureEnum.multiToolCall) { | ||||
| // return ( | // return ( | ||||
| // <TooltipPlus | |||||
| // <Tooltip | |||||
| // popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.multiToolCall })} | // popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.multiToolCall })} | ||||
| // > | // > | ||||
| // <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}> | // <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}> | ||||
| // <MagicBox className='w-3 h-3' /> | // <MagicBox className='w-3 h-3' /> | ||||
| // </ModelBadge> | // </ModelBadge> | ||||
| // </TooltipPlus> | |||||
| // </Tooltip> | |||||
| // ) | // ) | ||||
| // } | // } | ||||
| if (feature === ModelFeatureEnum.vision) { | if (feature === ModelFeatureEnum.vision) { | ||||
| return ( | return ( | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.vision })} | popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.vision })} | ||||
| > | > | ||||
| <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}> | |||||
| <MagicEyes className='w-3 h-3' /> | |||||
| </ModelBadge> | |||||
| </TooltipPlus> | |||||
| <div className='inline-block cursor-help'> | |||||
| <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}> | |||||
| <MagicEyes className='w-3 h-3' /> | |||||
| </ModelBadge> | |||||
| </div> | |||||
| </Tooltip> | |||||
| ) | ) | ||||
| } | } | ||||
| import ModelIcon from '../model-icon' | import ModelIcon from '../model-icon' | ||||
| import ModelName from '../model-name' | import ModelName from '../model-name' | ||||
| import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback' | import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| type ModelTriggerProps = { | type ModelTriggerProps = { | ||||
| open: boolean | open: boolean | ||||
| { | { | ||||
| model.status !== ModelStatusEnum.active | model.status !== ModelStatusEnum.active | ||||
| ? ( | ? ( | ||||
| <TooltipPlus popupContent={MODEL_STATUS_TEXT[model.status][language]}> | |||||
| <Tooltip popupContent={MODEL_STATUS_TEXT[model.status][language]}> | |||||
| <AlertTriangle className='w-4 h-4 text-[#F79009]' /> | <AlertTriangle className='w-4 h-4 text-[#F79009]' /> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| ) | ) | ||||
| : ( | : ( | ||||
| <RiArrowDownSLine | <RiArrowDownSLine |
| { | { | ||||
| model.models.map(modelItem => ( | model.models.map(modelItem => ( | ||||
| <Tooltip | <Tooltip | ||||
| selector={`${modelItem.model}-${modelItem.status}`} | |||||
| key={modelItem.model} | key={modelItem.model} | ||||
| content={modelItem.status !== ModelStatusEnum.active ? MODEL_STATUS_TEXT[modelItem.status][language] : undefined} | |||||
| popupContent={modelItem.status !== ModelStatusEnum.active ? MODEL_STATUS_TEXT[modelItem.status][language] : undefined} | |||||
| position='right' | position='right' | ||||
| > | > | ||||
| <div | <div |
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { useLatest } from 'ahooks' | import { useLatest } from 'ahooks' | ||||
| import SimplePieChart from '@/app/components/base/simple-pie-chart' | import SimplePieChart from '@/app/components/base/simple-pie-chart' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| export type CooldownTimerProps = { | export type CooldownTimerProps = { | ||||
| secondsRemaining?: number | secondsRemaining?: number | ||||
| return displayTime | return displayTime | ||||
| ? ( | ? ( | ||||
| <TooltipPlus popupContent={t('common.modelProvider.apiKeyRateLimit', { seconds: displayTime })}> | |||||
| <Tooltip popupContent={t('common.modelProvider.apiKeyRateLimit', { seconds: displayTime })}> | |||||
| <SimplePieChart percentage={Math.round(displayTime / 60 * 100)} className='w-3 h-3' /> | <SimplePieChart percentage={Math.round(displayTime / 60 * 100)} className='w-3 h-3' /> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| ) | ) | ||||
| : null | : null | ||||
| } | } |
| import { Balance } from '@/app/components/base/icons/src/vender/line/financeAndECommerce' | import { Balance } from '@/app/components/base/icons/src/vender/line/financeAndECommerce' | ||||
| import { Settings01 } from '@/app/components/base/icons/src/vender/line/general' | import { Settings01 } from '@/app/components/base/icons/src/vender/line/general' | ||||
| import Switch from '@/app/components/base/switch' | import Switch from '@/app/components/base/switch' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import { useProviderContext, useProviderContextSelector } from '@/context/provider-context' | import { useProviderContext, useProviderContextSelector } from '@/context/provider-context' | ||||
| import { disableModel, enableModel } from '@/service/common' | import { disableModel, enableModel } from '@/service/common' | ||||
| import { Plan } from '@/app/components/billing/type' | import { Plan } from '@/app/components/billing/type' | ||||
| { | { | ||||
| model.deprecated | model.deprecated | ||||
| ? ( | ? ( | ||||
| <TooltipPlus popupContent={<span className='font-semibold'>{t('common.modelProvider.modelHasBeenDeprecated')}</span>} offset={{ mainAxis: 4 }}> | |||||
| <Tooltip | |||||
| popupContent={ | |||||
| <span className='font-semibold'>{t('common.modelProvider.modelHasBeenDeprecated')}</span>} offset={{ mainAxis: 4 } | |||||
| } | |||||
| needsDelay | |||||
| > | |||||
| <Switch defaultValue={false} disabled size='md' /> | <Switch defaultValue={false} disabled size='md' /> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| ) | ) | ||||
| : (isCurrentWorkspaceManager && ( | : (isCurrentWorkspaceManager && ( | ||||
| <Switch | <Switch |
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { | import { | ||||
| RiDeleteBinLine, | RiDeleteBinLine, | ||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | } from '@remixicon/react' | ||||
| import type { ConfigurationMethodEnum, CustomConfigurationModelFixedFields, ModelLoadBalancingConfig, ModelLoadBalancingConfigEntry, ModelProvider } from '../declarations' | import type { ConfigurationMethodEnum, CustomConfigurationModelFixedFields, ModelLoadBalancingConfig, ModelLoadBalancingConfigEntry, ModelProvider } from '../declarations' | ||||
| import Indicator from '../../../indicator' | import Indicator from '../../../indicator' | ||||
| import CooldownTimer from './cooldown-timer' | import CooldownTimer from './cooldown-timer' | ||||
| import classNames from '@/utils/classnames' | import classNames from '@/utils/classnames' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import Switch from '@/app/components/base/switch' | import Switch from '@/app/components/base/switch' | ||||
| import { Balance } from '@/app/components/base/icons/src/vender/line/financeAndECommerce' | import { Balance } from '@/app/components/base/icons/src/vender/line/financeAndECommerce' | ||||
| import { Edit02, Plus02 } from '@/app/components/base/icons/src/vender/line/general' | import { Edit02, Plus02 } from '@/app/components/base/icons/src/vender/line/general' | ||||
| <div className='grow'> | <div className='grow'> | ||||
| <div className='flex items-center gap-1 text-sm'> | <div className='flex items-center gap-1 text-sm'> | ||||
| {t('common.modelProvider.loadBalancing')} | {t('common.modelProvider.loadBalancing')} | ||||
| <TooltipPlus popupContent={t('common.modelProvider.loadBalancingInfo')} popupClassName='max-w-[300px]'> | |||||
| <RiQuestionLine className='w-3 h-3 text-gray-400' /> | |||||
| </TooltipPlus> | |||||
| <Tooltip | |||||
| popupContent={t('common.modelProvider.loadBalancingInfo')} | |||||
| popupClassName='max-w-[300px]' | |||||
| triggerClassName='w-3 h-3' | |||||
| /> | |||||
| </div> | </div> | ||||
| <div className='text-xs text-gray-500'>{t('common.modelProvider.loadBalancingDescription')}</div> | <div className='text-xs text-gray-500'>{t('common.modelProvider.loadBalancingDescription')}</div> | ||||
| </div> | </div> | ||||
| <CooldownTimer secondsRemaining={config.ttl} onFinish={() => clearCountdown(index)} /> | <CooldownTimer secondsRemaining={config.ttl} onFinish={() => clearCountdown(index)} /> | ||||
| ) | ) | ||||
| : ( | : ( | ||||
| <TooltipPlus popupContent={t('common.modelProvider.apiKeyStatusNormal')}> | |||||
| <Tooltip popupContent={t('common.modelProvider.apiKeyStatusNormal')}> | |||||
| <Indicator color='green' /> | <Indicator color='green' /> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| )} | )} | ||||
| </div> | </div> | ||||
| <div className='text-[13px] mr-1'> | <div className='text-[13px] mr-1'> |
| return ( | return ( | ||||
| <Tooltip | <Tooltip | ||||
| selector='provider-quota-credential-priority-using' | |||||
| content={t('common.modelProvider.priorityUsing') || ''} | |||||
| popupContent={t('common.modelProvider.priorityUsing') || ''} | |||||
| > | > | ||||
| <div className='absolute -right-[5px] -top-[5px] bg-indigo-50 rounded-[5px] border-[0.5px] border-indigo-100 cursor-pointer'> | <div className='absolute -right-[5px] -top-[5px] bg-indigo-50 rounded-[5px] border-[0.5px] border-indigo-100 cursor-pointer'> | ||||
| <ChevronDownDouble className='rotate-180 w-3 h-3 text-indigo-600' /> | <ChevronDownDouble className='rotate-180 w-3 h-3 text-indigo-600' /> |
| MODEL_PROVIDER_QUOTA_GET_PAID, | MODEL_PROVIDER_QUOTA_GET_PAID, | ||||
| } from '../utils' | } from '../utils' | ||||
| import PriorityUseTip from './priority-use-tip' | import PriorityUseTip from './priority-use-tip' | ||||
| import { InfoCircle } from '@/app/components/base/icons/src/vender/line/general' | |||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import { formatNumber } from '@/utils/format' | import { formatNumber } from '@/utils/format' | ||||
| type QuotaPanelProps = { | type QuotaPanelProps = { | ||||
| <div className='group relative shrink-0 min-w-[112px] px-3 py-2 rounded-lg bg-white/[0.3] border-[0.5px] border-black/5'> | <div className='group relative shrink-0 min-w-[112px] px-3 py-2 rounded-lg bg-white/[0.3] border-[0.5px] border-black/5'> | ||||
| <div className='flex items-center mb-2 h-4 text-xs font-medium text-gray-500'> | <div className='flex items-center mb-2 h-4 text-xs font-medium text-gray-500'> | ||||
| {t('common.modelProvider.quota')} | {t('common.modelProvider.quota')} | ||||
| <TooltipPlus popupContent={ | |||||
| <Tooltip popupContent={ | |||||
| openaiOrAnthropic | openaiOrAnthropic | ||||
| ? t('common.modelProvider.card.tip') | ? t('common.modelProvider.card.tip') | ||||
| : t('common.modelProvider.quotaTip') | : t('common.modelProvider.quotaTip') | ||||
| }> | |||||
| <InfoCircle className='ml-0.5 w-3 h-3 text-gray-400' /> | |||||
| </TooltipPlus> | |||||
| } | |||||
| /> | |||||
| </div> | </div> | ||||
| { | { | ||||
| currentQuota && ( | currentQuota && ( |
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import { useState } from 'react' | import { useState } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import ModelSelector from '../model-selector' | import ModelSelector from '../model-selector' | ||||
| import { | import { | ||||
| useModelList, | useModelList, | ||||
| <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'> | <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'> | ||||
| {t('common.modelProvider.systemReasoningModel.key')} | {t('common.modelProvider.systemReasoningModel.key')} | ||||
| <Tooltip | <Tooltip | ||||
| selector='model-page-system-reasoning-model-tip' | |||||
| htmlContent={ | |||||
| <div className='w-[261px] text-gray-500'>{t('common.modelProvider.systemReasoningModel.tip')}</div> | |||||
| popupContent={ | |||||
| <div className='w-[261px] text-gray-500'> | |||||
| {t('common.modelProvider.systemReasoningModel.tip')} | |||||
| </div> | |||||
| } | } | ||||
| > | |||||
| <RiQuestionLine className='ml-0.5 w-[14px] h-[14px] text-gray-400' /> | |||||
| </Tooltip> | |||||
| triggerClassName='ml-0.5' | |||||
| /> | |||||
| </div> | </div> | ||||
| <div> | <div> | ||||
| <ModelSelector | <ModelSelector | ||||
| <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'> | <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'> | ||||
| {t('common.modelProvider.embeddingModel.key')} | {t('common.modelProvider.embeddingModel.key')} | ||||
| <Tooltip | <Tooltip | ||||
| selector='model-page-system-embedding-model-tip' | |||||
| htmlContent={ | |||||
| <div className='w-[261px] text-gray-500'>{t('common.modelProvider.embeddingModel.tip')}</div> | |||||
| popupContent={ | |||||
| <div className='w-[261px] text-gray-500'> | |||||
| {t('common.modelProvider.embeddingModel.tip')} | |||||
| </div> | |||||
| } | } | ||||
| > | |||||
| <RiQuestionLine className='ml-0.5 w-[14px] h-[14px] text-gray-400' /> | |||||
| </Tooltip> | |||||
| needsDelay={false} | |||||
| triggerClassName='ml-0.5' | |||||
| /> | |||||
| </div> | </div> | ||||
| <div> | <div> | ||||
| <ModelSelector | <ModelSelector | ||||
| <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'> | <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'> | ||||
| {t('common.modelProvider.rerankModel.key')} | {t('common.modelProvider.rerankModel.key')} | ||||
| <Tooltip | <Tooltip | ||||
| selector='model-page-system-rerankModel-model-tip' | |||||
| htmlContent={ | |||||
| <div className='w-[261px] text-gray-500'>{t('common.modelProvider.rerankModel.tip')}</div> | |||||
| popupContent={ | |||||
| <div className='w-[261px] text-gray-500'> | |||||
| {t('common.modelProvider.rerankModel.tip')} | |||||
| </div> | |||||
| } | } | ||||
| > | |||||
| <RiQuestionLine className='ml-0.5 w-[14px] h-[14px] text-gray-400' /> | |||||
| </Tooltip> | |||||
| needsDelay={false} | |||||
| triggerClassName='ml-0.5' | |||||
| /> | |||||
| </div> | </div> | ||||
| <div> | <div> | ||||
| <ModelSelector | <ModelSelector | ||||
| <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'> | <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'> | ||||
| {t('common.modelProvider.speechToTextModel.key')} | {t('common.modelProvider.speechToTextModel.key')} | ||||
| <Tooltip | <Tooltip | ||||
| selector='model-page-system-speechToText-model-tip' | |||||
| htmlContent={ | |||||
| <div className='w-[261px] text-gray-500'>{t('common.modelProvider.speechToTextModel.tip')}</div> | |||||
| popupContent={ | |||||
| <div className='w-[261px] text-gray-500'> | |||||
| {t('common.modelProvider.speechToTextModel.tip')} | |||||
| </div> | |||||
| } | } | ||||
| > | |||||
| <RiQuestionLine className='ml-0.5 w-[14px] h-[14px] text-gray-400' /> | |||||
| </Tooltip> | |||||
| needsDelay={false} | |||||
| triggerClassName='ml-0.5' | |||||
| /> | |||||
| </div> | </div> | ||||
| <div> | <div> | ||||
| <ModelSelector | <ModelSelector | ||||
| <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'> | <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'> | ||||
| {t('common.modelProvider.ttsModel.key')} | {t('common.modelProvider.ttsModel.key')} | ||||
| <Tooltip | <Tooltip | ||||
| selector='model-page-system-tts-model-tip' | |||||
| htmlContent={ | |||||
| <div className='w-[261px] text-gray-500'>{t('common.modelProvider.ttsModel.tip')}</div> | |||||
| popupContent={ | |||||
| <div className='w-[261px] text-gray-500'> | |||||
| {t('common.modelProvider.ttsModel.tip')} | |||||
| </div> | |||||
| } | } | ||||
| > | |||||
| <RiQuestionLine className='ml-0.5 w-[14px] h-[14px] text-gray-400' /> | |||||
| </Tooltip> | |||||
| triggerClassName='ml-0.5' | |||||
| /> | |||||
| </div> | </div> | ||||
| <div> | <div> | ||||
| <ModelSelector | <ModelSelector |
| {showFeedback && feedback.rating && feedback.rating === 'like' && ( | {showFeedback && feedback.rating && feedback.rating === 'like' && ( | ||||
| <Tooltip | <Tooltip | ||||
| selector="undo-feedback-like" | |||||
| content="Undo Great Rating" | |||||
| popupContent="Undo Great Rating" | |||||
| > | > | ||||
| <div | <div | ||||
| onClick={() => { | onClick={() => { | ||||
| {showFeedback && feedback.rating && feedback.rating === 'dislike' && ( | {showFeedback && feedback.rating && feedback.rating === 'dislike' && ( | ||||
| <Tooltip | <Tooltip | ||||
| selector="undo-feedback-dislike" | |||||
| content="Undo Undesirable Response" | |||||
| popupContent="Undo Undesirable Response" | |||||
| > | > | ||||
| <div | <div | ||||
| onClick={() => { | onClick={() => { | ||||
| {showFeedback && !feedback.rating && ( | {showFeedback && !feedback.rating && ( | ||||
| <div className='flex rounded-lg border border-gray-200 p-[1px] space-x-1'> | <div className='flex rounded-lg border border-gray-200 p-[1px] space-x-1'> | ||||
| <Tooltip | <Tooltip | ||||
| selector="feedback-like" | |||||
| content="Great Rating" | |||||
| popupContent="Great Rating" | |||||
| needsDelay={false} | |||||
| > | > | ||||
| <div | <div | ||||
| onClick={() => { | onClick={() => { | ||||
| </div> | </div> | ||||
| </Tooltip> | </Tooltip> | ||||
| <Tooltip | <Tooltip | ||||
| selector="feedback-dislike" | |||||
| content="Undesirable Response" | |||||
| popupContent="Undesirable Response" | |||||
| needsDelay={false} | |||||
| > | > | ||||
| <div | <div | ||||
| onClick={() => { | onClick={() => { |
| return ( | return ( | ||||
| <Tooltip | <Tooltip | ||||
| key={tool.name} | key={tool.name} | ||||
| selector={`workflow-block-tool-${tool.name}`} | |||||
| position='bottom' | position='bottom' | ||||
| className='!p-0 !px-3 !py-2.5 !w-[210px] !leading-[18px] !text-xs !text-gray-700 !border-[0.5px] !border-black/5 !bg-transparent !rounded-xl !shadow-lg translate-x-[108px]' | |||||
| htmlContent={( | |||||
| popupClassName='!p-0 !px-3 !py-2.5 !w-[210px] !leading-[18px] !text-xs !text-gray-700 !border-[0.5px] !border-black/5 !bg-transparent !rounded-xl !shadow-lg translate-x-[108px]' | |||||
| popupContent={( | |||||
| <div> | <div> | ||||
| <BlockIcon | <BlockIcon | ||||
| size='md' | size='md' | ||||
| )} | )} | ||||
| </div> | </div> | ||||
| )} | )} | ||||
| noArrow | |||||
| needsDelay | |||||
| > | > | ||||
| <div className='group/item flex items-center w-full pl-3 pr-1 h-8 rounded-lg hover:bg-gray-50 cursor-pointer'> | <div className='group/item flex items-center w-full pl-3 pr-1 h-8 rounded-lg hover:bg-gray-50 cursor-pointer'> | ||||
| <BlockIcon | <BlockIcon |
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import React from 'react' | import React from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import Tooltip from '../../base/tooltip' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import type { Credential } from '@/app/components/tools/types' | import type { Credential } from '@/app/components/tools/types' | ||||
| import Drawer from '@/app/components/base/drawer-plus' | import Drawer from '@/app/components/base/drawer-plus' | ||||
| <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'> | <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'> | ||||
| {t('tools.createTool.authMethod.key')} | {t('tools.createTool.authMethod.key')} | ||||
| <Tooltip | <Tooltip | ||||
| selector='model-page-system-reasoning-model-tip' | |||||
| htmlContent={ | |||||
| popupContent={ | |||||
| <div className='w-[261px] text-gray-500'> | <div className='w-[261px] text-gray-500'> | ||||
| {t('tools.createTool.authMethod.keyTooltip')} | {t('tools.createTool.authMethod.keyTooltip')} | ||||
| </div> | </div> | ||||
| } | } | ||||
| > | |||||
| <RiQuestionLine className='ml-0.5 w-[14px] h-[14px] text-gray-400' /> | |||||
| </Tooltip> | |||||
| triggerClassName='ml-0.5' | |||||
| /> | |||||
| </div> | </div> | ||||
| <input | <input | ||||
| value={tempCredential.api_key_header} | value={tempCredential.api_key_header} |
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import React, { useState } from 'react' | import React, { useState } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import produce from 'immer' | import produce from 'immer' | ||||
| import type { Emoji, WorkflowToolProviderParameter, WorkflowToolProviderRequest } from '../types' | import type { Emoji, WorkflowToolProviderParameter, WorkflowToolProviderRequest } from '../types' | ||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| <div className='flex items-center py-2 leading-5 text-sm font-medium text-gray-900'> | <div className='flex items-center py-2 leading-5 text-sm font-medium text-gray-900'> | ||||
| {t('tools.createTool.nameForToolCall')} <span className='ml-1 text-red-500'>*</span> | {t('tools.createTool.nameForToolCall')} <span className='ml-1 text-red-500'>*</span> | ||||
| <Tooltip | <Tooltip | ||||
| htmlContent={ | |||||
| popupContent={ | |||||
| <div className='w-[180px]'> | <div className='w-[180px]'> | ||||
| {t('tools.createTool.nameForToolCallPlaceHolder')} | {t('tools.createTool.nameForToolCallPlaceHolder')} | ||||
| </div> | </div> | ||||
| } | } | ||||
| selector='workflow-tool-modal-tooltip' | |||||
| > | |||||
| <RiQuestionLine className='ml-2 w-[14px] h-[14px] text-gray-400' /> | |||||
| </Tooltip> | |||||
| /> | |||||
| </div> | </div> | ||||
| <input | <input | ||||
| type='text' | type='text' |
| list.map(block => ( | list.map(block => ( | ||||
| <Tooltip | <Tooltip | ||||
| key={block.type} | key={block.type} | ||||
| selector={`workflow-block-${block.type}`} | |||||
| position='right' | position='right' | ||||
| className='!p-0 !px-3 !py-2.5 !w-[200px] !leading-[18px] !text-xs !text-gray-700 !border-[0.5px] !border-black/5 !rounded-xl !shadow-lg' | |||||
| htmlContent={( | |||||
| popupClassName='!p-0 !px-3 !py-2.5 !w-[200px] !leading-[18px] !text-xs !text-gray-700 !border-[0.5px] !border-black/5 !rounded-xl !shadow-lg' | |||||
| popupContent={( | |||||
| <div> | <div> | ||||
| <BlockIcon | <BlockIcon | ||||
| size='md' | size='md' | ||||
| <div className='text-xs text-gray-700 leading-[18px]'>{nodesExtraData[block.type].about}</div> | <div className='text-xs text-gray-700 leading-[18px]'>{nodesExtraData[block.type].about}</div> | ||||
| </div> | </div> | ||||
| )} | )} | ||||
| noArrow | |||||
| > | > | ||||
| <div | <div | ||||
| key={block.type} | key={block.type} |
| list.map(tool => ( | list.map(tool => ( | ||||
| <Tooltip | <Tooltip | ||||
| key={tool.name} | key={tool.name} | ||||
| selector={`workflow-block-tool-${tool.name}`} | |||||
| position='right' | position='right' | ||||
| className='!p-0 !px-3 !py-2.5 !w-[200px] !leading-[18px] !text-xs !text-gray-700 !border-[0.5px] !border-black/5 !rounded-xl !shadow-lg' | |||||
| htmlContent={( | |||||
| popupClassName='!p-0 !px-3 !py-2.5 !w-[200px] !leading-[18px] !text-xs !text-gray-700 !border-[0.5px] !border-black/5 !rounded-xl !shadow-lg' | |||||
| popupContent={( | |||||
| <div> | <div> | ||||
| <BlockIcon | <BlockIcon | ||||
| size='md' | size='md' | ||||
| <div className='text-xs text-gray-700 leading-[18px]'>{tool.description[language]}</div> | <div className='text-xs text-gray-700 leading-[18px]'>{tool.description[language]}</div> | ||||
| </div> | </div> | ||||
| )} | )} | ||||
| noArrow | |||||
| > | > | ||||
| <div | <div | ||||
| className='flex items-center px-3 w-full h-8 rounded-lg hover:bg-gray-50 cursor-pointer' | className='flex items-center px-3 w-full h-8 rounded-lg hover:bg-gray-50 cursor-pointer' | ||||
| type={BlockEnum.Tool} | type={BlockEnum.Tool} | ||||
| toolIcon={toolWithProvider.icon} | toolIcon={toolWithProvider.icon} | ||||
| /> | /> | ||||
| <div className='text-sm text-gray-900 truncate'>{tool.label[language]}</div> | |||||
| <div className='text-sm text-gray-900 flex-1 min-w-0 truncate'>{tool.label[language]}</div> | |||||
| </div> | </div> | ||||
| </Tooltip> | </Tooltip> | ||||
| )) | )) |
| PortalToFollowElemContent, | PortalToFollowElemContent, | ||||
| PortalToFollowElemTrigger, | PortalToFollowElemTrigger, | ||||
| } from '@/app/components/base/portal-to-follow-elem' | } from '@/app/components/base/portal-to-follow-elem' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import { useStore as useAppStore } from '@/app/components/app/store' | import { useStore as useAppStore } from '@/app/components/app/store' | ||||
| import { | import { | ||||
| ClockPlay, | ClockPlay, | ||||
| } | } | ||||
| { | { | ||||
| !withText && ( | !withText && ( | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={t('workflow.common.viewRunHistory')} | popupContent={t('workflow.common.viewRunHistory')} | ||||
| > | > | ||||
| <div | <div | ||||
| > | > | ||||
| <ClockPlay className={cn('w-4 h-4 group-hover:text-components-button-secondary-accent-text', open ? 'text-components-button-secondary-accent-text' : 'text-components-button-ghost-text')} /> | <ClockPlay className={cn('w-4 h-4 group-hover:text-components-button-secondary-accent-text', open ? 'text-components-button-secondary-accent-text' : 'text-components-button-ghost-text')} /> | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| ) | ) | ||||
| } | } | ||||
| </PortalToFollowElemTrigger> | </PortalToFollowElemTrigger> |
| import React from 'react' | import React from 'react' | ||||
| import { | import { | ||||
| RiArrowDownSLine, | RiArrowDownSLine, | ||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | } from '@remixicon/react' | ||||
| import { useBoolean } from 'ahooks' | import { useBoolean } from 'ahooks' | ||||
| import type { DefaultTFuncReturn } from 'i18next' | import type { DefaultTFuncReturn } from 'i18next' | ||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| type Props = { | type Props = { | ||||
| className?: string | className?: string | ||||
| <div className='flex items-center h-6'> | <div className='flex items-center h-6'> | ||||
| <div className='system-sm-semibold-uppercase text-text-secondary'>{title}</div> | <div className='system-sm-semibold-uppercase text-text-secondary'>{title}</div> | ||||
| {tooltip && ( | {tooltip && ( | ||||
| <TooltipPlus popupContent={ | |||||
| <div className='w-[120px]'> | |||||
| {tooltip} | |||||
| </div>}> | |||||
| <RiQuestionLine className='w-3.5 h-3.5 ml-0.5 text-text-quaternary' /> | |||||
| </TooltipPlus> | |||||
| <Tooltip | |||||
| popupContent={tooltip} | |||||
| popupClassName='ml-1' | |||||
| triggerClassName='w-4 h-4 ml-1' | |||||
| /> | |||||
| )} | )} | ||||
| </div> | </div> |
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { RiBookOpenLine } from '@remixicon/react' | import { RiBookOpenLine } from '@remixicon/react' | ||||
| import { useNodeHelpLink } from '../hooks/use-node-help-link' | import { useNodeHelpLink } from '../hooks/use-node-help-link' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import TooltipPlus from '@/app/components/base/tooltip' | |||||
| import type { BlockEnum } from '@/app/components/workflow/types' | import type { BlockEnum } from '@/app/components/workflow/types' | ||||
| type HelpLinkProps = { | type HelpLinkProps = { | ||||
| const link = useNodeHelpLink(nodeType) | const link = useNodeHelpLink(nodeType) | ||||
| return ( | return ( | ||||
| <TooltipPlus popupContent={t('common.userProfile.helpCenter')}> | |||||
| <TooltipPlus | |||||
| popupContent={t('common.userProfile.helpCenter')} | |||||
| > | |||||
| <a | <a | ||||
| href={link} | href={link} | ||||
| target='_blank' | target='_blank' |
| import { BlockEnum } from '@/app/components/workflow/types' | import { BlockEnum } from '@/app/components/workflow/types' | ||||
| import PromptEditor from '@/app/components/base/prompt-editor' | import PromptEditor from '@/app/components/base/prompt-editor' | ||||
| import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' | import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| type Props = { | type Props = { | ||||
| instanceId?: string | instanceId?: string | ||||
| {readOnly && <div className='absolute inset-0 z-10'></div>} | {readOnly && <div className='absolute inset-0 z-10'></div>} | ||||
| {isFocus && ( | {isFocus && ( | ||||
| <div className={cn('absolute z-10', insertVarTipToLeft ? 'top-1.5 left-[-12px]' : ' top-[-9px] right-1')}> | <div className={cn('absolute z-10', insertVarTipToLeft ? 'top-1.5 left-[-12px]' : ' top-[-9px] right-1')}> | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={`${t('workflow.common.insertVarTip')}`} | popupContent={`${t('workflow.common.insertVarTip')}`} | ||||
| > | > | ||||
| <div className='p-0.5 rounded-[5px] shadow-lg cursor-pointer bg-white hover:bg-gray-100 border-[0.5px] border-black/5'> | <div className='p-0.5 rounded-[5px] shadow-lg cursor-pointer bg-white hover:bg-gray-100 border-[0.5px] border-black/5'> | ||||
| <Variable02 className='w-3.5 h-3.5 text-components-button-secondary-accent-text' /> | <Variable02 className='w-3.5 h-3.5 text-components-button-secondary-accent-text' /> | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| </div> | </div> | ||||
| )} | )} | ||||
| </> | </> |
| import { | import { | ||||
| Stop, | Stop, | ||||
| } from '@/app/components/base/icons/src/vender/line/mediaAndDevices' | } from '@/app/components/base/icons/src/vender/line/mediaAndDevices' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| type NodeControlProps = Pick<Node, 'id' | 'data'> | type NodeControlProps = Pick<Node, 'id' | 'data'> | ||||
| const NodeControl: FC<NodeControlProps> = ({ | const NodeControl: FC<NodeControlProps> = ({ | ||||
| data._isSingleRun | data._isSingleRun | ||||
| ? <Stop className='w-3 h-3' /> | ? <Stop className='w-3 h-3' /> | ||||
| : ( | : ( | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={t('workflow.panel.runThisStep')} | popupContent={t('workflow.panel.runThisStep')} | ||||
| asChild={false} | |||||
| > | > | ||||
| <RiPlayLargeLine className='w-3 h-3' /> | <RiPlayLargeLine className='w-3 h-3' /> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| ) | ) | ||||
| } | } | ||||
| </div> | </div> |
| import React, { useCallback } from 'react' | import React, { useCallback } from 'react' | ||||
| import type { VariantProps } from 'class-variance-authority' | import type { VariantProps } from 'class-variance-authority' | ||||
| import { cva } from 'class-variance-authority' | import { cva } from 'class-variance-authority' | ||||
| import { RiQuestionLine } from '@remixicon/react' | |||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| const variants = cva([], { | const variants = cva([], { | ||||
| variants: { | variants: { | ||||
| onClick={handleSelect} | onClick={handleSelect} | ||||
| > | > | ||||
| <span>{title}</span> | <span>{title}</span> | ||||
| {tooltip && <TooltipPlus | |||||
| popupContent={<div className='w-[240px]'> | |||||
| {tooltip} | |||||
| </div>} | |||||
| > | |||||
| <RiQuestionLine className='ml-0.5 w-[14px] h-[14px] text-text-quaternary' /> | |||||
| </TooltipPlus>} | |||||
| {tooltip | |||||
| && <Tooltip | |||||
| popupContent={ | |||||
| <div className='w-[240px]'> | |||||
| {tooltip} | |||||
| </div> | |||||
| } | |||||
| /> | |||||
| } | |||||
| </div> | </div> | ||||
| ) | ) | ||||
| } | } |
| import { PROMPT_EDITOR_INSERT_QUICKLY } from '@/app/components/base/prompt-editor/plugins/update-block' | import { PROMPT_EDITOR_INSERT_QUICKLY } from '@/app/components/base/prompt-editor/plugins/update-block' | ||||
| import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' | import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' | ||||
| import ActionButton from '@/app/components/base/action-button' | import ActionButton from '@/app/components/base/action-button' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor/editor-support-vars' | import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor/editor-support-vars' | ||||
| import Switch from '@/app/components/base/switch' | import Switch from '@/app/components/base/switch' | ||||
| import { Jinja } from '@/app/components/base/icons/src/vender/workflow' | import { Jinja } from '@/app/components/base/icons/src/vender/workflow' | ||||
| {/* Operations */} | {/* Operations */} | ||||
| <div className='flex items-center space-x-[2px]'> | <div className='flex items-center space-x-[2px]'> | ||||
| {isSupportJinja && ( | {isSupportJinja && ( | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={ | popupContent={ | ||||
| <div> | <div> | ||||
| <div>{t('workflow.common.enableJinja')}</div> | <div>{t('workflow.common.enableJinja')}</div> | ||||
| <a className='text-[#155EEF]' target='_blank' href='https://jinja.palletsprojects.com/en/2.10.x/'>{t('workflow.common.learnMore')}</a> | <a className='text-[#155EEF]' target='_blank' href='https://jinja.palletsprojects.com/en/2.10.x/'>{t('workflow.common.learnMore')}</a> | ||||
| </div> | </div> | ||||
| } | } | ||||
| hideArrow | |||||
| needsDelay | |||||
| > | > | ||||
| <div className={cn(editionType === EditionType.jinja2 && 'border-black/5 bg-white', 'flex h-[22px] items-center px-1.5 rounded-[5px] border border-transparent hover:border-black/5 space-x-0.5')}> | <div className={cn(editionType === EditionType.jinja2 && 'border-black/5 bg-white', 'flex h-[22px] items-center px-1.5 rounded-[5px] border border-transparent hover:border-black/5 space-x-0.5')}> | ||||
| <Jinja className='w-6 h-3 text-gray-300' /> | <Jinja className='w-6 h-3 text-gray-300' /> | ||||
| }} | }} | ||||
| /> | /> | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| )} | )} | ||||
| {!readOnly && ( | {!readOnly && ( | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={`${t('workflow.common.insertVarTip')}`} | popupContent={`${t('workflow.common.insertVarTip')}`} | ||||
| asChild | |||||
| > | > | ||||
| <ActionButton onClick={handleInsertVariable}> | <ActionButton onClick={handleInsertVariable}> | ||||
| <Variable02 className='w-4 h-4' /> | <Variable02 className='w-4 h-4' /> | ||||
| </ActionButton> | </ActionButton> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| )} | )} | ||||
| {showRemove && ( | {showRemove && ( | ||||
| <ActionButton onClick={onRemove}> | <ActionButton onClick={onRemove}> |
| useWorkflowHistory, | useWorkflowHistory, | ||||
| } from '@/app/components/workflow/hooks' | } from '@/app/components/workflow/hooks' | ||||
| import { canRunBySingle } from '@/app/components/workflow/utils' | import { canRunBySingle } from '@/app/components/workflow/utils' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import type { Node } from '@/app/components/workflow/types' | import type { Node } from '@/app/components/workflow/types' | ||||
| import { useStore as useAppStore } from '@/app/components/app/store' | import { useStore as useAppStore } from '@/app/components/app/store' | ||||
| import { useStore } from '@/app/components/workflow/store' | import { useStore } from '@/app/components/workflow/store' | ||||
| <div className='shrink-0 flex items-center text-gray-500'> | <div className='shrink-0 flex items-center text-gray-500'> | ||||
| { | { | ||||
| canRunBySingle(data.type) && !nodesReadOnly && ( | canRunBySingle(data.type) && !nodesReadOnly && ( | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={t('workflow.panel.runThisStep')} | popupContent={t('workflow.panel.runThisStep')} | ||||
| popupClassName='mr-1' | |||||
| > | > | ||||
| <div | <div | ||||
| className='flex items-center justify-center mr-1 w-6 h-6 rounded-md hover:bg-black/5 cursor-pointer' | className='flex items-center justify-center mr-1 w-6 h-6 rounded-md hover:bg-black/5 cursor-pointer' | ||||
| > | > | ||||
| <RiPlayLargeLine className='w-4 h-4 text-text-tertiary' /> | <RiPlayLargeLine className='w-4 h-4 text-text-tertiary' /> | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| ) | ) | ||||
| } | } | ||||
| <HelpLink nodeType={data.type} /> | <HelpLink nodeType={data.type} /> |
| import { | import { | ||||
| BlockEnum, | BlockEnum, | ||||
| } from '@/app/components/workflow/types' | } from '@/app/components/workflow/types' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| type AddBlockProps = { | type AddBlockProps = { | ||||
| iterationNodeId: string | iterationNodeId: string | ||||
| return ( | return ( | ||||
| <div className='absolute top-12 left-6 flex items-center h-8 z-10'> | <div className='absolute top-12 left-6 flex items-center h-8 z-10'> | ||||
| <TooltipPlus popupContent={t('workflow.blocks.iteration-start')}> | |||||
| <Tooltip popupContent={t('workflow.blocks.iteration-start')}> | |||||
| <div className='flex items-center justify-center w-6 h-6 rounded-full border-[0.5px] border-black/[0.02] shadow-md bg-primary-500'> | <div className='flex items-center justify-center w-6 h-6 rounded-full border-[0.5px] border-black/[0.02] shadow-md bg-primary-500'> | ||||
| <IterationStart className='w-4 h-4 text-white' /> | <IterationStart className='w-4 h-4 text-white' /> | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| <div className='group/insert relative w-16 h-0.5 bg-gray-300'> | <div className='group/insert relative w-16 h-0.5 bg-gray-300'> | ||||
| { | { | ||||
| iterationNodeData.startNodeType && ( | iterationNodeData.startNodeType && ( |
| import React, { useCallback, useEffect, useState } from 'react' | import React, { useCallback, useEffect, useState } from 'react' | ||||
| import { uniqueId } from 'lodash-es' | import { uniqueId } from 'lodash-es' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { RiQuestionLine } from '@remixicon/react' | |||||
| import type { ModelConfig, PromptItem, Variable } from '../../../types' | import type { ModelConfig, PromptItem, Variable } from '../../../types' | ||||
| import { EditionType } from '../../../types' | import { EditionType } from '../../../types' | ||||
| import { useWorkflowStore } from '../../../store' | import { useWorkflowStore } from '../../../store' | ||||
| import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor' | import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor' | ||||
| import TypeSelector from '@/app/components/workflow/nodes/_base/components/selector' | import TypeSelector from '@/app/components/workflow/nodes/_base/components/selector' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import { PromptRole } from '@/models/debug' | import { PromptRole } from '@/models/debug' | ||||
| const i18nPrefix = 'workflow.nodes.llm' | const i18nPrefix = 'workflow.nodes.llm' | ||||
| /> | /> | ||||
| )} | )} | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={ | popupContent={ | ||||
| <div className='max-w-[180px]'>{t(`${i18nPrefix}.roleDescription.${payload.role}`)}</div> | <div className='max-w-[180px]'>{t(`${i18nPrefix}.roleDescription.${payload.role}`)}</div> | ||||
| } | } | ||||
| > | |||||
| <RiQuestionLine className='w-3.5 h-3.5 text-gray-400' /> | |||||
| </TooltipPlus> | |||||
| triggerClassName='w-4 h-4' | |||||
| /> | |||||
| </div> | </div> | ||||
| } | } | ||||
| value={payload.edition_type === EditionType.jinja2 ? (payload.jinja2_text || '') : payload.text} | value={payload.edition_type === EditionType.jinja2 ? (payload.jinja2_text || '') : payload.text} |
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import React from 'react' | import React from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { RiQuestionLine } from '@remixicon/react' | |||||
| import MemoryConfig from '../_base/components/memory-config' | import MemoryConfig from '../_base/components/memory-config' | ||||
| import VarReferencePicker from '../_base/components/variable/var-reference-picker' | import VarReferencePicker from '../_base/components/variable/var-reference-picker' | ||||
| import useConfig from './use-config' | import useConfig from './use-config' | ||||
| import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form' | import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form' | ||||
| import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form' | import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form' | ||||
| import ResultPanel from '@/app/components/workflow/run/result-panel' | import ResultPanel from '@/app/components/workflow/run/result-panel' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor' | import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor' | ||||
| import Switch from '@/app/components/base/switch' | import Switch from '@/app/components/base/switch' | ||||
| const i18nPrefix = 'workflow.nodes.llm' | const i18nPrefix = 'workflow.nodes.llm' | ||||
| <div className='flex justify-between items-center h-8 pl-3 pr-2 rounded-lg bg-gray-100'> | <div className='flex justify-between items-center h-8 pl-3 pr-2 rounded-lg bg-gray-100'> | ||||
| <div className='flex items-center space-x-1'> | <div className='flex items-center space-x-1'> | ||||
| <div className='text-xs font-semibold text-gray-700 uppercase'>{t('workflow.nodes.common.memories.title')}</div> | <div className='text-xs font-semibold text-gray-700 uppercase'>{t('workflow.nodes.common.memories.title')}</div> | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={t('workflow.nodes.common.memories.tip')} | popupContent={t('workflow.nodes.common.memories.tip')} | ||||
| > | |||||
| <RiQuestionLine className='w-3.5 h-3.5 text-gray-400' /> | |||||
| </TooltipPlus> | |||||
| triggerClassName='w-4 h-4' | |||||
| /> | |||||
| </div> | </div> | ||||
| <div className='flex items-center h-[18px] px-1 rounded-[5px] border border-black/8 text-xs font-semibold text-gray-500 uppercase'>{t('workflow.nodes.common.memories.builtIn')}</div> | <div className='flex items-center h-[18px] px-1 rounded-[5px] border border-black/8 text-xs font-semibold text-gray-500 uppercase'>{t('workflow.nodes.common.memories.builtIn')}</div> | ||||
| </div> | </div> | ||||
| <Editor | <Editor | ||||
| title={<div className='flex items-center space-x-1'> | title={<div className='flex items-center space-x-1'> | ||||
| <div className='text-xs font-semibold text-gray-700 uppercase'>user</div> | <div className='text-xs font-semibold text-gray-700 uppercase'>user</div> | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={ | popupContent={ | ||||
| <div className='max-w-[180px]'>{t('workflow.nodes.llm.roleDescription.user')}</div> | <div className='max-w-[180px]'>{t('workflow.nodes.llm.roleDescription.user')}</div> | ||||
| } | } | ||||
| > | |||||
| <RiQuestionLine className='w-3.5 h-3.5 text-gray-400' /> | |||||
| </TooltipPlus> | |||||
| triggerClassName='w-4 h-4' | |||||
| /> | |||||
| </div>} | </div>} | ||||
| value={inputs.memory.query_prompt_template || '{{#sys.query#}}'} | value={inputs.memory.query_prompt_template || '{{#sys.query#}}'} | ||||
| onChange={handleSyeQueryChange} | onChange={handleSyeQueryChange} |
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import React from 'react' | import React from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import MemoryConfig from '../_base/components/memory-config' | import MemoryConfig from '../_base/components/memory-config' | ||||
| import VarReferencePicker from '../_base/components/variable/var-reference-picker' | import VarReferencePicker from '../_base/components/variable/var-reference-picker' | ||||
| import Editor from '../_base/components/prompt/editor' | import Editor from '../_base/components/prompt/editor' | ||||
| import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal' | import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal' | ||||
| import OutputVars, { VarItem } from '@/app/components/workflow/nodes/_base/components/output-vars' | import OutputVars, { VarItem } from '@/app/components/workflow/nodes/_base/components/output-vars' | ||||
| import { InputVarType, type NodePanelProps } from '@/app/components/workflow/types' | import { InputVarType, type NodePanelProps } from '@/app/components/workflow/types' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form' | import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form' | ||||
| import { VarType } from '@/app/components/workflow/types' | import { VarType } from '@/app/components/workflow/types' | ||||
| title={ | title={ | ||||
| <div className='flex items-center space-x-1'> | <div className='flex items-center space-x-1'> | ||||
| <span className='uppercase'>{t(`${i18nPrefix}.instruction`)}</span> | <span className='uppercase'>{t(`${i18nPrefix}.instruction`)}</span> | ||||
| <TooltipPlus popupContent={ | |||||
| <div className='w-[120px]'> | |||||
| {t(`${i18nPrefix}.instructionTip`)} | |||||
| </div>}> | |||||
| <RiQuestionLine className='w-3.5 h-3.5 ml-0.5 text-gray-400' /> | |||||
| </TooltipPlus> | |||||
| <Tooltip | |||||
| popupContent={ | |||||
| <div className='w-[120px]'> | |||||
| {t(`${i18nPrefix}.instructionTip`)} | |||||
| </div> | |||||
| } | |||||
| triggerClassName='w-3.5 h-3.5 ml-0.5' | |||||
| /> | |||||
| </div> | </div> | ||||
| } | } | ||||
| value={inputs.instruction} | value={inputs.instruction} |
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import React from 'react' | import React from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { | |||||
| RiQuestionLine, | |||||
| } from '@remixicon/react' | |||||
| import MemoryConfig from '../../_base/components/memory-config' | import MemoryConfig from '../../_base/components/memory-config' | ||||
| import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor' | import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor' | ||||
| import type { Memory, Node, NodeOutPutVar } from '@/app/components/workflow/types' | import type { Memory, Node, NodeOutPutVar } from '@/app/components/workflow/types' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| const i18nPrefix = 'workflow.nodes.questionClassifiers' | const i18nPrefix = 'workflow.nodes.questionClassifiers' | ||||
| type Props = { | type Props = { | ||||
| title={ | title={ | ||||
| <div className='flex items-center space-x-1'> | <div className='flex items-center space-x-1'> | ||||
| <span className='uppercase'>{t(`${i18nPrefix}.instruction`)}</span> | <span className='uppercase'>{t(`${i18nPrefix}.instruction`)}</span> | ||||
| <TooltipPlus popupContent={ | |||||
| <div className='w-[120px]'> | |||||
| {t(`${i18nPrefix}.instructionTip`)} | |||||
| </div>}> | |||||
| <RiQuestionLine className='w-3.5 h-3.5 ml-0.5 text-gray-400' /> | |||||
| </TooltipPlus> | |||||
| <Tooltip | |||||
| popupContent={ | |||||
| <div className='w-[120px]'> | |||||
| {t(`${i18nPrefix}.instructionTip`)} | |||||
| </div> | |||||
| } | |||||
| triggerClassName='w-3.5 h-3.5 ml-0.5' | |||||
| /> | |||||
| </div> | </div> | ||||
| } | } | ||||
| value={instruction} | value={instruction} |
| import { useStore } from '../store' | import { useStore } from '../store' | ||||
| import { useCommand } from './hooks' | import { useCommand } from './hooks' | ||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| type CommandProps = { | type CommandProps = { | ||||
| type: 'bold' | 'italic' | 'strikethrough' | 'link' | 'bullet' | type: 'bold' | 'italic' | 'strikethrough' | 'link' | 'bullet' | ||||
| }, [type, t]) | }, [type, t]) | ||||
| return ( | return ( | ||||
| <TooltipPlus popupContent={tip}> | |||||
| <Tooltip | |||||
| popupContent={tip} | |||||
| > | |||||
| <div | <div | ||||
| className={cn( | className={cn( | ||||
| 'flex items-center justify-center w-8 h-8 cursor-pointer rounded-md text-gray-500 hover:text-gray-800 hover:bg-black/5', | 'flex items-center justify-center w-8 h-8 cursor-pointer rounded-md text-gray-500 hover:text-gray-800 hover:bg-black/5', | ||||
| > | > | ||||
| {icon} | {icon} | ||||
| </div> | </div> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| ) | ) | ||||
| } | } | ||||
| import { memo } from 'react' | import { memo } from 'react' | ||||
| import ShortcutsName from '../shortcuts-name' | import ShortcutsName from '../shortcuts-name' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| type TipPopupProps = { | type TipPopupProps = { | ||||
| title: string | title: string | ||||
| shortcuts, | shortcuts, | ||||
| }: TipPopupProps) => { | }: TipPopupProps) => { | ||||
| return ( | return ( | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| offset={4} | offset={4} | ||||
| hideArrow | |||||
| popupClassName='!p-0 !bg-gray-25' | popupClassName='!p-0 !bg-gray-25' | ||||
| popupContent={ | popupContent={ | ||||
| <div className='flex items-center gap-1 px-2 h-6 text-xs font-medium text-gray-700 rounded-lg border-[0.5px] border-black/5'> | <div className='flex items-center gap-1 px-2 h-6 text-xs font-medium text-gray-700 rounded-lg border-[0.5px] border-black/5'> | ||||
| } | } | ||||
| > | > | ||||
| {children} | {children} | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| ) | ) | ||||
| } | } | ||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import { RefreshCcw01 } from '@/app/components/base/icons/src/vender/line/arrows' | import { RefreshCcw01 } from '@/app/components/base/icons/src/vender/line/arrows' | ||||
| import { BubbleX } from '@/app/components/base/icons/src/vender/line/others' | import { BubbleX } from '@/app/components/base/icons/src/vender/line/others' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import ActionButton, { ActionButtonState } from '@/app/components/base/action-button' | import ActionButton, { ActionButtonState } from '@/app/components/base/action-button' | ||||
| import { useStore } from '@/app/components/workflow/store' | import { useStore } from '@/app/components/workflow/store' | ||||
| <div className='shrink-0 flex items-center justify-between px-4 pt-3 pb-2 text-text-primary system-xl-semibold'> | <div className='shrink-0 flex items-center justify-between px-4 pt-3 pb-2 text-text-primary system-xl-semibold'> | ||||
| <div className='h-8'>{t('workflow.common.debugAndPreview').toLocaleUpperCase()}</div> | <div className='h-8'>{t('workflow.common.debugAndPreview').toLocaleUpperCase()}</div> | ||||
| <div className='flex items-center gap-1'> | <div className='flex items-center gap-1'> | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={t('common.operation.refresh')} | popupContent={t('common.operation.refresh')} | ||||
| > | > | ||||
| <ActionButton onClick={() => handleRestartChat()}> | <ActionButton onClick={() => handleRestartChat()}> | ||||
| <RefreshCcw01 className='w-4 h-4' /> | <RefreshCcw01 className='w-4 h-4' /> | ||||
| </ActionButton> | </ActionButton> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| {varList.length > 0 && ( | {varList.length > 0 && ( | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={t('workflow.chatVariable.panelTitle')} | popupContent={t('workflow.chatVariable.panelTitle')} | ||||
| > | > | ||||
| <ActionButton onClick={() => setShowConversationVariableModal(true)}> | <ActionButton onClick={() => setShowConversationVariableModal(true)}> | ||||
| <BubbleX className='w-4 h-4' /> | <BubbleX className='w-4 h-4' /> | ||||
| </ActionButton> | </ActionButton> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| )} | )} | ||||
| {variables.length > 0 && ( | {variables.length > 0 && ( | ||||
| <div className='relative'> | <div className='relative'> | ||||
| <TooltipPlus | |||||
| <Tooltip | |||||
| popupContent={t('workflow.panel.userInputField')} | popupContent={t('workflow.panel.userInputField')} | ||||
| > | > | ||||
| <ActionButton state={expanded ? ActionButtonState.Active : undefined} onClick={() => setExpanded(!expanded)}> | <ActionButton state={expanded ? ActionButtonState.Active : undefined} onClick={() => setExpanded(!expanded)}> | ||||
| <RiEqualizer2Line className='w-4 h-4' /> | <RiEqualizer2Line className='w-4 h-4' /> | ||||
| </ActionButton> | </ActionButton> | ||||
| </TooltipPlus> | |||||
| </Tooltip> | |||||
| {expanded && <div className='absolute z-10 bottom-[-17px] right-[5px] w-3 h-3 bg-components-panel-on-panel-item-bg border-l-[0.5px] border-t-[0.5px] border-components-panel-border-subtle rotate-45'/>} | {expanded && <div className='absolute z-10 bottom-[-17px] right-[5px] w-3 h-3 bg-components-panel-on-panel-item-bg border-l-[0.5px] border-t-[0.5px] border-components-panel-border-subtle rotate-45'/>} | ||||
| </div> | </div> | ||||
| )} | )} |
| import React, { useEffect } from 'react' | import React, { useEffect } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { v4 as uuid4 } from 'uuid' | import { v4 as uuid4 } from 'uuid' | ||||
| import { RiCloseLine, RiQuestionLine } from '@remixicon/react' | |||||
| import { RiCloseLine } from '@remixicon/react' | |||||
| import { useContext } from 'use-context-selector' | import { useContext } from 'use-context-selector' | ||||
| import Button from '@/app/components/base/button' | import Button from '@/app/components/base/button' | ||||
| import TooltipPlus from '@/app/components/base/tooltip-plus' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import { ToastContext } from '@/app/components/base/toast' | import { ToastContext } from '@/app/components/base/toast' | ||||
| import { useStore } from '@/app/components/workflow/store' | import { useStore } from '@/app/components/workflow/store' | ||||
| import type { EnvironmentVariable } from '@/app/components/workflow/types' | import type { EnvironmentVariable } from '@/app/components/workflow/types' | ||||
| type === 'secret' && 'text-text-primary font-medium border-[1.5px] shadow-xs bg-components-option-card-option-selected-bg border-components-option-card-option-selected-border hover:border-components-option-card-option-selected-border', | type === 'secret' && 'text-text-primary font-medium border-[1.5px] shadow-xs bg-components-option-card-option-selected-bg border-components-option-card-option-selected-border hover:border-components-option-card-option-selected-border', | ||||
| )} onClick={() => setType('secret')}> | )} onClick={() => setType('secret')}> | ||||
| <span>Secret</span> | <span>Secret</span> | ||||
| <TooltipPlus popupContent={ | |||||
| <div className='w-[240px]'> | |||||
| {t('workflow.env.modal.secretTip')} | |||||
| </div> | |||||
| }> | |||||
| <RiQuestionLine className='ml-0.5 w-[14px] h-[14px] text-text-quaternary' /> | |||||
| </TooltipPlus> | |||||
| <Tooltip | |||||
| popupContent={ | |||||
| <div className='w-[240px]'> | |||||
| {t('workflow.env.modal.secretTip')} | |||||
| </div> | |||||
| } | |||||
| triggerClassName='ml-0.5 w-3.5 h-3.5' | |||||
| /> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> |
| import { useRouter } from 'next/navigation' | import { useRouter } from 'next/navigation' | ||||
| // import { useContext } from 'use-context-selector' | // import { useContext } from 'use-context-selector' | ||||
| import Button from '@/app/components/base/button' | import Button from '@/app/components/base/button' | ||||
| import Tooltip from '@/app/components/base/tooltip/index' | |||||
| import Tooltip from '@/app/components/base/tooltip' | |||||
| import { SimpleSelect } from '@/app/components/base/select' | import { SimpleSelect } from '@/app/components/base/select' | ||||
| import { timezones } from '@/utils/timezone' | import { timezones } from '@/utils/timezone' | ||||
| import { LanguagesSupported, languages } from '@/i18n/language' | import { LanguagesSupported, languages } from '@/i18n/language' | ||||
| <label className="my-2 flex items-center justify-between text-sm font-medium text-gray-900"> | <label className="my-2 flex items-center justify-between text-sm font-medium text-gray-900"> | ||||
| {t('login.invitationCode')} | {t('login.invitationCode')} | ||||
| <Tooltip | <Tooltip | ||||
| clickable | |||||
| selector='dont-have' | |||||
| htmlContent={ | |||||
| popupContent={ | |||||
| <div className='w-[256px] text-xs font-medium'> | <div className='w-[256px] text-xs font-medium'> | ||||
| <div className='font-medium'>{t('login.sendUsMail')}</div> | <div className='font-medium'>{t('login.sendUsMail')}</div> | ||||
| <div className='text-xs font-medium cursor-pointer text-primary-600'> | <div className='text-xs font-medium cursor-pointer text-primary-600'> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| } | } | ||||
| needsDelay | |||||
| > | > | ||||
| <span className='cursor-pointer text-primary-600'>{t('login.donthave')}</span> | <span className='cursor-pointer text-primary-600'>{t('login.donthave')}</span> | ||||
| </Tooltip> | </Tooltip> |