mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-17 03:05:52 +08:00
marketplace
This commit is contained in:
parent
f111e605c4
commit
76f6b8d104
@ -6,7 +6,6 @@ import {
|
|||||||
RiArrowRightUpLine,
|
RiArrowRightUpLine,
|
||||||
RiBugLine,
|
RiBugLine,
|
||||||
RiClipboardLine,
|
RiClipboardLine,
|
||||||
RiDragDropLine,
|
|
||||||
RiEqualizer2Line,
|
RiEqualizer2Line,
|
||||||
} from '@remixicon/react'
|
} from '@remixicon/react'
|
||||||
import InstallPluginDropdown from './InstallPluginDropdown'
|
import InstallPluginDropdown from './InstallPluginDropdown'
|
||||||
@ -16,12 +15,18 @@ import Button from '@/app/components/base/button'
|
|||||||
import TabSlider from '@/app/components/base/tab-slider'
|
import TabSlider from '@/app/components/base/tab-slider'
|
||||||
import ActionButton from '@/app/components/base/action-button'
|
import ActionButton from '@/app/components/base/action-button'
|
||||||
import Tooltip from '@/app/components/base/tooltip'
|
import Tooltip from '@/app/components/base/tooltip'
|
||||||
import Marketplace from '@/app/components/plugins/marketplace'
|
|
||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
|
|
||||||
const Container = () => {
|
type ContainerWrapperProps = {
|
||||||
|
plugins: React.ReactNode
|
||||||
|
marketplace: React.ReactNode
|
||||||
|
}
|
||||||
|
const ContainerWrapper = ({
|
||||||
|
plugins,
|
||||||
|
marketplace,
|
||||||
|
}: ContainerWrapperProps) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { setShowPluginSettingModal } = useModalContext()
|
const { setShowPluginSettingModal } = useModalContext() as any
|
||||||
|
|
||||||
const options = useMemo(() => {
|
const options = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
@ -104,31 +109,13 @@ const Container = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
activeTab === 'plugins' && (
|
activeTab === 'plugins' && plugins
|
||||||
<>
|
|
||||||
<div className='flex flex-col pt-1 pb-3 px-12 justify-center items-start gap-3 self-stretch'>
|
|
||||||
<div className='h-px self-stretch bg-divider-subtle'></div>
|
|
||||||
<div className='flex items-center gap-2 self-stretch'>
|
|
||||||
{/* Filter goes here */}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className='flex px-12 items-start content-start gap-2 flex-grow self-stretch flex-wrap'>
|
|
||||||
{/* Plugin cards go here */}
|
|
||||||
</div>
|
|
||||||
<div className='flex items-center justify-center py-4 gap-2 text-text-quaternary'>
|
|
||||||
<RiDragDropLine className='w-4 h-4' />
|
|
||||||
<span className='system-xs-regular'>Drop plugin package here to install</span>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
activeTab === 'discover' && (
|
activeTab === 'discover' && marketplace
|
||||||
<Marketplace />
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Container
|
export default ContainerWrapper
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
import Container from './Container'
|
import PluginsPanel from './plugins-panel'
|
||||||
|
import Container from './container'
|
||||||
|
import Marketplace from '@/app/components/plugins/marketplace'
|
||||||
|
|
||||||
const PluginList = async () => {
|
const PluginList = async () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<Container
|
||||||
<Container />
|
plugins={<PluginsPanel />}
|
||||||
</>
|
marketplace={<Marketplace />}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
25
web/app/(commonLayout)/plugins/plugins-panel.tsx
Normal file
25
web/app/(commonLayout)/plugins/plugins-panel.tsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { RiDragDropLine } from '@remixicon/react'
|
||||||
|
|
||||||
|
const PluginsPanel = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className='flex flex-col pt-1 pb-3 px-12 justify-center items-start gap-3 self-stretch'>
|
||||||
|
<div className='h-px self-stretch bg-divider-subtle'></div>
|
||||||
|
<div className='flex items-center gap-2 self-stretch'>
|
||||||
|
{/* Filter goes here */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='flex px-12 items-start content-start gap-2 flex-grow self-stretch flex-wrap'>
|
||||||
|
{/* Plugin cards go here */}
|
||||||
|
</div>
|
||||||
|
<div className='flex items-center justify-center py-4 gap-2 text-text-quaternary'>
|
||||||
|
<RiDragDropLine className='w-4 h-4' />
|
||||||
|
<span className='system-xs-regular'>Drop plugin package here to install</span>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PluginsPanel
|
@ -1,12 +1,41 @@
|
|||||||
import MarketplaceWrapper from './marketplace-wrapper'
|
import SearchBox from './search-box'
|
||||||
import Marketplace from './marketplace'
|
import PluginTypeSwitch from './plugin-type-switch'
|
||||||
|
import List from './list'
|
||||||
|
|
||||||
const MarketplacePage = () => {
|
const Marketplace = () => {
|
||||||
return (
|
return (
|
||||||
<MarketplaceWrapper>
|
<div className='w-full'>
|
||||||
<Marketplace />
|
<div className='py-10'>
|
||||||
</MarketplaceWrapper>
|
<h1 className='mb-2 text-center title-4xl-semi-bold text-text-primary'>
|
||||||
|
Empower your AI development
|
||||||
|
</h1>
|
||||||
|
<h2 className='flex justify-center items-center mb-4 text-center body-md-regular text-text-tertiary'>
|
||||||
|
Discover
|
||||||
|
<span className="relative ml-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected">
|
||||||
|
models
|
||||||
|
</span>
|
||||||
|
,
|
||||||
|
<span className="relative ml-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected">
|
||||||
|
tools
|
||||||
|
</span>
|
||||||
|
,
|
||||||
|
<span className="relative ml-1 mr-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected">
|
||||||
|
extensions
|
||||||
|
</span>
|
||||||
|
and
|
||||||
|
<span className="relative ml-1 mr-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected">
|
||||||
|
bundles
|
||||||
|
</span>
|
||||||
|
in Dify Marketplace
|
||||||
|
</h2>
|
||||||
|
<div className='flex items-center justify-center mb-4'>
|
||||||
|
<SearchBox />
|
||||||
|
</div>
|
||||||
|
<PluginTypeSwitch />
|
||||||
|
</div>
|
||||||
|
<List />
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MarketplacePage
|
export default Marketplace
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import Card from '@/app/components/plugins/card'
|
import Card from '@/app/components/plugins/card'
|
||||||
import CardMoreInfo from '@/app/components/plugins/card/card-more-info'
|
import CardMoreInfo from '@/app/components/plugins/card/card-more-info'
|
||||||
import { toolNotion } from '@/app/components/plugins/card/card-mock'
|
import { toolNotion } from '@/app/components/plugins/card/card-mock'
|
||||||
|
import { getLocaleOnServer } from '@/i18n/server'
|
||||||
|
|
||||||
const List = () => {
|
const List = () => {
|
||||||
|
const locale = getLocaleOnServer()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='px-12 py-2 bg-background-default-subtle'>
|
<div className='px-12 py-2 bg-background-default-subtle'>
|
||||||
<div className='py-3'>
|
<div className='py-3'>
|
||||||
@ -10,30 +13,35 @@ const List = () => {
|
|||||||
<div className='system-xs-regular text-text-tertiary'>Our top picks to get you started</div>
|
<div className='system-xs-regular text-text-tertiary'>Our top picks to get you started</div>
|
||||||
<div className='grid grid-cols-4 gap-3 mt-2'>
|
<div className='grid grid-cols-4 gap-3 mt-2'>
|
||||||
<Card
|
<Card
|
||||||
|
locale={locale}
|
||||||
payload={toolNotion as any}
|
payload={toolNotion as any}
|
||||||
footer={
|
footer={
|
||||||
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Card
|
<Card
|
||||||
|
locale={locale}
|
||||||
payload={toolNotion as any}
|
payload={toolNotion as any}
|
||||||
footer={
|
footer={
|
||||||
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Card
|
<Card
|
||||||
|
locale={locale}
|
||||||
payload={toolNotion as any}
|
payload={toolNotion as any}
|
||||||
footer={
|
footer={
|
||||||
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Card
|
<Card
|
||||||
|
locale={locale}
|
||||||
payload={toolNotion as any}
|
payload={toolNotion as any}
|
||||||
footer={
|
footer={
|
||||||
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Card
|
<Card
|
||||||
|
locale={locale}
|
||||||
payload={toolNotion as any}
|
payload={toolNotion as any}
|
||||||
footer={
|
footer={
|
||||||
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
||||||
@ -46,36 +54,42 @@ const List = () => {
|
|||||||
<div className='system-xs-regular text-text-tertiary'>Explore the library and discover the incredible work of our community</div>
|
<div className='system-xs-regular text-text-tertiary'>Explore the library and discover the incredible work of our community</div>
|
||||||
<div className='grid grid-cols-4 gap-3 mt-2'>
|
<div className='grid grid-cols-4 gap-3 mt-2'>
|
||||||
<Card
|
<Card
|
||||||
|
locale={locale}
|
||||||
payload={toolNotion as any}
|
payload={toolNotion as any}
|
||||||
footer={
|
footer={
|
||||||
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Card
|
<Card
|
||||||
|
locale={locale}
|
||||||
payload={toolNotion as any}
|
payload={toolNotion as any}
|
||||||
footer={
|
footer={
|
||||||
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Card
|
<Card
|
||||||
|
locale={locale}
|
||||||
payload={toolNotion as any}
|
payload={toolNotion as any}
|
||||||
footer={
|
footer={
|
||||||
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Card
|
<Card
|
||||||
|
locale={locale}
|
||||||
payload={toolNotion as any}
|
payload={toolNotion as any}
|
||||||
footer={
|
footer={
|
||||||
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Card
|
<Card
|
||||||
|
locale={locale}
|
||||||
payload={toolNotion as any}
|
payload={toolNotion as any}
|
||||||
footer={
|
footer={
|
||||||
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Card
|
<Card
|
||||||
|
locale={locale}
|
||||||
payload={toolNotion as any}
|
payload={toolNotion as any}
|
||||||
footer={
|
footer={
|
||||||
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
<CardMoreInfo downloadCount={1234} tags={['Search', 'Productivity']} />
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
type WrapperProps = {
|
|
||||||
children: React.ReactNode
|
|
||||||
}
|
|
||||||
const MarketplaceWrapper = ({
|
|
||||||
children,
|
|
||||||
}: WrapperProps) => {
|
|
||||||
return children
|
|
||||||
}
|
|
||||||
|
|
||||||
export default MarketplaceWrapper
|
|
@ -1,41 +0,0 @@
|
|||||||
import SearchBox from './search-box'
|
|
||||||
import PluginTypeSwitch from './plugin-type-switch'
|
|
||||||
import List from './list'
|
|
||||||
|
|
||||||
const Marketplace = () => {
|
|
||||||
return (
|
|
||||||
<div className='w-full'>
|
|
||||||
<div className='py-10'>
|
|
||||||
<h1 className='mb-2 text-center title-4xl-semi-bold text-text-primary'>
|
|
||||||
Empower your AI development
|
|
||||||
</h1>
|
|
||||||
<h2 className='flex justify-center items-center mb-4 text-center body-md-regular text-text-tertiary'>
|
|
||||||
Discover
|
|
||||||
<span className="relative ml-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected">
|
|
||||||
models
|
|
||||||
</span>
|
|
||||||
,
|
|
||||||
<span className="relative ml-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected">
|
|
||||||
tools
|
|
||||||
</span>
|
|
||||||
,
|
|
||||||
<span className="relative ml-1 mr-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected">
|
|
||||||
extensions
|
|
||||||
</span>
|
|
||||||
and
|
|
||||||
<span className="relative ml-1 mr-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected">
|
|
||||||
bundles
|
|
||||||
</span>
|
|
||||||
in Dify Marketplace
|
|
||||||
</h2>
|
|
||||||
<div className='flex items-center justify-center mb-4'>
|
|
||||||
<SearchBox onChange={() => {}} />
|
|
||||||
</div>
|
|
||||||
<PluginTypeSwitch onChange={() => {}} />
|
|
||||||
</div>
|
|
||||||
<List />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Marketplace
|
|
@ -8,7 +8,7 @@ import {
|
|||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
|
|
||||||
type PluginTypeSwitchProps = {
|
type PluginTypeSwitchProps = {
|
||||||
onChange: (type: string) => void
|
onChange?: (type: string) => void
|
||||||
}
|
}
|
||||||
const options = [
|
const options = [
|
||||||
{
|
{
|
||||||
@ -54,7 +54,7 @@ const PluginTypeSwitch = ({
|
|||||||
)}
|
)}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setActiveType(option.value)
|
setActiveType(option.value)
|
||||||
onChange(option.value)
|
onChange?.(option.value)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{option.icon}
|
{option.icon}
|
||||||
|
@ -9,7 +9,7 @@ import TagsFilter from './tags-filter'
|
|||||||
import ActionButton from '@/app/components/base/action-button'
|
import ActionButton from '@/app/components/base/action-button'
|
||||||
|
|
||||||
type SearchBoxProps = {
|
type SearchBoxProps = {
|
||||||
onChange: (searchText: string, tags: string[]) => void
|
onChange?: (searchText: string, tags: string[]) => void
|
||||||
}
|
}
|
||||||
const SearchBox = ({
|
const SearchBox = ({
|
||||||
onChange,
|
onChange,
|
||||||
@ -19,7 +19,7 @@ const SearchBox = ({
|
|||||||
|
|
||||||
const handleTagsChange = useCallback((tags: string[]) => {
|
const handleTagsChange = useCallback((tags: string[]) => {
|
||||||
setSelectedTags(tags)
|
setSelectedTags(tags)
|
||||||
onChange(searchText, tags)
|
onChange?.(searchText, tags)
|
||||||
}, [searchText, onChange])
|
}, [searchText, onChange])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -36,7 +36,7 @@ const SearchBox = ({
|
|||||||
value={searchText}
|
value={searchText}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setSearchText(e.target.value)
|
setSearchText(e.target.value)
|
||||||
onChange(e.target.value, selectedTags)
|
onChange?.(e.target.value, selectedTags)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user