feat: add to workspace api

pull/198/head
金伟强 3 years ago
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)

@ -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} />
) )

@ -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…
Cancel
Save