mirror of https://github.com/langgenius/dify.git
support app creation in nav
This commit is contained in:
parent
0fcb746c08
commit
cf22842554
|
|
@ -3,7 +3,6 @@
|
|||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useParams } from 'next/navigation'
|
||||
// import useSWR from 'swr'
|
||||
import useSWRInfinite from 'swr/infinite'
|
||||
import { flatten } from 'lodash-es'
|
||||
import produce from 'immer'
|
||||
|
|
@ -11,7 +10,9 @@ import Nav from '../nav'
|
|||
import { type NavItem } from '../nav/nav-selector'
|
||||
import { Robot, RobotActive } from '../../base/icons/src/public/header-nav/studio'
|
||||
import { fetchAppList } from '@/service/apps'
|
||||
import CreateAppDialog from '@/app/components/app/create-app-dialog'
|
||||
import CreateAppTemplateDialog from '@/app/components/app/create-app-dialog'
|
||||
import CreateAppModal from '@/app/components/app/create-app-modal'
|
||||
import CreateFromDSLModal from '@/app/components/app/create-from-dsl-modal'
|
||||
import type { AppListResponse } from '@/models/app'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
|
|
@ -28,6 +29,8 @@ const AppNav = () => {
|
|||
const { isCurrentWorkspaceManager } = useAppContext()
|
||||
const { appDetail } = useAppStore()
|
||||
const [showNewAppDialog, setShowNewAppDialog] = useState(false)
|
||||
const [showNewAppTemplateDialog, setShowNewAppTemplateDialog] = useState(false)
|
||||
const [showCreateFromDSLModal, setShowCreateFromDSLModal] = useState(false)
|
||||
const [navItems, setNavItems] = useState<NavItem[]>([])
|
||||
|
||||
const { data: appsData, setSize } = useSWRInfinite(appId ? getKey : () => null, fetchAppList, { revalidateFirstPage: false })
|
||||
|
|
@ -36,6 +39,15 @@ const AppNav = () => {
|
|||
setSize(size => size + 1)
|
||||
}, [setSize])
|
||||
|
||||
const openModal = (state: string) => {
|
||||
if (state === 'blank')
|
||||
setShowNewAppDialog(true)
|
||||
if (state === 'template')
|
||||
setShowNewAppTemplateDialog(true)
|
||||
if (state === 'dsl')
|
||||
setShowCreateFromDSLModal(true)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (appsData) {
|
||||
const appItems = flatten(appsData?.map(appData => appData.data))
|
||||
|
|
@ -87,14 +99,24 @@ const AppNav = () => {
|
|||
curNav={appDetail}
|
||||
navs={navItems}
|
||||
createText={t('common.menus.newApp')}
|
||||
onCreate={() => setShowNewAppDialog(true)}
|
||||
onCreate={openModal}
|
||||
onLoadmore={handleLoadmore}
|
||||
/>
|
||||
<CreateAppDialog
|
||||
<CreateAppModal
|
||||
show={showNewAppDialog}
|
||||
onClose={() => setShowNewAppDialog(false)}
|
||||
onSuccess={() => {}}
|
||||
/>
|
||||
<CreateAppTemplateDialog
|
||||
show={showNewAppTemplateDialog}
|
||||
onClose={() => setShowNewAppTemplateDialog(false)}
|
||||
onSuccess={() => {}}
|
||||
/>
|
||||
<CreateFromDSLModal
|
||||
show={showCreateFromDSLModal}
|
||||
onClose={() => setShowCreateFromDSLModal(false)}
|
||||
onSuccess={() => {}}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
'use client'
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Fragment, useCallback } from 'react'
|
||||
import cn from 'classnames'
|
||||
import { Menu } from '@headlessui/react'
|
||||
import { Menu, Transition } from '@headlessui/react'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { debounce } from 'lodash-es'
|
||||
import Indicator from '../../indicator'
|
||||
import AppIcon from '@/app/components/base/app-icon'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import { ChevronDown } from '@/app/components/base/icons/src/vender/line/arrows'
|
||||
import { ChevronDown, ChevronRight } from '@/app/components/base/icons/src/vender/line/arrows'
|
||||
import { FileArrow01, FilePlus01, FilePlus02 } from '@/app/components/base/icons/src/vender/line/files'
|
||||
import { Plus } from '@/app/components/base/icons/src/vender/line/general'
|
||||
|
||||
export type NavItem = {
|
||||
|
|
@ -22,11 +24,12 @@ export type INavSelectorProps = {
|
|||
navs: NavItem[]
|
||||
curNav?: Omit<NavItem, 'link'>
|
||||
createText: string
|
||||
onCreate: () => void
|
||||
onCreate: (state: string) => void
|
||||
onLoadmore?: () => void
|
||||
}
|
||||
|
||||
const NavSelector = ({ curNav, navs, createText, onCreate, onLoadmore }: INavSelectorProps) => {
|
||||
const { t } = useTranslation()
|
||||
const router = useRouter()
|
||||
const { isCurrentWorkspaceManager } = useAppContext()
|
||||
const { setAppDetail } = useAppStore()
|
||||
|
|
@ -84,16 +87,56 @@ const NavSelector = ({ curNav, navs, createText, onCreate, onLoadmore }: INavSel
|
|||
))
|
||||
}
|
||||
</div>
|
||||
{isCurrentWorkspaceManager && <Menu.Item>
|
||||
<div className='p-1' onClick={onCreate}>
|
||||
<div className='flex items-center px-3 py-[6px] rounded-lg cursor-pointer hover:bg-gray-100'>
|
||||
<div className='flex justify-center items-center mr-2 w-6 h-6 bg-gray-100 rounded-[6px] border-[0.5px] border-gray-200 border'>
|
||||
<Plus className='w-4 h-4 text-gray-500' />
|
||||
</div>
|
||||
<div className='font-normal text-[14px] text-gray-700'>{createText}</div>
|
||||
</div>
|
||||
</div>
|
||||
</Menu.Item>}
|
||||
{isCurrentWorkspaceManager && (
|
||||
<Menu as="div" className="relative w-full h-full">
|
||||
{({ open }) => (
|
||||
<>
|
||||
<Menu.Button className='p-1 w-full'>
|
||||
<div className={cn(
|
||||
'flex items-center gap-2 px-3 py-[6px] rounded-lg cursor-pointer hover:bg-gray-100',
|
||||
open && '!bg-gray-100',
|
||||
)}>
|
||||
<div className='shrink-0 flex justify-center items-center w-6 h-6 bg-gray-50 rounded-[6px] border-[0.5px] border-gray-200 border'>
|
||||
<Plus className='w-4 h-4 text-gray-500' />
|
||||
</div>
|
||||
<div className='grow text-left font-normal text-[14px] text-gray-700'>{createText}</div>
|
||||
<ChevronRight className='shrink-0 w-3.5 h-3.5 text-gray-500'/>
|
||||
</div>
|
||||
</Menu.Button>
|
||||
<Transition
|
||||
as={Fragment}
|
||||
enter="transition ease-out duration-100"
|
||||
enterFrom="transform opacity-0 scale-95"
|
||||
enterTo="transform opacity-100 scale-100"
|
||||
leave="transition ease-in duration-75"
|
||||
leaveFrom="transform opacity-100 scale-100"
|
||||
leaveTo="transform opacity-0 scale-95"
|
||||
>
|
||||
<Menu.Items className={cn(
|
||||
'absolute top-[3px] right-[-198px] min-w-[200px] z-10 bg-white border-[0.5px] border-gray-200 rounded-lg shadow-lg',
|
||||
)}>
|
||||
<div className='p-1'>
|
||||
<div className={cn('flex items-center px-3 py-[6px] rounded-lg cursor-pointer hover:bg-gray-100 text-gray-700 font-normal')} onClick={() => onCreate('blank')}>
|
||||
<FilePlus01 className='shrink-0 mr-2 w-4 h-4 text-gray-600' />
|
||||
{t('app.newApp.startFromBlank')}
|
||||
</div>
|
||||
<div className={cn('flex items-center px-3 py-[6px] rounded-lg cursor-pointer hover:bg-gray-100 text-gray-700 font-normal')} onClick={() => onCreate('template')}>
|
||||
<FilePlus02 className='shrink-0 mr-2 w-4 h-4 text-gray-600' />
|
||||
{t('app.newApp.startFromTemplate')}
|
||||
</div>
|
||||
</div>
|
||||
<div className='p-1 border border-top-[1px] border-gray-100'>
|
||||
<div className={cn('flex items-center px-3 py-[6px] rounded-lg cursor-pointer hover:bg-gray-100 text-gray-700 font-normal')} onClick={() => onCreate('dsl')}>
|
||||
<FileArrow01 className='shrink-0 mr-2 w-4 h-4 text-gray-600' />
|
||||
{t('app.importDSL')}
|
||||
</div>
|
||||
</div>
|
||||
</Menu.Items>
|
||||
</Transition>
|
||||
</>
|
||||
)}
|
||||
</Menu>
|
||||
)}
|
||||
</Menu.Items>
|
||||
</>
|
||||
)}
|
||||
|
|
|
|||
Loading…
Reference in New Issue