app info in full screen mode

pull/21369/head
jZonG 11 months ago
parent fc4e7ea7f1
commit baaada7205

@ -39,16 +39,19 @@ import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigge
export type IAppInfoProps = { export type IAppInfoProps = {
expand: boolean expand: boolean
onlyShowDetail?: boolean
openState?: boolean
onDetailExpand?: (expand: boolean) => void
} }
const AppInfo = ({ expand }: IAppInfoProps) => { const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailExpand }: IAppInfoProps) => {
const { t } = useTranslation() const { t } = useTranslation()
const { notify } = useContext(ToastContext) const { notify } = useContext(ToastContext)
const { replace } = useRouter() const { replace } = useRouter()
const { onPlanInfoChanged } = useProviderContext() const { onPlanInfoChanged } = useProviderContext()
const appDetail = useAppStore(state => state.appDetail) const appDetail = useAppStore(state => state.appDetail)
const setAppDetail = useAppStore(state => state.setAppDetail) const setAppDetail = useAppStore(state => state.setAppDetail)
const [open, setOpen] = useState(false) const [open, setOpen] = useState(openState)
const [showEditModal, setShowEditModal] = useState(false) const [showEditModal, setShowEditModal] = useState(false)
const [showDuplicateModal, setShowDuplicateModal] = useState(false) const [showDuplicateModal, setShowDuplicateModal] = useState(false)
const [showConfirmDelete, setShowConfirmDelete] = useState(false) const [showConfirmDelete, setShowConfirmDelete] = useState(false)
@ -193,43 +196,48 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
return ( return (
<div> <div>
<button {!onlyShowDetail && (
onClick={() => { <button
if (isCurrentWorkspaceEditor) onClick={() => {
setOpen(v => !v) if (isCurrentWorkspaceEditor)
}} setOpen(v => !v)
className='block w-full' }}
> className='block w-full'
<div className={cn('flex rounded-lg', expand ? 'flex-col gap-2 p-2 pb-2.5' : 'items-start justify-center gap-1 p-1', open && 'bg-state-base-hover', isCurrentWorkspaceEditor && 'cursor-pointer hover:bg-state-base-hover')}> >
<div className={`flex items-center self-stretch ${expand ? 'justify-between' : 'flex-col gap-1'}`}> <div className={cn('flex rounded-lg', expand ? 'flex-col gap-2 p-2 pb-2.5' : 'items-start justify-center gap-1 p-1', open && 'bg-state-base-hover', isCurrentWorkspaceEditor && 'cursor-pointer hover:bg-state-base-hover')}>
<AppIcon <div className={`flex items-center self-stretch ${expand ? 'justify-between' : 'flex-col gap-1'}`}>
size={expand ? 'large' : 'small'} <AppIcon
iconType={appDetail.icon_type} size={expand ? 'large' : 'small'}
icon={appDetail.icon} iconType={appDetail.icon_type}
background={appDetail.icon_background} icon={appDetail.icon}
imageUrl={appDetail.icon_url} background={appDetail.icon_background}
/> imageUrl={appDetail.icon_url}
<div className='flex items-center justify-center rounded-md p-0.5'> />
<div className='flex h-5 w-5 items-center justify-center'> <div className='flex items-center justify-center rounded-md p-0.5'>
<RiEqualizer2Line className='h-4 w-4 text-text-tertiary' /> <div className='flex h-5 w-5 items-center justify-center'>
<RiEqualizer2Line className='h-4 w-4 text-text-tertiary' />
</div>
</div> </div>
</div> </div>
</div> {
{ expand && (
expand && ( <div className='flex flex-col items-start gap-1'>
<div className='flex flex-col items-start gap-1'> <div className='flex w-full'>
<div className='flex w-full'> <div className='system-md-semibold truncate text-text-secondary'>{appDetail.name}</div>
<div className='system-md-semibold truncate text-text-secondary'>{appDetail.name}</div> </div>
<div className='system-2xs-medium-uppercase text-text-tertiary'>{appDetail.mode === 'advanced-chat' ? t('app.types.advanced') : appDetail.mode === 'agent-chat' ? t('app.types.agent') : appDetail.mode === 'chat' ? t('app.types.chatbot') : appDetail.mode === 'completion' ? t('app.types.completion') : t('app.types.workflow')}</div>
</div> </div>
<div className='system-2xs-medium-uppercase text-text-tertiary'>{appDetail.mode === 'advanced-chat' ? t('app.types.advanced') : appDetail.mode === 'agent-chat' ? t('app.types.agent') : appDetail.mode === 'chat' ? t('app.types.chatbot') : appDetail.mode === 'completion' ? t('app.types.completion') : t('app.types.workflow')}</div> )
</div> }
) </div>
} </button>
</div> )}
</button>
<ContentDialog <ContentDialog
show={open} show={onlyShowDetail ? openState : open}
onClose={() => setOpen(false)} onClose={() => {
setOpen(false)
onDetailExpand?.(false)
}}
className='absolute bottom-2 left-2 top-2 flex w-[420px] flex-col rounded-2xl !p-0' className='absolute bottom-2 left-2 top-2 flex w-[420px] flex-col rounded-2xl !p-0'
> >
<div className='flex shrink-0 flex-col items-start justify-center gap-3 self-stretch p-4'> <div className='flex shrink-0 flex-col items-start justify-center gap-3 self-stretch p-4'>
@ -258,6 +266,7 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
className='gap-[1px]' className='gap-[1px]'
onClick={() => { onClick={() => {
setOpen(false) setOpen(false)
onDetailExpand?.(false)
setShowEditModal(true) setShowEditModal(true)
}} }}
> >
@ -270,6 +279,7 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
className='gap-[1px]' className='gap-[1px]'
onClick={() => { onClick={() => {
setOpen(false) setOpen(false)
onDetailExpand?.(false)
setShowDuplicateModal(true) setShowDuplicateModal(true)
}}> }}>
<RiFileCopy2Line className='h-3.5 w-3.5 text-components-button-secondary-text' /> <RiFileCopy2Line className='h-3.5 w-3.5 text-components-button-secondary-text' />
@ -308,6 +318,7 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
&& <div className='flex h-8 cursor-pointer items-center gap-x-1 rounded-lg p-1.5 hover:bg-state-base-hover' && <div className='flex h-8 cursor-pointer items-center gap-x-1 rounded-lg p-1.5 hover:bg-state-base-hover'
onClick={() => { onClick={() => {
setOpen(false) setOpen(false)
onDetailExpand?.(false)
setShowImportDSLModal(true) setShowImportDSLModal(true)
}}> }}>
<RiFileUploadLine className='h-4 w-4 text-text-tertiary' /> <RiFileUploadLine className='h-4 w-4 text-text-tertiary' />
@ -319,6 +330,7 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
&& <div className='flex h-8 cursor-pointer items-center gap-x-1 rounded-lg p-1.5 hover:bg-state-base-hover' && <div className='flex h-8 cursor-pointer items-center gap-x-1 rounded-lg p-1.5 hover:bg-state-base-hover'
onClick={() => { onClick={() => {
setOpen(false) setOpen(false)
onDetailExpand?.(false)
setShowSwitchModal(true) setShowSwitchModal(true)
}}> }}>
<RiExchange2Line className='h-4 w-4 text-text-tertiary' /> <RiExchange2Line className='h-4 w-4 text-text-tertiary' />
@ -345,6 +357,7 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
className='gap-0.5' className='gap-0.5'
onClick={() => { onClick={() => {
setOpen(false) setOpen(false)
onDetailExpand?.(false)
setShowConfirmDelete(true) setShowConfirmDelete(true)
}} }}
> >

@ -1,5 +1,10 @@
import React, { useCallback, useRef, useState } from 'react' import React, { useCallback, useRef, useState } from 'react'
import { RiMenuLine } from '@remixicon/react' import { useTranslation } from 'react-i18next'
import { useAppContext } from '@/context/app-context'
import {
RiEqualizer2Line,
RiMenuLine,
} from '@remixicon/react'
import { import {
PortalToFollowElem, PortalToFollowElem,
PortalToFollowElemContent, PortalToFollowElemContent,
@ -23,7 +28,10 @@ type Props = {
} }
const AppSidebarDropdown = ({ navigation }: Props) => { const AppSidebarDropdown = ({ navigation }: Props) => {
const { t } = useTranslation()
const { isCurrentWorkspaceEditor } = useAppContext()
const appDetail = useAppStore(state => state.appDetail) const appDetail = useAppStore(state => state.appDetail)
const [detailExpand, setDetailExpand] = useState(false)
const [open, doSetOpen] = useState(false) const [open, doSetOpen] = useState(false)
const openRef = useRef(open) const openRef = useRef(open)
@ -39,46 +47,78 @@ const AppSidebarDropdown = ({ navigation }: Props) => {
return null return null
return ( return (
<div className='fixed left-2 top-2 z-[1000]'> <>
<PortalToFollowElem <div className='fixed left-2 top-2 z-20'>
open={open} <PortalToFollowElem
onOpenChange={setOpen} open={open}
placement='bottom-start' onOpenChange={setOpen}
offset={{ placement='bottom-start'
mainAxis: -41, offset={{
}} mainAxis: -41,
> }}
<PortalToFollowElemTrigger onClick={handleTrigger}> >
<div className={cn('flex cursor-pointer items-center rounded-[10px] border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg p-1 shadow-lg backdrop-blur-sm hover:bg-background-default-hover', open && 'bg-background-default-hover')}> <PortalToFollowElemTrigger onClick={handleTrigger}>
<AppIcon <div className={cn('flex cursor-pointer items-center rounded-[10px] border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg p-1 shadow-lg backdrop-blur-sm hover:bg-background-default-hover', open && 'bg-background-default-hover')}>
size='small' <AppIcon
iconType={appDetail.icon_type} size='small'
icon={appDetail.icon} iconType={appDetail.icon_type}
background={appDetail.icon_background} icon={appDetail.icon}
imageUrl={appDetail.icon_url} background={appDetail.icon_background}
/> imageUrl={appDetail.icon_url}
<RiMenuLine className='h-4 w-4 text-text-tertiary' /> />
</div> <RiMenuLine className='h-4 w-4 text-text-tertiary' />
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-[1000]'>
<div className={cn('w-[305px] rounded-xl border-[0.5px] border-components-panel-border bg-background-default-subtle shadow-lg')}>
<div className='p-2'>
<AppInfo expand />
</div> </div>
<div className='px-4'> </PortalToFollowElemTrigger>
<Divider bgStyle='gradient' /> <PortalToFollowElemContent className='z-[1000]'>
<div className={cn('w-[305px] rounded-xl border-[0.5px] border-components-panel-border bg-background-default-subtle shadow-lg')}>
<div className='p-2'>
<div
className={cn('flex flex-col gap-2 rounded-lg p-2 pb-2.5', isCurrentWorkspaceEditor && 'cursor-pointer hover:bg-state-base-hover')}
onClick={() => {
setDetailExpand(true)
setOpen(false)
}}
>
<div className='flex items-center justify-between self-stretch'>
<AppIcon
size='large'
iconType={appDetail.icon_type}
icon={appDetail.icon}
background={appDetail.icon_background}
imageUrl={appDetail.icon_url}
/>
<div className='flex items-center justify-center rounded-md p-0.5'>
<div className='flex h-5 w-5 items-center justify-center'>
<RiEqualizer2Line className='h-4 w-4 text-text-tertiary' />
</div>
</div>
</div>
<div className='flex flex-col items-start gap-1'>
<div className='flex w-full'>
<div className='system-md-semibold truncate text-text-secondary'>{appDetail.name}</div>
</div>
<div className='system-2xs-medium-uppercase text-text-tertiary'>{appDetail.mode === 'advanced-chat' ? t('app.types.advanced') : appDetail.mode === 'agent-chat' ? t('app.types.agent') : appDetail.mode === 'chat' ? t('app.types.chatbot') : appDetail.mode === 'completion' ? t('app.types.completion') : t('app.types.workflow')}</div>
</div>
</div>
</div>
<div className='px-4'>
<Divider bgStyle='gradient' />
</div>
<nav className='space-y-0.5 px-3 pb-6 pt-4'>
{navigation.map((item, index) => {
return (
<NavLink key={index} mode='expand' iconMap={{ selected: item.selectedIcon, normal: item.icon }} name={item.name} href={item.href} />
)
})}
</nav>
</div> </div>
<nav className='space-y-0.5 px-3 pb-6 pt-4'> </PortalToFollowElemContent>
{navigation.map((item, index) => { </PortalToFollowElem>
return ( </div>
<NavLink key={index} mode='expand' iconMap={{ selected: item.selectedIcon, normal: item.icon }} name={item.name} href={item.href} /> <div className='z-20'>
) <AppInfo expand onlyShowDetail openState={detailExpand} onDetailExpand={setDetailExpand} />
})} </div>
</nav> </>
</div>
</PortalToFollowElemContent>
</PortalToFollowElem>
</div>
) )
} }

@ -61,8 +61,13 @@ const AppDetailNav = ({ title, desc, isExternal, icon, icon_background, navigati
} }
}, [appSidebarExpand, setAppSiderbarExpand]) }, [appSidebarExpand, setAppSiderbarExpand])
if (inWorkflowCanvas && hideHeader) if (inWorkflowCanvas && hideHeader) {
return <AppSidebarDropdown navigation={navigation} /> return (
<div className='flex w-0 shrink-0'>
<AppSidebarDropdown navigation={navigation} />
</div>
)
}
return ( return (
<div <div

Loading…
Cancel
Save