Merge branch 'feat/plugins' of https://github.com/langgenius/dify into feat/plugins

This commit is contained in:
AkaraChen 2025-01-09 14:31:49 +08:00
commit a87c2d7e20
11 changed files with 110 additions and 113 deletions

View File

@ -21,7 +21,7 @@ type IShareLinkProps = {
}
const StepNum: FC<{ children: React.ReactNode }> = ({ children }) =>
<div className='h-7 w-7 flex justify-center items-center flex-shrink-0 mr-3 text-primary-600 bg-primary-50 rounded-2xl'>
<div className='h-7 w-7 flex justify-center items-center shrink-0 mr-3 text-text-accent bg-util-colors-blue-blue-50 rounded-2xl'>
{children}
</div>
@ -54,27 +54,27 @@ const CustomizeModal: FC<IShareLinkProps> = ({
className='!max-w-2xl w-[640px]'
closable={true}
>
<div className='w-full mt-4 px-6 py-5 border-gray-200 rounded-lg border-[0.5px]'>
<Tag bordered={true} hideBg={true} className='text-primary-600 border-primary-600 uppercase'>{t(`${prefixCustomize}.way`)} 1</Tag>
<p className='my-2 text-base font-medium text-gray-800'>{t(`${prefixCustomize}.way1.name`)}</p>
<div className='w-full mt-4 px-6 py-5 border-components-panel-border rounded-lg border-[0.5px]'>
<Tag bordered={true} hideBg={true} className='text-text-accent-secondary border-text-accent-secondary uppercase'>{t(`${prefixCustomize}.way`)} 1</Tag>
<p className='my-2 system-sm-medium text-text-secondary'>{t(`${prefixCustomize}.way1.name`)}</p>
<div className='flex py-4'>
<StepNum>1</StepNum>
<div className='flex flex-col'>
<div className='text-gray-900'>{t(`${prefixCustomize}.way1.step1`)}</div>
<div className='text-gray-500 text-xs mt-1 mb-2'>{t(`${prefixCustomize}.way1.step1Tip`)}</div>
<div className='text-text-primary'>{t(`${prefixCustomize}.way1.step1`)}</div>
<div className='text-text-tertiary text-xs mt-1 mb-2'>{t(`${prefixCustomize}.way1.step1Tip`)}</div>
<a href={`https://github.com/langgenius/${isChatApp ? 'webapp-conversation' : 'webapp-text-generator'}`} target='_blank' rel='noopener noreferrer'>
<Button><GithubIcon className='text-gray-800 mr-2' />{t(`${prefixCustomize}.way1.step1Operation`)}</Button>
<Button><GithubIcon className='text-text-secondary mr-2' />{t(`${prefixCustomize}.way1.step1Operation`)}</Button>
</a>
</div>
</div>
<div className='flex pt-4'>
<StepNum>2</StepNum>
<div className='flex flex-col'>
<div className='text-gray-900'>{t(`${prefixCustomize}.way1.step3`)}</div>
<div className='text-gray-500 text-xs mt-1 mb-2'>{t(`${prefixCustomize}.way1.step2Tip`)}</div>
<div className='text-text-primary'>{t(`${prefixCustomize}.way1.step3`)}</div>
<div className='text-text-tertiary text-xs mt-1 mb-2'>{t(`${prefixCustomize}.way1.step2Tip`)}</div>
<a href="https://vercel.com/docs/concepts/deployments/git/vercel-for-github" target='_blank' rel='noopener noreferrer'>
<Button>
<div className='mr-1.5 border-solid border-t-0 border-r-[7px] border-l-[7px] border-b-[12px] border-r-transparent border-b-black border-l-transparent border-t-transparent'></div>
<div className='mr-1.5 border-solid border-t-0 border-r-[7px] border-l-[7px] border-b-[12px] border-r-transparent border-text-primary border-l-transparent border-t-transparent'></div>
<span>{t(`${prefixCustomize}.way1.step2Operation`)}</span>
</Button>
</a>
@ -83,9 +83,9 @@ const CustomizeModal: FC<IShareLinkProps> = ({
<div className='flex py-4'>
<StepNum>3</StepNum>
<div className='flex flex-col w-full overflow-hidden'>
<div className='text-gray-900'>{t(`${prefixCustomize}.way1.step3`)}</div>
<div className='text-gray-500 text-xs mt-1 mb-2'>{t(`${prefixCustomize}.way1.step3Tip`)}</div>
<pre className='overflow-x-scroll box-border py-3 px-4 bg-gray-100 text-xs font-medium rounded-lg select-text'>
<div className='text-text-primary'>{t(`${prefixCustomize}.way1.step3`)}</div>
<div className='text-text-tertiary text-xs mt-1 mb-2'>{t(`${prefixCustomize}.way1.step3Tip`)}</div>
<pre className='overflow-x-scroll box-border py-3 px-4 bg-background-section text-xs font-medium rounded-lg select-text text-text-secondary border-[0.5px] border-components-panel-border'>
NEXT_PUBLIC_APP_ID={`'${appId}'`} <br />
NEXT_PUBLIC_APP_KEY={'\'<Web API Key From Dify>\''} <br />
NEXT_PUBLIC_API_URL={`'${api_base_url}'`}
@ -94,9 +94,9 @@ const CustomizeModal: FC<IShareLinkProps> = ({
</div>
</div>
<div className='w-full mt-4 px-6 py-5 border-gray-200 rounded-lg border-[0.5px]'>
<Tag bordered={true} hideBg={true} className='text-primary-600 border-primary-600 uppercase'>{t(`${prefixCustomize}.way`)} 2</Tag>
<p className='mt-2 text-base font-medium text-gray-800'>{t(`${prefixCustomize}.way2.name`)}</p>
<div className='w-full mt-4 px-6 py-5 border-components-panel-border rounded-lg border-[0.5px]'>
<Tag bordered={true} hideBg={true} className='text-text-accent-secondary border-text-accent-secondary uppercase'>{t(`${prefixCustomize}.way`)} 2</Tag>
<p className='my-2 system-sm-medium text-text-secondary'>{t(`${prefixCustomize}.way2.name`)}</p>
<Button
className='mt-2'
onClick={() =>
@ -109,8 +109,8 @@ const CustomizeModal: FC<IShareLinkProps> = ({
)
}
>
<span className='text-sm text-gray-800'>{t(`${prefixCustomize}.way2.operation`)}</span>
<ArrowTopRightOnSquareIcon className='w-4 h-4 ml-1 text-gray-800 shrink-0' />
<span className='text-sm text-text-secondary'>{t(`${prefixCustomize}.way2.operation`)}</span>
<ArrowTopRightOnSquareIcon className='w-4 h-4 ml-1 text-text-secondary shrink-0' />
</Button>
</div>
</Modal>

View File

@ -1,15 +1,19 @@
import React, { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import {
RiClipboardFill,
RiClipboardLine,
} from '@remixicon/react'
import copy from 'copy-to-clipboard'
import style from './style.module.css'
import cn from '@/utils/classnames'
import Modal from '@/app/components/base/modal'
import copyStyle from '@/app/components/base/copy-btn/style.module.css'
import Tooltip from '@/app/components/base/tooltip'
import { useAppContext } from '@/context/app-context'
import { IS_CE_EDITION } from '@/config'
import type { SiteInfo } from '@/models/share'
import { useThemeContext } from '@/app/components/base/chat/embedded-chatbot/theme/theme-context'
import ActionButton from '@/app/components/base/action-button'
import cn from '@/utils/classnames'
type Props = {
siteInfo?: SiteInfo
@ -119,7 +123,7 @@ const Embedded = ({ siteInfo, isShow, onClose, appBaseUrl, accessToken, classNam
wrapperClassName={className}
closable={true}
>
<div className="mb-4 mt-8 text-gray-900 text-[14px] font-medium leading-tight">
<div className="mb-4 mt-8 text-text-primary system-sm-medium">
{t(`${prefixEmbedded}.explanation`)}
</div>
<div className="flex flex-wrap items-center justify-between gap-y-2">
@ -143,30 +147,37 @@ const Embedded = ({ siteInfo, isShow, onClose, appBaseUrl, accessToken, classNam
{option === 'chromePlugin' && (
<div className="w-full mt-6">
<div className={cn('gap-2 py-3 justify-center items-center inline-flex w-full rounded-lg',
'bg-primary-600 hover:bg-primary-600/75 hover:shadow-md cursor-pointer text-white hover:shadow-sm flex-shrink-0')}>
'bg-primary-600 hover:bg-primary-600/75 cursor-pointer text-white hover:shadow-sm flex-shrink-0')}>
<div className={`w-4 h-4 relative ${style.pluginInstallIcon}`}></div>
<div className="text-white text-sm font-medium font-['Inter'] leading-tight" onClick={navigateToChromeUrl}>{t(`${prefixEmbedded}.chromePlugin`)}</div>
</div>
</div>
)}
<div className={cn('w-full bg-gray-100 rounded-lg flex-col justify-start items-start inline-flex',
<div className={cn('w-full bg-background-section border-[0.5px] border-components-panel-border rounded-lg flex-col justify-start items-start inline-flex',
'mt-6')}>
<div className="inline-flex items-center self-stretch justify-start gap-2 py-1 pl-3 pr-1 border border-black rounded-tl-lg rounded-tr-lg bg-gray-50 border-opacity-5">
<div className="grow shrink basis-0 text-slate-700 text-[13px] font-medium leading-none">
<div className="inline-flex items-center self-stretch justify-start gap-2 py-1 pl-3 pr-1 rounded-t-lg bg-background-section-burn">
<div className="grow shrink-0 text-text-secondary system-sm-medium">
{t(`${prefixEmbedded}.${option}`)}
</div>
<div className="flex items-center justify-center gap-1 p-2 rounded-lg">
<Tooltip
popupContent={(isCopied[option] ? t(`${prefixEmbedded}.copied`) : t(`${prefixEmbedded}.copy`)) || ''}
>
<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>
<Tooltip
popupContent={
(isCopied[option]
? t(`${prefixEmbedded}.copied`)
: t(`${prefixEmbedded}.copy`)) || ''
}
>
<ActionButton>
<div
onClick={onClickCopy}
>
{isCopied[option] && <RiClipboardFill className='w-4 h-4' />}
{!isCopied[option] && <RiClipboardLine className='w-4 h-4' />}
</div>
</Tooltip>
</div>
</ActionButton>
</Tooltip>
</div>
<div className="flex items-start justify-start w-full gap-2 p-3 overflow-x-auto">
<div className="grow shrink basis-0 text-slate-700 text-[13px] leading-tight font-mono">
<div className="grow shrink basis-0 text-text-secondary text-[13px] leading-tight font-mono">
<pre className='select-text'>{OPTION_MAP[option].getContent(appBaseUrl, accessToken, themeBuilder.theme?.primaryColor ?? '#1C64F2', isTestEnv)}</pre>
</div>
</div>

View File

@ -5,7 +5,6 @@ import { ChevronRightIcon } from '@heroicons/react/20/solid'
import Link from 'next/link'
import { Trans, useTranslation } from 'react-i18next'
import { useContextSelector } from 'use-context-selector'
import s from './style.module.css'
import Modal from '@/app/components/base/modal'
import Button from '@/app/components/base/button'
import Input from '@/app/components/base/input'
@ -21,6 +20,8 @@ import Tooltip from '@/app/components/base/tooltip'
import AppContext, { useAppContext } from '@/context/app-context'
import type { AppIconSelection } from '@/app/components/base/app-icon-picker'
import AppIconPicker from '@/app/components/base/app-icon-picker'
import Divider from '@/app/components/base/divider'
import cn from '@/utils/classnames'
export type ISettingsModalProps = {
isChat: boolean
@ -195,9 +196,9 @@ const SettingsModal: FC<ISettingsModalProps> = ({
title={t(`${prefixSettings}.title`)}
isShow={isShow}
onClose={onHide}
className={`${s.settingsModal}`}
className='max-w-[520px]'
>
<div className={`mt-6 font-medium ${s.settingTitle} text-gray-900`}>{t(`${prefixSettings}.webName`)}</div>
<div className={cn('mt-6 system-sm-semibold text-text-secondary')}>{t(`${prefixSettings}.webName`)}</div>
<div className='flex mt-2'>
<AppIcon size='large'
onClick={() => { setShowAppIconPicker(true) }}
@ -214,8 +215,8 @@ const SettingsModal: FC<ISettingsModalProps> = ({
placeholder={t('app.appNamePlaceholder') || ''}
/>
</div>
<div className={`mt-6 font-medium ${s.settingTitle} text-gray-900 `}>{t(`${prefixSettings}.webDesc`)}</div>
<p className={`mt-1 ${s.settingsTip} text-gray-500`}>{t(`${prefixSettings}.webDescTip`)}</p>
<div className={cn('mt-6 system-sm-semibold text-text-secondary')}>{t(`${prefixSettings}.webDesc`)}</div>
<p className={cn('mt-1 body-xs-regular text-text-tertiary')}>{t(`${prefixSettings}.webDescTip`)}</p>
<Textarea
className='mt-2'
value={inputInfo.desc}
@ -225,36 +226,36 @@ const SettingsModal: FC<ISettingsModalProps> = ({
{isChatBot && (
<div className='w-full mt-4'>
<div className='flex justify-between items-center'>
<div className={`font-medium ${s.settingTitle} text-gray-900 `}>{t('app.answerIcon.title')}</div>
<div className={cn('system-sm-semibold text-text-secondary')}>{t('app.answerIcon.title')}</div>
<Switch
defaultValue={inputInfo.use_icon_as_answer_icon}
onChange={v => setInputInfo({ ...inputInfo, use_icon_as_answer_icon: v })}
/>
</div>
<p className='body-xs-regular text-gray-500'>{t('app.answerIcon.description')}</p>
<p className='body-xs-regular text-text-tertiary'>{t('app.answerIcon.description')}</p>
</div>
)}
<div className={`mt-6 mb-2 font-medium ${s.settingTitle} text-gray-900 `}>{t(`${prefixSettings}.language`)}</div>
<div className={cn('mt-6 mb-2 system-sm-semibold text-text-secondary')}>{t(`${prefixSettings}.language`)}</div>
<SimpleSelect
items={languages.filter(item => item.supported)}
defaultValue={language}
onSelect={item => setLanguage(item.value as Language)}
/>
<div className='w-full mt-8'>
<p className='system-xs-medium text-gray-500'>{t(`${prefixSettings}.workflow.title`)}</p>
<p className='system-xs-medium text-text-tertiary'>{t(`${prefixSettings}.workflow.title`)}</p>
<div className='flex justify-between items-center'>
<div className='font-medium system-sm-semibold grow text-gray-900'>{t(`${prefixSettings}.workflow.subTitle`)}</div>
<div className='font-medium system-sm-semibold grow text-text-primary'>{t(`${prefixSettings}.workflow.subTitle`)}</div>
<Switch
disabled={!(appInfo.mode === 'workflow' || appInfo.mode === 'advanced-chat')}
defaultValue={inputInfo.show_workflow_steps}
onChange={v => setInputInfo({ ...inputInfo, show_workflow_steps: v })}
/>
</div>
<p className='body-xs-regular text-gray-500'>{t(`${prefixSettings}.workflow.showDesc`)}</p>
<p className='body-xs-regular text-text-tertiary'>{t(`${prefixSettings}.workflow.showDesc`)}</p>
</div>
{isChat && <> <div className={`mt-8 font-medium ${s.settingTitle} text-gray-900`}>{t(`${prefixSettings}.chatColorTheme`)}</div>
<p className={`mt-1 ${s.settingsTip} text-gray-500`}>{t(`${prefixSettings}.chatColorThemeDesc`)}</p>
{isChat && <> <div className={cn('mt-8 system-sm-semibold text-text-secondary')}>{t(`${prefixSettings}.chatColorTheme`)}</div>
<p className='mt-1 body-xs-regular text-text-tertiary'>{t(`${prefixSettings}.chatColorThemeDesc`)}</p>
<Input
className='mt-2 h-10'
value={inputInfo.chatColorTheme ?? ''}
@ -262,14 +263,14 @@ const SettingsModal: FC<ISettingsModalProps> = ({
placeholder='E.g #A020F0'
/>
<div className="mt-1 flex justify-between items-center">
<p className={`ml-2 ${s.settingsTip} text-gray-500`}>{t(`${prefixSettings}.chatColorThemeInverted`)}</p>
<p className='ml-2 body-xs-regular text-text-tertiary'>{t(`${prefixSettings}.chatColorThemeInverted`)}</p>
<Switch defaultValue={inputInfo.chatColorThemeInverted} onChange={v => setInputInfo({ ...inputInfo, chatColorThemeInverted: v })}></Switch>
</div>
</>}
{systemFeatures.enable_web_sso_switch_component && <div className='w-full mt-8'>
<p className='system-xs-medium text-gray-500'>{t(`${prefixSettings}.sso.label`)}</p>
<p className='system-xs-medium text-text-tertiary'>{t(`${prefixSettings}.sso.label`)}</p>
<div className='flex justify-between items-center'>
<div className='font-medium system-sm-semibold grow text-gray-900'>{t(`${prefixSettings}.sso.title`)}</div>
<div className='system-sm-semibold grow text-text-secondary'>{t(`${prefixSettings}.sso.title`)}</div>
<Tooltip
disabled={systemFeatures.sso_enforced_for_web}
popupContent={
@ -280,31 +281,31 @@ const SettingsModal: FC<ISettingsModalProps> = ({
<Switch disabled={!systemFeatures.sso_enforced_for_web || !isCurrentWorkspaceEditor} defaultValue={systemFeatures.sso_enforced_for_web && inputInfo.enable_sso} onChange={v => setInputInfo({ ...inputInfo, enable_sso: v })}></Switch>
</Tooltip>
</div>
<p className='body-xs-regular text-gray-500'>{t(`${prefixSettings}.sso.description`)}</p>
<p className='body-xs-regular text-text-tertiary'>{t(`${prefixSettings}.sso.description`)}</p>
</div>}
{!isShowMore && <div className='w-full cursor-pointer mt-8' onClick={() => setIsShowMore(true)}>
<div className='flex justify-between'>
<div className={`font-medium ${s.settingTitle} grow text-gray-900`}>{t(`${prefixSettings}.more.entry`)}</div>
<div className='shrink-0 w-4 h-4 text-gray-500'>
<div className='system-sm-semibold text-text-secondary'>{t(`${prefixSettings}.more.entry`)}</div>
<div className='shrink-0 w-4 h-4 text-text-tertiary'>
<ChevronRightIcon />
</div>
</div>
<p className={`mt-1 ${s.policy} text-gray-500`}>{t(`${prefixSettings}.more.copyright`)} & {t(`${prefixSettings}.more.privacyPolicy`)}</p>
<p className='mt-1 body-xs-regular text-text-tertiary'>{t(`${prefixSettings}.more.copyright`)} & {t(`${prefixSettings}.more.privacyPolicy`)}</p>
</div>}
{isShowMore && <>
<hr className='w-full mt-6' />
<div className={`mt-6 font-medium ${s.settingTitle} text-gray-900`}>{t(`${prefixSettings}.more.copyright`)}</div>
<Divider className='my-6' />
<div className='system-sm-semibold text-text-secondary'>{t(`${prefixSettings}.more.copyright`)}</div>
<Input
className='mt-2 h-10'
value={inputInfo.copyright}
onChange={onChange('copyright')}
placeholder={t(`${prefixSettings}.more.copyRightPlaceholder`) as string}
/>
<div className={`mt-8 font-medium ${s.settingTitle} text-gray-900`}>{t(`${prefixSettings}.more.privacyPolicy`)}</div>
<p className={`mt-1 ${s.settingsTip} text-gray-500`}>
<div className='mt-8 system-sm-semibold text-text-secondary'>{t(`${prefixSettings}.more.privacyPolicy`)}</div>
<p className='mt-1 body-xs-regular text-text-tertiary'>
<Trans
i18nKey={`${prefixSettings}.more.privacyPolicyTip`}
components={{ privacyPolicyLink: <Link href={'https://docs.dify.ai/user-agreement/privacy-policy'} target='_blank' rel='noopener noreferrer' className='text-primary-600' /> }}
components={{ privacyPolicyLink: <Link href={'https://docs.dify.ai/user-agreement/privacy-policy'} target='_blank' rel='noopener noreferrer' className='text-text-accent' /> }}
/>
</p>
<Input
@ -313,8 +314,8 @@ const SettingsModal: FC<ISettingsModalProps> = ({
onChange={onChange('privacyPolicy')}
placeholder={t(`${prefixSettings}.more.privacyPolicyPlaceholder`) as string}
/>
<div className={`mt-8 font-medium ${s.settingTitle} text-gray-900`}>{t(`${prefixSettings}.more.customDisclaimer`)}</div>
<p className={`mt-1 ${s.settingsTip} text-gray-500`}>{t(`${prefixSettings}.more.customDisclaimerTip`)}</p>
<div className='mt-8 system-sm-semibold text-text-secondary'>{t(`${prefixSettings}.more.customDisclaimer`)}</div>
<p className='mt-1 body-xs-regular text-text-tertiary'>{t(`${prefixSettings}.more.customDisclaimerTip`)}</p>
<Input
className='mt-2 h-10'
value={inputInfo.customDisclaimer}

View File

@ -1,18 +0,0 @@
.settingsModal {
max-width: 32.5rem !important;
}
.settingTitle {
line-height: 21px;
font-size: 0.875rem;
}
.settingsTip {
line-height: 1.125rem;
font-size: 0.75rem;
}
.policy {
font-size: 0.75rem;
line-height: 1.125rem;
}

View File

@ -33,10 +33,10 @@ const InputCopy = ({
}, [isCopied])
return (
<div className={`flex rounded-lg bg-gray-50 hover:bg-gray-50 py-2 items-center ${className}`}>
<div className="flex items-center flex-grow h-5">
<div className={`flex rounded-lg bg-components-input-bg-normal hover:bg-state-base-hover py-2 items-center ${className}`}>
<div className="flex items-center grow h-5">
{children}
<div className='flex-grow bg-gray-50 text-[13px] relative h-full'>
<div className='grow text-[13px] relative h-full'>
<div className='absolute top-0 left-0 w-full pl-2 pr-2 truncate cursor-pointer r-0' onClick={() => {
copy(value)
setIsCopied(true)
@ -49,13 +49,13 @@ const InputCopy = ({
</Tooltip>
</div>
</div>
<div className="flex-shrink-0 h-4 bg-gray-200 border" />
<div className="shrink-0 h-4 bg-divider-regular border" />
<Tooltip
popupContent={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`}
position='bottom'
>
<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="px-0.5 shrink-0">
<div className={`box-border w-[30px] h-[30px] flex items-center justify-center rounded-lg hover:bg-state-base-hover cursor-pointer ${s.copyIcon} ${isCopied ? s.copied : ''}`} onClick={() => {
copy(value)
setIsCopied(true)
}}>

View File

@ -23,14 +23,14 @@ const SecretKeyGenerateModal = ({
const { t } = useTranslation()
return (
<Modal isShow={isShow} onClose={onClose} title={`${t('appApi.apiKeyModal.apiSecretKey')}`} className={`px-8 ${className}`}>
<XMarkIcon className={`w-6 h-6 absolute cursor-pointer text-gray-500 ${s.close}`} onClick={onClose} />
<p className='mt-1 text-[13px] text-gray-500 font-normal leading-5'>{t('appApi.apiKeyModal.generateTips')}</p>
<XMarkIcon className={`w-6 h-6 absolute cursor-pointer text-text-tertiary ${s.close}`} onClick={onClose} />
<p className='mt-1 text-[13px] text-text-tertiary font-normal leading-5'>{t('appApi.apiKeyModal.generateTips')}</p>
<div className='my-4'>
<InputCopy className='w-full' value={newKey?.token} />
</div>
<div className='flex justify-end my-4'>
<Button className={`flex-shrink-0 ${s.w64}`} onClick={onClose}>
<span className='text-xs font-medium text-gray-800'>{t('appApi.actionMsg.ok')}</span>
<Button className={`shrink-0 ${s.w64}`} onClick={onClose}>
<span className='text-xs font-medium text-text-secondary'>{t('appApi.actionMsg.ok')}</span>
</Button>
</div>

View File

@ -98,37 +98,37 @@ const SecretKeyModal = ({
return (
<Modal isShow={isShow} onClose={onClose} title={`${t('appApi.apiKeyModal.apiSecretKey')}`} className={`${s.customModal} px-8 flex flex-col`}>
<XMarkIcon className={`w-6 h-6 absolute cursor-pointer text-gray-500 ${s.close}`} onClick={onClose} />
<p className='mt-1 text-[13px] text-gray-500 font-normal leading-5 flex-shrink-0'>{t('appApi.apiKeyModal.apiSecretKeyTips')}</p>
<XMarkIcon className={`w-6 h-6 absolute cursor-pointer text-text-tertiary ${s.close}`} onClick={onClose} />
<p className='mt-1 text-[13px] text-text-tertiary font-normal leading-5 shrink-0'>{t('appApi.apiKeyModal.apiSecretKeyTips')}</p>
{!apiKeysList && <div className='mt-4'><Loading /></div>}
{
!!apiKeysList?.data?.length && (
<div className='flex flex-col flex-grow mt-4 overflow-hidden'>
<div className='flex items-center flex-shrink-0 text-xs font-semibold text-gray-500 border-b border-solid h-9'>
<div className='flex-shrink-0 w-64 px-3'>{t('appApi.apiKeyModal.secretKey')}</div>
<div className='flex-shrink-0 px-3 w-[200px]'>{t('appApi.apiKeyModal.created')}</div>
<div className='flex-shrink-0 px-3 w-[200px]'>{t('appApi.apiKeyModal.lastUsed')}</div>
<div className='flex-grow px-3'></div>
<div className='flex flex-col grow mt-4 overflow-hidden'>
<div className='flex items-center shrink-0 text-xs font-semibold text-text-tertiary border-b border-solid h-9'>
<div className='shrink-0 w-64 px-3'>{t('appApi.apiKeyModal.secretKey')}</div>
<div className='shrink-0 px-3 w-[200px]'>{t('appApi.apiKeyModal.created')}</div>
<div className='shrink-0 px-3 w-[200px]'>{t('appApi.apiKeyModal.lastUsed')}</div>
<div className='grow px-3'></div>
</div>
<div className='flex-grow overflow-auto'>
<div className='grow overflow-auto'>
{apiKeysList.data.map(api => (
<div className='flex items-center text-sm font-normal text-gray-700 border-b border-solid h-9' key={api.id}>
<div className='flex-shrink-0 w-64 px-3 font-mono truncate'>{generateToken(api.token)}</div>
<div className='flex-shrink-0 px-3 truncate w-[200px]'>{formatTime(Number(api.created_at), t('appLog.dateTimeFormat') as string)}</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 items-center text-sm font-normal text-text-secondary border-b border-solid h-9' key={api.id}>
<div className='shrink-0 w-64 px-3 font-mono truncate'>{generateToken(api.token)}</div>
<div className='shrink-0 px-3 truncate w-[200px]'>{formatTime(Number(api.created_at), t('appLog.dateTimeFormat') as string)}</div>
<div className='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 grow px-3'>
<Tooltip
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 shrink-0 w-6 h-6 mr-1 rounded-lg cursor-pointer hover:bg-state-base-hover ${s.copyIcon} ${copyValue === api.token ? s.copied : ''}`} onClick={() => {
// setIsCopied(true)
copy(api.token)
setCopyValue(api.token)
}}></div>
</Tooltip>
{isCurrentWorkspaceManager
&& <div className={`flex items-center justify-center flex-shrink-0 w-6 h-6 rounded-lg cursor-pointer ${s.trashIcon}`} onClick={() => {
&& <div className={`flex items-center justify-center shrink-0 w-6 h-6 rounded-lg cursor-pointer ${s.trashIcon}`} onClick={() => {
setDelKeyId(api.id)
setShowConfirmDelete(true)
}}>
@ -142,12 +142,12 @@ const SecretKeyModal = ({
)
}
<div className='flex'>
<Button className={`flex flex-shrink-0 mt-4 ${s.autoWidth}`} onClick={onCreate} disabled={!currentWorkspace || !isCurrentWorkspaceEditor}>
<PlusIcon className='flex flex-shrink-0 w-4 h-4' />
<div className='text-xs font-medium text-gray-800'>{t('appApi.apiKeyModal.createNewSecretKey')}</div>
<Button className={`flex shrink-0 mt-4 ${s.autoWidth}`} onClick={onCreate} disabled={!currentWorkspace || !isCurrentWorkspaceEditor}>
<PlusIcon className='flex shrink-0 w-4 h-4 mr-1' />
<div className='text-xs font-medium text-text-secondary'>{t('appApi.apiKeyModal.createNewSecretKey')}</div>
</Button>
</div>
<SecretKeyGenerateModal className='flex-shrink-0' isShow={isVisible} onClose={() => setVisible(false)} newKey={newKey} />
<SecretKeyGenerateModal className='shrink-0' isShow={isVisible} onClose={() => setVisible(false)} newKey={newKey} />
{showConfirmDelete && (
<Confirm
title={`${t('appApi.actionMsg.deleteConfirmTitle')}`}

View File

@ -27,7 +27,7 @@ const PluginsNav = ({
return (
<Link href="/plugins" className={classNames(
className, 'group',
className, 'group', 'plugins-nav-button', // used for use-fold-anim-into.ts
)}>
<div
className={classNames(

View File

@ -1,6 +1,6 @@
import { sleep } from '@/utils'
const animTime = 2000
const animTime = 750
const modalClassName = 'install-modal'
const COUNT_DOWN_TIME = 15000 // 15s
@ -21,7 +21,7 @@ const useFoldAnimInto = (onClose: () => void) => {
const foldIntoAnim = async () => {
clearCountDown()
const modalElem = document.querySelector(`.${modalClassName}`) as HTMLElement
const pluginTaskTriggerElem = document.getElementById('plugin-task-trigger')
const pluginTaskTriggerElem = document.getElementById('plugin-task-trigger') || document.querySelector('.plugins-nav-button')
if (!modalElem || !pluginTaskTriggerElem) {
onClose()

View File

@ -144,6 +144,7 @@ const AllTools = ({
wrapElemRef={wrapElemRef}
list={notInstalledPlugins as any} ref={pluginRef}
searchText={searchText}
toolContentClassName={toolContentClassName}
tags={tags}
/>
</div>

View File

@ -15,6 +15,7 @@ type Props = {
list: Plugin[]
searchText: string
tags: string[]
toolContentClassName?: string
disableMaxWidth?: boolean
}
@ -23,6 +24,7 @@ const List = forwardRef<{ handleScroll: () => void }, Props>(({
searchText,
tags,
list,
toolContentClassName,
disableMaxWidth = false,
}, ref) => {
const { t } = useTranslation()
@ -76,7 +78,7 @@ const List = forwardRef<{ handleScroll: () => void }, Props>(({
)
}
const maxWidthClassName = 'max-w-[300px]'
const maxWidthClassName = toolContentClassName || 'max-w-[300px]'
return (
<>