mirror of
https://github.com/langgenius/dify.git
synced 2026-01-06 06:26:00 +00:00
feat: support use tempalte in create app
This commit is contained in:
@@ -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>
|
||||
)
|
||||
|
||||
@@ -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]' /> },
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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()}>
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user