support app creation in nav

This commit is contained in:
JzoNg 2024-04-02 12:13:59 +08:00
parent 0fcb746c08
commit cf22842554
2 changed files with 83 additions and 18 deletions

View File

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

View File

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