feat: can show app detail modal

This commit is contained in:
Joel 2025-10-23 14:17:43 +08:00
parent ab56b4a818
commit b018f2b0a0
6 changed files with 115 additions and 7 deletions

View File

@ -8,7 +8,10 @@ import AppIcon from '@/app/components/base/app-icon'
import { AppTypeIcon } from '../../app/type-selector'
import { useGlobalPublicStore } from '@/context/global-public-context'
import { RiArrowRightUpLine } from '@remixicon/react'
import Link from 'next/link'
import { useCallback } from 'react'
import ExploreContext from '@/context/explore-context'
import { useContextSelector } from 'use-context-selector'
export type AppCardProps = {
app: App
canCreate: boolean
@ -26,6 +29,12 @@ const AppCard = ({
const { app: appBasicInfo } = app
const { systemFeatures } = useGlobalPublicStore()
const isTrialApp = app.can_trial && systemFeatures.enable_trial_app
const setShowTryAppPanel = useContextSelector(ExploreContext, ctx => ctx.setShowTryAppPanel)
const showTryAPPPanel = useCallback((appId: string) => {
return () => {
setShowTryAppPanel?.(true, { appId })
}
}, [setShowTryAppPanel])
return (
<div className={cn('group relative col-span-1 flex cursor-pointer flex-col overflow-hidden rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg pb-2 shadow-sm transition-all duration-200 ease-in-out hover:bg-components-panel-on-panel-item-bg-hover hover:shadow-lg')}>
@ -71,12 +80,11 @@ const AppCard = ({
</Button>
)}
{isTrialApp && (
<Link href={`/try/app/${app.app_id}`} target='_blank' rel='noreferrer'>
<Button className='w-full'>
<span>{t('explore.appCard.try')}</span>
<RiArrowRightUpLine className='size-4' />
</Button>
</Link>
// /try/app/${app.app_id}
<Button className='w-full' onClick={showTryAPPPanel(app.app_id)}>
<span>{t('explore.appCard.try')}</span>
<RiArrowRightUpLine className='size-4' />
</Button>
)}
</div>
)}

View File

@ -25,6 +25,8 @@ import DSLConfirmModal from '@/app/components/app/create-from-dsl-modal/dsl-conf
import Banner from '@/app/components/explore/banner/banner'
import { useGlobalPublicStore } from '@/context/global-public-context'
import Button from '@/app/components/base/button'
import { useContextSelector } from 'use-context-selector'
import TryApp from '../try-app'
type AppsProps = {
onSuccess?: () => void
@ -141,6 +143,12 @@ const Apps = ({
})
}, [handleImportDSLConfirm, onSuccess])
const isShowTryAppPanel = useContextSelector(ExploreContext, ctx => ctx.isShowTryAppPanel)
const setShowTryAppPanel = useContextSelector(ExploreContext, ctx => ctx.setShowTryAppPanel)
const hideTryAppPanel = useCallback(() => {
setShowTryAppPanel(false)
}, [setShowTryAppPanel])
const appId = useContextSelector(ExploreContext, ctx => ctx.currentApp?.appId) as string
if (!categories || categories.length === 0) {
return (
<div className="flex h-full items-center">
@ -235,6 +243,8 @@ const Apps = ({
/>
)
}
{isShowTryAppPanel && <TryApp appId={appId} onClose={hideTryAppPanel} />}
</div>
)
}

View File

@ -2,6 +2,7 @@
import type { FC } from 'react'
import React, { useEffect, useState } from 'react'
import { useRouter } from 'next/navigation'
import type { CurrentTryAppParams } from '@/context/explore-context'
import ExploreContext from '@/context/explore-context'
import Sidebar from '@/app/components/explore/sidebar'
import { useAppContext } from '@/context/app-context'
@ -42,6 +43,16 @@ const Explore: FC<IExploreProps> = ({
return router.replace('/datasets')
}, [isCurrentWorkspaceDatasetOperator])
const [currentTryAppParams, setCurrentTryAppParams] = useState<CurrentTryAppParams | undefined>({ appId: '47b94c61-5b0d-402b-b5bb-482ee406bc68' })
const [isShowTryAppPanel, setIsShowTryAppPanel] = useState(true)
const setShowTryAppPanel = (showTryAppPanel: boolean, params?: CurrentTryAppParams) => {
if (showTryAppPanel)
setCurrentTryAppParams(params)
else
setCurrentTryAppParams(undefined)
setIsShowTryAppPanel(showTryAppPanel)
}
return (
<div className='flex h-full overflow-hidden border-t border-divider-regular bg-background-body'>
<ExploreContext.Provider
@ -54,6 +65,9 @@ const Explore: FC<IExploreProps> = ({
setInstalledApps,
isFetchingInstalledApps,
setIsFetchingInstalledApps,
currentApp: currentTryAppParams,
isShowTryAppPanel,
setShowTryAppPanel,
}
}
>

View File

@ -0,0 +1,32 @@
'use client'
import type { FC } from 'react'
import React, { useState } from 'react'
import Modal from '@/app/components/base/modal/index'
import Tab, { TypeEnum } from './tab'
type Props = {
appId: string
onClose: () => void
}
const TryApp: FC<Props> = ({
appId,
onClose,
}) => {
const [type, setType] = useState<TypeEnum>(TypeEnum.TRY)
return (
<Modal
isShow
onClose={onClose}
className='h-[calc(100vh-32px)] max-w-[calc(100vw-32px)]'
>
<Tab
value={type}
onChange={setType}
/>
{appId}
</Modal>
)
}
export default React.memo(TryApp)

View File

@ -0,0 +1,34 @@
'use client'
import type { FC } from 'react'
import React from 'react'
import TabHeader from '../../base/tab-header'
export enum TypeEnum {
TRY = 'try',
DETAIL = 'detail',
}
type Props = {
value: TypeEnum
onChange: (value: TypeEnum) => void
}
const Tab: FC<Props> = ({
value,
onChange,
}) => {
const tabs = [
{ id: TypeEnum.TRY, name: 'Try App' },
{ id: TypeEnum.DETAIL, name: 'App Details' },
]
return (
<div>
<TabHeader
items={tabs}
value={value}
onChange={onChange as (value: string) => void}
/>
</div>
)
}
export default React.memo(Tab)

View File

@ -2,6 +2,10 @@ import { createContext } from 'use-context-selector'
import type { InstalledApp } from '@/models/explore'
import { noop } from 'lodash-es'
export type CurrentTryAppParams = {
appId: string
}
type IExplore = {
controlUpdateInstalledApps: number
setControlUpdateInstalledApps: (controlUpdateInstalledApps: number) => void
@ -10,6 +14,9 @@ type IExplore = {
setInstalledApps: (installedApps: InstalledApp[]) => void
isFetchingInstalledApps: boolean
setIsFetchingInstalledApps: (isFetchingInstalledApps: boolean) => void
currentApp?: CurrentTryAppParams
isShowTryAppPanel: boolean
setShowTryAppPanel: (showTryAppPanel: boolean, params?: CurrentTryAppParams) => void
}
const ExploreContext = createContext<IExplore>({
@ -20,6 +27,9 @@ const ExploreContext = createContext<IExplore>({
setInstalledApps: noop,
isFetchingInstalledApps: false,
setIsFetchingInstalledApps: noop,
isShowTryAppPanel: false,
setShowTryAppPanel: noop,
currentApp: undefined,
})
export default ExploreContext