feat: add external api
parent
19c526120c
commit
fbedd08292
@ -0,0 +1,5 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Icon L">
|
||||
<path id="Vector" fill-rule="evenodd" clip-rule="evenodd" d="M7.99996 3.33333C5.42263 3.33333 3.33329 5.42267 3.33329 8C3.33329 10.5773 5.42263 12.6667 7.99996 12.6667C9.72643 12.6667 11.2348 11.7295 12.0427 10.3329C12.227 10.0141 12.6349 9.90523 12.9536 10.0896C13.2723 10.274 13.3812 10.6818 13.1968 11.0005C12.1604 12.7921 10.2216 14 7.99996 14C4.91159 14 2.36821 11.6666 2.03658 8.66667H1.33329C0.965103 8.66667 0.666626 8.36819 0.666626 8C0.666626 7.63181 0.965103 7.33333 1.33329 7.33333H2.03658C2.36821 4.33337 4.91159 2 7.99996 2C10.2216 2 12.1604 3.20785 13.1968 4.99952C13.3812 5.31823 13.2723 5.72605 12.9536 5.91041C12.6349 6.09477 12.227 5.98585 12.0427 5.66714C11.2348 4.27054 9.72643 3.33333 7.99996 3.33333ZM7.99996 6C6.89539 6 5.99996 6.89543 5.99996 8C5.99996 9.10455 6.89539 10 7.99996 10C9.1045 10 9.99996 9.10454 9.99996 8C9.99996 6.89543 9.10451 6 7.99996 6ZM4.66663 8C4.66663 6.15905 6.15901 4.66667 7.99996 4.66667C9.61257 4.66667 10.9578 5.81184 11.2666 7.33333H14.6666C15.0348 7.33333 15.3333 7.63181 15.3333 8C15.3333 8.36819 15.0348 8.66667 14.6666 8.66667H11.2666C10.9578 10.1881 9.61257 11.3333 7.99996 11.3333C6.159 11.3333 4.66663 9.84092 4.66663 8Z" fill="#354052"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@ -0,0 +1,38 @@
|
||||
{
|
||||
"icon": {
|
||||
"type": "element",
|
||||
"isRootNode": true,
|
||||
"name": "svg",
|
||||
"attributes": {
|
||||
"width": "16",
|
||||
"height": "16",
|
||||
"viewBox": "0 0 16 16",
|
||||
"fill": "none",
|
||||
"xmlns": "http://www.w3.org/2000/svg"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "element",
|
||||
"name": "g",
|
||||
"attributes": {
|
||||
"id": "Icon L"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "element",
|
||||
"name": "path",
|
||||
"attributes": {
|
||||
"id": "Vector",
|
||||
"fill-rule": "evenodd",
|
||||
"clip-rule": "evenodd",
|
||||
"d": "M7.99996 3.33333C5.42263 3.33333 3.33329 5.42267 3.33329 8C3.33329 10.5773 5.42263 12.6667 7.99996 12.6667C9.72643 12.6667 11.2348 11.7295 12.0427 10.3329C12.227 10.0141 12.6349 9.90523 12.9536 10.0896C13.2723 10.274 13.3812 10.6818 13.1968 11.0005C12.1604 12.7921 10.2216 14 7.99996 14C4.91159 14 2.36821 11.6666 2.03658 8.66667H1.33329C0.965103 8.66667 0.666626 8.36819 0.666626 8C0.666626 7.63181 0.965103 7.33333 1.33329 7.33333H2.03658C2.36821 4.33337 4.91159 2 7.99996 2C10.2216 2 12.1604 3.20785 13.1968 4.99952C13.3812 5.31823 13.2723 5.72605 12.9536 5.91041C12.6349 6.09477 12.227 5.98585 12.0427 5.66714C11.2348 4.27054 9.72643 3.33333 7.99996 3.33333ZM7.99996 6C6.89539 6 5.99996 6.89543 5.99996 8C5.99996 9.10455 6.89539 10 7.99996 10C9.1045 10 9.99996 9.10454 9.99996 8C9.99996 6.89543 9.10451 6 7.99996 6ZM4.66663 8C4.66663 6.15905 6.15901 4.66667 7.99996 4.66667C9.61257 4.66667 10.9578 5.81184 11.2666 7.33333H14.6666C15.0348 7.33333 15.3333 7.63181 15.3333 8C15.3333 8.36819 15.0348 8.66667 14.6666 8.66667H11.2666C10.9578 10.1881 9.61257 11.3333 7.99996 11.3333C6.159 11.3333 4.66663 9.84092 4.66663 8Z",
|
||||
"fill": "currentColor"
|
||||
},
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": "ApiConnectionMod"
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
// GENERATE BY script
|
||||
// DON NOT EDIT IT MANUALLY
|
||||
|
||||
import * as React from 'react'
|
||||
import data from './ApiConnectionMod.json'
|
||||
import IconBase from '@/app/components/base/icons/IconBase'
|
||||
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
|
||||
|
||||
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
|
||||
props,
|
||||
ref,
|
||||
) => <IconBase {...props} ref={ref} data={data as IconData} />)
|
||||
|
||||
Icon.displayName = 'ApiConnectionMod'
|
||||
|
||||
export default Icon
|
||||
@ -0,0 +1,141 @@
|
||||
import type { FC } from 'react'
|
||||
import {
|
||||
memo,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
RiCloseLine,
|
||||
RiInformation2Line,
|
||||
RiLock2Fill,
|
||||
} from '@remixicon/react'
|
||||
import { useToastContext } from '@/app/components/base/toast'
|
||||
import {
|
||||
PortalToFollowElem,
|
||||
PortalToFollowElemContent,
|
||||
} from '@/app/components/base/portal-to-follow-elem'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Input from '@/app/components/base/input'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
|
||||
type AddExternalAPIModalProps = {
|
||||
show: boolean
|
||||
onHide: () => void
|
||||
}
|
||||
|
||||
const AddExternalAPIModal: FC<AddExternalAPIModalProps> = ({ show, onHide }) => {
|
||||
const { t } = useTranslation()
|
||||
const { notify } = useToastContext()
|
||||
const [showConfirm, setShowConfirm] = useState(false)
|
||||
const [formData, setFormData] = useState({ name: '', endpoint: '', apiKey: '' })
|
||||
const isEditMode = true
|
||||
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { name, value } = e.target
|
||||
setFormData({ ...formData, [name]: value })
|
||||
}
|
||||
|
||||
const handleFormSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
// Handle form submission logic here
|
||||
console.log('Form Data:', formData)
|
||||
onHide()
|
||||
}
|
||||
|
||||
return (
|
||||
<PortalToFollowElem open>
|
||||
<PortalToFollowElemContent className='w-full h-full z-[60]'>
|
||||
<div className='fixed inset-0 flex items-center justify-center bg-black/[.25]'>
|
||||
<div className='flex relative w-[480px] flex-col items-start bg-components-panel-bg rounded-2xl border-[0.5px] border-components-panel-border shadows-shadow-xl'>
|
||||
<div className='flex flex-col pt-6 pl-6 pb-3 pr-14 items-start gap-2 self-stretch'>
|
||||
<div className='self-stretch text-text-primary title-2xl-semi-bold flex-grow'>
|
||||
{
|
||||
isEditMode ? t('dataset.editExternalAPIFormTitle') : t('dataset.createExternalAPIFormTitle')
|
||||
}
|
||||
</div>
|
||||
{isEditMode && (
|
||||
<div className='text-text-tertiary system-xs-regular flex items-center'>
|
||||
{t('dataset.editExternalAPIFormWarning.front')}
|
||||
<span className='text-text-accent cursor-pointer flex items-center'>
|
||||
3 {t('dataset.editExternalAPIFormWarning.end')} <Tooltip popupContent={'3 LINKED KNOWLEDGE --- needs to be modified'} asChild={false} position='bottom'><RiInformation2Line className='w-3.5 h-3.5' /></Tooltip>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<ActionButton className='absolute top-5 right-5' onClick={onHide}>
|
||||
<RiCloseLine className='w-[18px] h-[18px] text-text-tertiary flex-shrink-0' />
|
||||
</ActionButton>
|
||||
<form onSubmit={handleFormSubmit} className='flex px-6 py-3 flex-col justify-center items-start gap-4 self-stretch'>
|
||||
<div className='flex flex-col justify-center items-start gap-4 self-stretch'>
|
||||
<div className='flex flex-col items-start gap-1 self-stretch'>
|
||||
<label className='text-text-secondary system-sm-semibold' htmlFor='name'>
|
||||
{t('dataset.externalAPIForm.name')}
|
||||
</label>
|
||||
<Input
|
||||
type='text'
|
||||
id='name'
|
||||
name='name'
|
||||
value={formData.name}
|
||||
onChange={handleInputChange}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className='flex flex-col items-start gap-1 self-stretch'>
|
||||
<label className='text-text-secondary system-sm-semibold' htmlFor='endpoint'>
|
||||
{t('dataset.externalAPIForm.endpoint')}
|
||||
</label>
|
||||
<Input
|
||||
type='text'
|
||||
id='endpoint'
|
||||
name='endpoint'
|
||||
value={formData.endpoint}
|
||||
onChange={handleInputChange}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className='flex flex-col items-start gap-1 self-stretch'>
|
||||
<label className='text-text-secondary system-sm-semibold' htmlFor='apiKey'>
|
||||
{t('dataset.externalAPIForm.apiKey')}
|
||||
</label>
|
||||
<Input
|
||||
type='text'
|
||||
id='apiKey'
|
||||
name='apiKey'
|
||||
value={formData.apiKey}
|
||||
onChange={handleInputChange}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div className='flex p-6 pt-5 justify-end items-center gap-2 self-stretch'>
|
||||
<Button type='button' variant='secondary' onClick={onHide}>
|
||||
{t('dataset.externalAPIForm.cancel')}
|
||||
</Button>
|
||||
<Button type='submit' variant='primary'>
|
||||
{t('dataset.externalAPIForm.save')}
|
||||
</Button>
|
||||
</div>
|
||||
<div className='flex px-2 py-3 justify-center items-center gap-1 self-stretch rounded-b-2xl
|
||||
border-t-[0.5px] border-divider-subtle bg-background-soft text-text-tertiary system-xs-regular'
|
||||
>
|
||||
<RiLock2Fill className='w-3 h-3 text-text-quaternary' />
|
||||
{t('dataset.externalAPIForm.encrypted.front')}
|
||||
<a
|
||||
className='text-text-accent'
|
||||
target='_blank' rel='noopener noreferrer'
|
||||
href='https://pycryptodome.readthedocs.io/en/latest/src/cipher/oaep.html'
|
||||
>
|
||||
PKCS1_OAEP
|
||||
</a>
|
||||
{t('dataset.externalAPIForm.encrypted.end')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</PortalToFollowElemContent>
|
||||
</PortalToFollowElem>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(AddExternalAPIModal)
|
||||
@ -0,0 +1,70 @@
|
||||
import React from 'react'
|
||||
import {
|
||||
RiAddLine,
|
||||
RiBookOpenLine,
|
||||
RiCloseLine,
|
||||
} from '@remixicon/react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import cn from '@/utils/classnames'
|
||||
// import AddExternalAPIForm from '../create/add-external-api'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { useModalContext } from '@/context/modal-context'
|
||||
|
||||
type ExternalAPIPanelProps = {
|
||||
onClose: () => void
|
||||
isShow: boolean
|
||||
}
|
||||
|
||||
const ExternalAPIPanel: React.FC<ExternalAPIPanelProps> = ({ onClose, isShow }) => {
|
||||
const { t } = useTranslation()
|
||||
const { setShowExternalAPIModal } = useModalContext()
|
||||
|
||||
const handleOpenExternalAPIModal = () => {
|
||||
setShowExternalAPIModal()
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
tabIndex={-1}
|
||||
className={cn('absolute top-14 right-0 bottom-2 flex z-10 outline-none')}
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
'relative flex flex-col w-[420px] bg-components-panel-bg-alt rounded-l-2xl h-full border border-components-panel-border',
|
||||
)}
|
||||
>
|
||||
<div className='flex items-start self-stretch p-4 pb-0'>
|
||||
<div className='flex flex-col items-start gap-1 flex-grow'>
|
||||
<div className='self-stretch text-text-primary system-xl-semibold'>{t('dataset.externalAPIPanelTitle')}</div>
|
||||
<div className='self-stretch text-text-tertiary body-xs-regular'>{t('dataset.externalAPIPanelDescription')}</div>
|
||||
<a className='flex justify-center items-center gap-1 self-stretch cursor-pointer' href='https://docs.dify.ai/docs/external-api' target='_blank'>
|
||||
<RiBookOpenLine className='w-3 h-3 text-text-accent' />
|
||||
<div className='flex-grow text-text-accent body-xs-regular'>{t('dataset.externalAPIPanelDocumentation')}</div>
|
||||
</a>
|
||||
</div>
|
||||
<div className='flex items-center'>
|
||||
<ActionButton onClick={() => onClose()}>
|
||||
<RiCloseLine className='w-4 h-4 text-text-tertiary' />
|
||||
</ActionButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex px-4 py-3 flex-col justify-center items-start gap-2 self-stretch'>
|
||||
<Button
|
||||
variant={'primary'}
|
||||
className='flex justify-center items-center px-3 py-2 gap-0.5'
|
||||
onClick={handleOpenExternalAPIModal}
|
||||
>
|
||||
<RiAddLine className='w-4 h-4 text-components-button-primary-text' />
|
||||
<div className='text-components-button-primary-text system-sm-medium'>{t('dataset.createExternalAPI')}</div>
|
||||
</Button>
|
||||
</div>
|
||||
<div className='flex py-0 px-4 flex-col items-start gap-1 flex-grow self-stretch'>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ExternalAPIPanel
|
||||
Loading…
Reference in New Issue