index.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. 'use client'
  2. import React, { FC, useEffect } from 'react'
  3. import { useRouter } from 'next/navigation'
  4. import { useTranslation } from 'react-i18next'
  5. import { useContext } from 'use-context-selector'
  6. import ExploreContext from '@/context/explore-context'
  7. import { App } from '@/models/explore'
  8. import Category from '@/app/components/explore/category'
  9. import AppCard from '@/app/components/explore/app-card'
  10. import { fetchAppList, installApp, fetchAppDetail } from '@/service/explore'
  11. import { createApp } from '@/service/apps'
  12. import CreateAppModal from '@/app/components/explore/create-app-modal'
  13. import Loading from '@/app/components/base/loading'
  14. import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
  15. import s from './style.module.css'
  16. import Toast from '../../base/toast'
  17. const Apps: FC = ({ }) => {
  18. const { t } = useTranslation()
  19. const router = useRouter()
  20. const { setControlUpdateInstalledApps, hasEditPermission } = useContext(ExploreContext)
  21. const [currCategory, setCurrCategory] = React.useState('')
  22. const [allList, setAllList] = React.useState<App[]>([])
  23. const [isLoaded, setIsLoaded] = React.useState(false)
  24. const currList = (() => {
  25. if(currCategory === '') return allList
  26. return allList.filter(item => item.category === currCategory)
  27. })()
  28. const [categories, setCategories] = React.useState([])
  29. useEffect(() => {
  30. (async () => {
  31. const {categories, recommended_apps}:any = await fetchAppList()
  32. setCategories(categories)
  33. setAllList(recommended_apps)
  34. setIsLoaded(true)
  35. })()
  36. }, [])
  37. const handleAddToWorkspace = async (appId: string) => {
  38. await installApp(appId)
  39. Toast.notify({
  40. type: 'success',
  41. message: t('common.api.success'),
  42. })
  43. setControlUpdateInstalledApps(Date.now())
  44. }
  45. const [currApp, setCurrApp] = React.useState<App | null>(null)
  46. const [isShowCreateModal, setIsShowCreateModal] = React.useState(false)
  47. const onCreate = async ({name, icon, icon_background}: any) => {
  48. const { app_model_config: model_config } = await fetchAppDetail(currApp?.app.id as string)
  49. try {
  50. const app = await createApp({
  51. name,
  52. icon,
  53. icon_background,
  54. mode: currApp?.app.mode as any,
  55. config: model_config,
  56. })
  57. setIsShowCreateModal(false)
  58. Toast.notify({
  59. type: 'success',
  60. message: t('app.newApp.appCreated'),
  61. })
  62. localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
  63. router.push(`/app/${app.id}/overview`)
  64. } catch (e) {
  65. Toast.notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
  66. }
  67. }
  68. if(!isLoaded) {
  69. return (
  70. <div className='flex h-full items-center'>
  71. <Loading type='area' />
  72. </div>
  73. )
  74. }
  75. return (
  76. <div className='h-full flex flex-col'>
  77. <div className='shrink-0 pt-6 px-12'>
  78. <div className='mb-1 text-primary-600 text-xl font-semibold'>{t('explore.apps.title')}</div>
  79. <div className='text-gray-500 text-sm'>{t('explore.apps.description')}</div>
  80. </div>
  81. <Category
  82. className='mt-6 px-12'
  83. list={categories}
  84. value={currCategory}
  85. onChange={setCurrCategory}
  86. />
  87. <div
  88. className='flex mt-6 flex-col overflow-auto bg-gray-100 shrink-0 grow'
  89. style={{
  90. maxHeight: 'calc(100vh - 243px)'
  91. }}
  92. >
  93. <nav
  94. className={`${s.appList} grid content-start grid-cols-1 gap-4 px-12 pb-10grow shrink-0`}>
  95. {currList.map(app => (
  96. <AppCard
  97. key={app.app_id}
  98. app={app}
  99. canCreate={hasEditPermission}
  100. onCreate={() => {
  101. setCurrApp(app)
  102. setIsShowCreateModal(true)
  103. }}
  104. onAddToWorkspace={handleAddToWorkspace}
  105. />
  106. ))}
  107. </nav>
  108. </div>
  109. {isShowCreateModal && (
  110. <CreateAppModal
  111. appName={currApp?.app.name || ''}
  112. show={isShowCreateModal}
  113. onConfirm={onCreate}
  114. onHide={() => setIsShowCreateModal(false)}
  115. />
  116. )}
  117. </div>
  118. )
  119. }
  120. export default React.memo(Apps)