feat: support use tempalte in create app

This commit is contained in:
Joel
2025-10-27 10:58:57 +08:00
parent b49a4eab62
commit 8786ebdbca
5 changed files with 129 additions and 5 deletions

View File

@@ -4,8 +4,15 @@ import List from './list'
import useDocumentTitle from '@/hooks/use-document-title'
import { useTranslation } from 'react-i18next'
import AppListContext from '@/context/app-list-context'
import { useState } from 'react'
import { useCallback, useState } from 'react'
import type { CurrentTryAppParams } from '@/context/explore-context'
import TryApp from '../explore/try-app'
import type { CreateAppModalProps } from '../explore/create-app-modal'
import CreateAppModal from '../explore/create-app-modal'
import { fetchAppDetail } from '@/service/explore'
import { DSLImportMode } from '@/models/app'
import { useImportDSL } from '@/hooks/use-import-dsl'
import DSLConfirmModal from '../app/create-from-dsl-modal/dsl-confirm-modal'
const Apps = () => {
const { t } = useTranslation()
@@ -14,7 +21,11 @@ const Apps = () => {
useEducationInit()
const [currentTryAppParams, setCurrentTryAppParams] = useState<CurrentTryAppParams | undefined>(undefined)
const currApp = currentTryAppParams?.app
const [isShowTryAppPanel, setIsShowTryAppPanel] = useState(false)
const hideTryAppPanel = useCallback(() => {
setIsShowTryAppPanel(false)
}, [])
const setShowTryAppPanel = (showTryAppPanel: boolean, params?: CurrentTryAppParams) => {
if (showTryAppPanel)
setCurrentTryAppParams(params)
@@ -22,15 +33,107 @@ const Apps = () => {
setCurrentTryAppParams(undefined)
setIsShowTryAppPanel(showTryAppPanel)
}
const [isShowCreateModal, setIsShowCreateModal] = useState(false)
const handleShowFromTryApp = useCallback(() => {
setIsShowCreateModal(true)
}, [])
const [controlRefreshList, setControlRefreshList] = useState(0)
const [controlHideCreateFromTemplatePanel, setControlHideCreateFromTemplatePanel] = useState(0)
const onSuccess = useCallback(() => {
setControlRefreshList(prev => prev + 1)
setControlHideCreateFromTemplatePanel(prev => prev + 1)
}, [])
const [showDSLConfirmModal, setShowDSLConfirmModal] = useState(false)
const {
handleImportDSL,
handleImportDSLConfirm,
versions,
isFetching,
} = useImportDSL()
const onConfirmDSL = useCallback(async () => {
await handleImportDSLConfirm({
onSuccess,
})
}, [handleImportDSLConfirm, onSuccess])
const onCreate: CreateAppModalProps['onConfirm'] = async ({
name,
icon_type,
icon,
icon_background,
description,
}) => {
hideTryAppPanel()
const { export_data } = await fetchAppDetail(
currApp?.app.id as string,
)
const payload = {
mode: DSLImportMode.YAML_CONTENT,
yaml_content: export_data,
name,
icon_type,
icon,
icon_background,
description,
}
await handleImportDSL(payload, {
onSuccess: () => {
setIsShowCreateModal(false)
},
onPending: () => {
setShowDSLConfirmModal(true)
},
})
}
return (
<AppListContext.Provider value={{
currentApp: currentTryAppParams,
isShowTryAppPanel,
setShowTryAppPanel,
controlHideCreateFromTemplatePanel,
}}>
<div className='relative flex h-0 shrink-0 grow flex-col overflow-y-auto bg-background-body'>
<List />
<List controlRefreshList={controlRefreshList} />
{isShowTryAppPanel && (
<TryApp appId={currentTryAppParams?.appId || ''}
category={currentTryAppParams?.app?.category}
onClose={hideTryAppPanel}
onCreate={handleShowFromTryApp}
/>
)}
{
showDSLConfirmModal && (
<DSLConfirmModal
versions={versions}
onCancel={() => setShowDSLConfirmModal(false)}
onConfirm={onConfirmDSL}
confirmDisabled={isFetching}
/>
)
}
{isShowCreateModal && (
<CreateAppModal
appIconType={currApp?.app.icon_type || 'emoji'}
appIcon={currApp?.app.icon || ''}
appIconBackground={currApp?.app.icon_background || ''}
appIconUrl={currApp?.app.icon_url}
appName={currApp?.app.name || ''}
appDescription={currApp?.app.description || ''}
show
onConfirm={onCreate}
confirmDisabled={isFetching}
onHide={() => setIsShowCreateModal(false)}
/>
)}
</div >
</AppListContext.Provider>
)

View File

@@ -1,5 +1,6 @@
'use client'
import type { FC } from 'react'
import { useCallback, useEffect, useRef, useState } from 'react'
import {
useRouter,
@@ -66,7 +67,12 @@ const getKey = (
return null
}
const List = () => {
type Props = {
controlRefreshList: number
}
const List: FC<Props> = ({
controlRefreshList,
}) => {
const { t } = useTranslation()
const { systemFeatures } = useGlobalPublicStore()
const router = useRouter()
@@ -112,6 +118,11 @@ const List = () => {
},
)
useEffect(() => {
if (controlRefreshList > 0)
mutate()
}, [controlRefreshList])
const anchorRef = useRef<HTMLDivElement>(null)
const options = [
{ value: 'all', text: t('app.types.all'), icon: <RiApps2Line className='mr-1 h-[14px] w-[14px]' /> },

View File

@@ -1,6 +1,6 @@
'use client'
import React, { useMemo, useState } from 'react'
import React, { useEffect, useMemo, useState } from 'react'
import {
useRouter,
useSearchParams,
@@ -11,6 +11,8 @@ import { useProviderContext } from '@/context/provider-context'
import { FileArrow01, FilePlus01, FilePlus02 } from '@/app/components/base/icons/src/vender/line/files'
import cn from '@/utils/classnames'
import dynamic from 'next/dynamic'
import AppListContext from '@/context/app-list-context'
import { useContextSelector } from 'use-context-selector'
const CreateAppModal = dynamic(() => import('@/app/components/app/create-app-modal'), {
ssr: false,
@@ -52,6 +54,12 @@ const CreateAppCard = ({
return undefined
}, [dslUrl])
const controlHideCreateFromTemplatePanel = useContextSelector(AppListContext, ctx => ctx.controlHideCreateFromTemplatePanel)
useEffect(() => {
if (controlHideCreateFromTemplatePanel > 0)
setShowNewAppTemplateDialog(false)
}, [controlHideCreateFromTemplatePanel])
return (
<div
ref={ref}

View File

@@ -71,7 +71,7 @@ const AppCard = ({
{isExplore && (canCreate || isTrialApp) && (
<div className={cn(
'absolute bottom-0 left-0 right-0 hidden bg-gradient-to-t from-components-panel-gradient-2 from-[60.27%] to-transparent p-4 pt-8',
(canCreate && isTrialApp) && 'grid-cols-2 gap-2 group-hover:grid ',
(canCreate && isTrialApp) && 'grid-cols-2 gap-2 group-hover:grid',
)}>
{canCreate && (
<Button variant='primary' className='h-7' onClick={() => onCreate()}>

View File

@@ -6,12 +6,14 @@ type Props = {
currentApp?: CurrentTryAppParams
isShowTryAppPanel: boolean
setShowTryAppPanel: (showTryAppPanel: boolean, params?: CurrentTryAppParams) => void
controlHideCreateFromTemplatePanel: number
}
const AppListContext = createContext<Props>({
isShowTryAppPanel: false,
setShowTryAppPanel: noop,
currentApp: undefined,
controlHideCreateFromTemplatePanel: 0,
})
export default AppListContext