mirror of
https://github.com/langgenius/dify.git
synced 2026-06-17 14:51:10 +08:00
Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: yyh <yuanyouhuilyz@gmail.com> Co-authored-by: Joel <iamjoel007@gmail.com> Co-authored-by: hjlarry <hjlarry@163.com> Co-authored-by: fatelei <fatelei@gmail.com> Co-authored-by: Asuka Minato <i@asukaminato.eu.org> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Xiyuan Chen <52963600+GareArc@users.noreply.github.com> Co-authored-by: gigglewang <gigglewang@dify.ai> Co-authored-by: Yunlu Wen <yunlu.wen@dify.ai> Co-authored-by: chariri <w@chariri.moe> Co-authored-by: Evan <2869018789@qq.com> Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
116 lines
3.9 KiB
TypeScript
116 lines
3.9 KiB
TypeScript
'use client'
|
|
|
|
import type { ReactNode } from 'react'
|
|
import { useSuspenseQuery } from '@tanstack/react-query'
|
|
import { noop } from 'es-toolkit/function'
|
|
import { useMemo, useState } from 'react'
|
|
import InstallFromLocalPackage from '@/app/components/plugins/install-plugin/install-from-local-package'
|
|
import { usePluginPageContext } from '@/app/components/plugins/plugin-page/context'
|
|
import { PluginPageContextProvider } from '@/app/components/plugins/plugin-page/context-provider'
|
|
import PluginsPanel from '@/app/components/plugins/plugin-page/plugins-panel'
|
|
import { useUploader } from '@/app/components/plugins/plugin-page/use-uploader'
|
|
import { PluginCategoryEnum } from '@/app/components/plugins/types'
|
|
import { SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS } from '@/config'
|
|
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
|
|
|
type PluginCategoryPageProps = {
|
|
canInstall?: boolean
|
|
category: PluginCategoryEnum
|
|
layout?: (parts: { body: ReactNode, toolbar: ReactNode }) => ReactNode
|
|
onSwitchToMarketplace?: () => void
|
|
toolbarAction?: ReactNode
|
|
}
|
|
|
|
const supportedLocalPackageExtensions = SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS.split(',')
|
|
|
|
const PluginCategoryPageContent = ({
|
|
canInstall = true,
|
|
category,
|
|
layout,
|
|
onSwitchToMarketplace,
|
|
toolbarAction,
|
|
}: PluginCategoryPageProps) => {
|
|
const [currentFile, setCurrentFile] = useState<File | null>(null)
|
|
const containerRef = usePluginPageContext(v => v.containerRef)
|
|
const { data: pluginInstallationPermission } = useSuspenseQuery({
|
|
...systemFeaturesQueryOptions(),
|
|
select: s => s.plugin_installation_permission,
|
|
})
|
|
const supportsDropInstall = category === PluginCategoryEnum.tool || category === PluginCategoryEnum.trigger || category === PluginCategoryEnum.agent || category === PluginCategoryEnum.extension
|
|
const canDropLocalPackage = canInstall && supportsDropInstall && !pluginInstallationPermission.restrict_to_marketplace_only
|
|
|
|
const handleFileChange = (file: File | null) => {
|
|
if (!canInstall) {
|
|
setCurrentFile(null)
|
|
return
|
|
}
|
|
|
|
if (!file || !supportedLocalPackageExtensions.some(extension => file.name.endsWith(extension))) {
|
|
setCurrentFile(null)
|
|
return
|
|
}
|
|
|
|
setCurrentFile(file)
|
|
}
|
|
const {
|
|
dragging,
|
|
fileUploader,
|
|
fileChangeHandle,
|
|
removeFile,
|
|
} = useUploader({
|
|
onFileChange: handleFileChange,
|
|
containerRef,
|
|
enabled: canDropLocalPackage,
|
|
})
|
|
|
|
return (
|
|
<div ref={containerRef} className="relative flex h-0 grow flex-col overflow-hidden bg-components-panel-bg">
|
|
<PluginsPanel canInstall={canInstall} contentInset="compact" fixedCategory={category} layout={layout} onSwitchToMarketplace={onSwitchToMarketplace} toolbarAction={toolbarAction} />
|
|
{dragging && (
|
|
<div
|
|
className="absolute inset-0 m-0.5 rounded-2xl border-2 border-dashed border-components-dropzone-border-accent
|
|
bg-[rgba(21,90,239,0.14)] p-2"
|
|
/>
|
|
)}
|
|
{currentFile && (
|
|
<InstallFromLocalPackage
|
|
file={currentFile}
|
|
installContextCategory={category}
|
|
onClose={removeFile ?? noop}
|
|
onSuccess={noop}
|
|
/>
|
|
)}
|
|
<input
|
|
ref={fileUploader}
|
|
className="hidden"
|
|
type="file"
|
|
id="fileUploader"
|
|
accept={SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS}
|
|
onChange={fileChangeHandle ?? noop}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const PluginCategoryPage = ({
|
|
canInstall = true,
|
|
category,
|
|
layout,
|
|
onSwitchToMarketplace,
|
|
toolbarAction,
|
|
}: PluginCategoryPageProps) => {
|
|
const initialFilters = useMemo(() => ({
|
|
categories: [category],
|
|
tags: [],
|
|
searchQuery: '',
|
|
}), [category])
|
|
|
|
return (
|
|
<PluginPageContextProvider key={category} initialFilters={initialFilters}>
|
|
<PluginCategoryPageContent canInstall={canInstall} category={category} layout={layout} onSwitchToMarketplace={onSwitchToMarketplace} toolbarAction={toolbarAction} />
|
|
</PluginPageContextProvider>
|
|
)
|
|
}
|
|
|
|
export default PluginCategoryPage
|