mirror of
https://github.com/langgenius/dify.git
synced 2026-04-22 16:06:55 +08:00
feat: add to workspace api
This commit is contained in:
parent
c42ccdfc6f
commit
78fbbded1a
@ -1,19 +1,15 @@
|
|||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Sidebar from '@/app/components/explore/sidebar'
|
import ExploreClient from '@/app/components/explore'
|
||||||
|
|
||||||
export type IAppDetail = {
|
export type IAppDetail = {
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
const AppDetail: FC<IAppDetail> = ({ children }) => {
|
const AppDetail: FC<IAppDetail> = ({ children }) => {
|
||||||
return (
|
return (
|
||||||
<div className='flex h-full bg-gray-100 border-t border-gray-200'>
|
<ExploreClient>
|
||||||
<Sidebar />
|
|
||||||
<div className='grow'>
|
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</ExploreClient>
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,18 +1,21 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import React, { FC, useEffect } from 'react'
|
import React, { FC, useEffect } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { useContext } from 'use-context-selector'
|
||||||
|
import ExploreContext from '@/context/explore-context'
|
||||||
import { App } from '@/models/explore'
|
import { App } from '@/models/explore'
|
||||||
import Category from '@/app/components/explore/category'
|
import Category from '@/app/components/explore/category'
|
||||||
import AppCard from '@/app/components/explore/app-card'
|
import AppCard from '@/app/components/explore/app-card'
|
||||||
import { fetchAppList } from '@/service/explore'
|
import { fetchAppList, installApp } from '@/service/explore'
|
||||||
import CreateAppModal from '@/app/components/explore/create-app-modal'
|
import CreateAppModal from '@/app/components/explore/create-app-modal'
|
||||||
import Loading from '@/app/components/base/loading'
|
import Loading from '@/app/components/base/loading'
|
||||||
|
|
||||||
import s from './style.module.css'
|
import s from './style.module.css'
|
||||||
|
import Toast from '../../base/toast'
|
||||||
|
|
||||||
const Apps: FC = ({ }) => {
|
const Apps: FC = ({ }) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const { setControlUpdateInstalledApps } = useContext(ExploreContext)
|
||||||
const [currCategory, setCurrCategory] = React.useState('')
|
const [currCategory, setCurrCategory] = React.useState('')
|
||||||
const [allList, setAllList] = React.useState<App[]>([])
|
const [allList, setAllList] = React.useState<App[]>([])
|
||||||
const [isLoaded, setIsLoaded] = React.useState(false)
|
const [isLoaded, setIsLoaded] = React.useState(false)
|
||||||
@ -31,8 +34,13 @@ const Apps: FC = ({ }) => {
|
|||||||
})()
|
})()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const handleAddToWorkspace = (appId: string) => {
|
const handleAddToWorkspace = async (appId: string) => {
|
||||||
console.log('handleAddToWorkspace', appId)
|
await installApp(appId)
|
||||||
|
Toast.notify({
|
||||||
|
type: 'success',
|
||||||
|
message: t('common.api.success'),
|
||||||
|
})
|
||||||
|
setControlUpdateInstalledApps(Date.now())
|
||||||
}
|
}
|
||||||
|
|
||||||
const [currApp, setCurrApp] = React.useState<any>(null)
|
const [currApp, setCurrApp] = React.useState<any>(null)
|
||||||
|
|||||||
33
web/app/components/explore/index.tsx
Normal file
33
web/app/components/explore/index.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
'use client'
|
||||||
|
import React, { FC } from 'react'
|
||||||
|
import ExploreContext from '@/context/explore-context'
|
||||||
|
import Sidebar from '@/app/components/explore/sidebar'
|
||||||
|
|
||||||
|
|
||||||
|
export interface IExploreProps {
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
const Explore: FC<IExploreProps> = ({
|
||||||
|
children
|
||||||
|
}) => {
|
||||||
|
const [controlUpdateInstalledApps, setControlUpdateInstalledApps] = React.useState(0)
|
||||||
|
return (
|
||||||
|
<div className='flex h-full bg-gray-100 border-t border-gray-200'>
|
||||||
|
<ExploreContext.Provider
|
||||||
|
value={
|
||||||
|
{
|
||||||
|
controlUpdateInstalledApps,
|
||||||
|
setControlUpdateInstalledApps
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Sidebar controlUpdateInstalledApps={controlUpdateInstalledApps} />
|
||||||
|
<div className='grow'>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</ExploreContext.Provider>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default React.memo(Explore)
|
||||||
@ -2,7 +2,6 @@
|
|||||||
import React, { FC, useEffect } from 'react'
|
import React, { FC, useEffect } from 'react'
|
||||||
import { App } from '@/types/app'
|
import { App } from '@/types/app'
|
||||||
import ChatApp from '@/app/components/share/chat'
|
import ChatApp from '@/app/components/share/chat'
|
||||||
|
|
||||||
export interface IInstalledAppProps {
|
export interface IInstalledAppProps {
|
||||||
id: string
|
id: string
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,21 +1,12 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import React, { FC } from 'react'
|
import React, { FC, useEffect } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import cn from 'classnames'
|
import cn from 'classnames'
|
||||||
import { useSelectedLayoutSegments } from 'next/navigation'
|
import { useSelectedLayoutSegments } from 'next/navigation'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import Item from './app-nav-item'
|
import Item from './app-nav-item'
|
||||||
|
import { InstalledApp } from '@/models/explore'
|
||||||
const list = [
|
import { fetchInstalledAppList as doFetchInstalledAppList } from '@/service/explore'
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
name: 'Story Bot',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2',
|
|
||||||
name: 'Fancy title'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const SelectedDiscoveryIcon = () => (
|
const SelectedDiscoveryIcon = () => (
|
||||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
@ -29,11 +20,29 @@ const DiscoveryIcon = () => (
|
|||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
|
|
||||||
const SideBar: FC = () => {
|
const SideBar: FC<{
|
||||||
|
controlUpdateInstalledApps: number
|
||||||
|
}> = ({
|
||||||
|
controlUpdateInstalledApps
|
||||||
|
}) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const segments = useSelectedLayoutSegments()
|
const segments = useSelectedLayoutSegments()
|
||||||
const lastSegment = segments.slice(-1)[0]
|
const lastSegment = segments.slice(-1)[0]
|
||||||
const isDiscoverySelected = lastSegment === 'apps'
|
const isDiscoverySelected = lastSegment === 'apps'
|
||||||
|
const [installedApps, setInstalledApps] = React.useState<InstalledApp[]>([])
|
||||||
|
|
||||||
|
const fetchInstalledAppList = async () => {
|
||||||
|
const {installed_apps} : any = await doFetchInstalledAppList()
|
||||||
|
setInstalledApps(installed_apps)
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchInstalledAppList()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchInstalledAppList()
|
||||||
|
}, [controlUpdateInstalledApps])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='w-[216px] shrink-0 pt-6 px-4 border-r border-gray-200 cursor-pointer'>
|
<div className='w-[216px] shrink-0 pt-6 px-4 border-r border-gray-200 cursor-pointer'>
|
||||||
@ -47,11 +56,11 @@ const SideBar: FC = () => {
|
|||||||
<div className='text-sm'>{t('explore.sidebar.discovery')}</div>
|
<div className='text-sm'>{t('explore.sidebar.discovery')}</div>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
{list.length > 0 && (
|
{installedApps.length > 0 && (
|
||||||
<div className='mt-10'>
|
<div className='mt-10'>
|
||||||
<div className='pl-2 text-xs text-gray-500 font-medium uppercase'>{t('explore.sidebar.workspace')}</div>
|
<div className='pl-2 text-xs text-gray-500 font-medium uppercase'>{t('explore.sidebar.workspace')}</div>
|
||||||
<div className='mt-3 space-y-1'>
|
<div className='mt-3 space-y-1'>
|
||||||
{list.map(({id, name}) => {
|
{installedApps.map(({app : {id, name}}) => {
|
||||||
return (
|
return (
|
||||||
<Item key={id} name={name} id={id} isSelected={lastSegment?.toLowerCase() === id} />
|
<Item key={id} name={name} id={id} isSelected={lastSegment?.toLowerCase() === id} />
|
||||||
)
|
)
|
||||||
|
|||||||
13
web/context/explore-context.ts
Normal file
13
web/context/explore-context.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { createContext } from 'use-context-selector'
|
||||||
|
|
||||||
|
type IExplore = {
|
||||||
|
controlUpdateInstalledApps: number
|
||||||
|
setControlUpdateInstalledApps: (controlUpdateInstalledApps: number) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const ExploreContext = createContext<IExplore>({
|
||||||
|
controlUpdateInstalledApps: 0,
|
||||||
|
setControlUpdateInstalledApps: () => { },
|
||||||
|
})
|
||||||
|
|
||||||
|
export default ExploreContext
|
||||||
@ -20,4 +20,10 @@ export type App = {
|
|||||||
install_count: number;
|
install_count: number;
|
||||||
installed: boolean;
|
installed: boolean;
|
||||||
editable: boolean;
|
editable: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type InstalledApp = {
|
||||||
|
app: AppBasicInfo;
|
||||||
|
id: string;
|
||||||
|
uninstallable: boolean
|
||||||
}
|
}
|
||||||
@ -1,5 +1,17 @@
|
|||||||
import { get } from './base'
|
import { get, post } from './base'
|
||||||
|
|
||||||
export const fetchAppList = () => {
|
export const fetchAppList = () => {
|
||||||
return get('/explore/apps')
|
return get('/explore/apps')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const fetchInstalledAppList = () => {
|
||||||
|
return get('/installed-apps')
|
||||||
|
}
|
||||||
|
|
||||||
|
export const installApp = (id: string) => {
|
||||||
|
return post('/installed-apps', {
|
||||||
|
body: {
|
||||||
|
app_id: id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user