Chore: frontend infrastructure upgrade (#16420)

Co-authored-by: NFish <douxc512@gmail.com>
Co-authored-by: zxhlyh <jasonapring2015@outlook.com>
Co-authored-by: twwu <twwu@dify.ai>
Co-authored-by: jZonG <jzongcode@gmail.com>
This commit is contained in:
Joel
2025-03-21 17:41:03 +08:00
committed by GitHub
parent e61415223b
commit 7709d9df20
1435 changed files with 13372 additions and 11612 deletions

View File

@@ -226,37 +226,37 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
}
return (
<div className="relative w-full py-1" onMouseLeave={onMouseLeave}>
<button className='h-8 w-[calc(100%_-_8px)] py-[6px] px-3 mx-1 flex items-center gap-2 hover:bg-state-base-hover rounded-lg cursor-pointer' onClick={onClickSettings}>
<span className='text-text-secondary system-sm-regular'>{t('app.editApp')}</span>
<button className='mx-1 flex h-8 w-[calc(100%_-_8px)] cursor-pointer items-center gap-2 rounded-lg px-3 py-[6px] hover:bg-state-base-hover' onClick={onClickSettings}>
<span className='system-sm-regular text-text-secondary'>{t('app.editApp')}</span>
</button>
<Divider className="!my-1" />
<button className='h-8 w-[calc(100%_-_8px)] py-[6px] px-3 mx-1 flex items-center gap-2 hover:bg-state-base-hover rounded-lg cursor-pointer' onClick={onClickDuplicate}>
<span className='text-text-secondary system-sm-regular'>{t('app.duplicate')}</span>
<button className='mx-1 flex h-8 w-[calc(100%_-_8px)] cursor-pointer items-center gap-2 rounded-lg px-3 py-[6px] hover:bg-state-base-hover' onClick={onClickDuplicate}>
<span className='system-sm-regular text-text-secondary'>{t('app.duplicate')}</span>
</button>
<button className='h-8 w-[calc(100%_-_8px)] py-[6px] px-3 mx-1 flex items-center gap-2 hover:bg-state-base-hover rounded-lg cursor-pointer' onClick={onClickExport}>
<span className='text-text-secondary system-sm-regular'>{t('app.export')}</span>
<button className='mx-1 flex h-8 w-[calc(100%_-_8px)] cursor-pointer items-center gap-2 rounded-lg px-3 py-[6px] hover:bg-state-base-hover' onClick={onClickExport}>
<span className='system-sm-regular text-text-secondary'>{t('app.export')}</span>
</button>
{(app.mode === 'completion' || app.mode === 'chat') && (
<>
<Divider className="!my-1" />
<div
className='h-9 py-2 px-3 mx-1 flex items-center hover:bg-state-base-hover rounded-lg cursor-pointer'
className='mx-1 flex h-9 cursor-pointer items-center rounded-lg px-3 py-2 hover:bg-state-base-hover'
onClick={onClickSwitch}
>
<span className='text-text-secondary text-sm leading-5'>{t('app.switch')}</span>
<span className='text-sm leading-5 text-text-secondary'>{t('app.switch')}</span>
</div>
</>
)}
<Divider className="!my-1" />
<button className='h-8 w-[calc(100%_-_8px)] py-[6px] px-3 mx-1 flex items-center gap-2 hover:bg-state-base-hover rounded-lg cursor-pointer' onClick={onClickInstalledApp}>
<span className='text-text-secondary system-sm-regular'>{t('app.openInExplore')}</span>
<button className='mx-1 flex h-8 w-[calc(100%_-_8px)] cursor-pointer items-center gap-2 rounded-lg px-3 py-[6px] hover:bg-state-base-hover' onClick={onClickInstalledApp}>
<span className='system-sm-regular text-text-secondary'>{t('app.openInExplore')}</span>
</button>
<Divider className="!my-1" />
<div
className='group h-8 w-[calc(100%_-_8px)] py-[6px] px-3 mx-1 flex items-center gap-2 hover:bg-state-destructive-hover rounded-lg cursor-pointer'
className='group mx-1 flex h-8 w-[calc(100%_-_8px)] cursor-pointer items-center gap-2 rounded-lg px-3 py-[6px] hover:bg-state-destructive-hover'
onClick={onClickDelete}
>
<span className='text-text-secondary system-sm-regular group-hover:text-text-destructive'>
<span className='system-sm-regular text-text-secondary group-hover:text-text-destructive'>
{t('common.operation.delete')}
</span>
</div>
@@ -276,9 +276,9 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
e.preventDefault()
getRedirection(isCurrentWorkspaceEditor, app, push)
}}
className='relative h-[160px] group col-span-1 bg-components-card-bg border-[1px] border-solid border-components-card-border rounded-xl shadow-sm inline-flex flex-col transition-all duration-200 ease-in-out cursor-pointer hover:shadow-lg'
className='group relative col-span-1 inline-flex h-[160px] cursor-pointer flex-col rounded-xl border-[1px] border-solid border-components-card-border bg-components-card-bg shadow-sm transition-all duration-200 ease-in-out hover:shadow-lg'
>
<div className='flex pt-[14px] px-[14px] pb-3 h-[66px] items-center gap-3 grow-0 shrink-0'>
<div className='flex h-[66px] shrink-0 grow-0 items-center gap-3 px-[14px] pb-3 pt-[14px]'>
<div className='relative shrink-0'>
<AppIcon
size="large"
@@ -287,13 +287,13 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
background={app.icon_background}
imageUrl={app.icon_url}
/>
<AppTypeIcon type={app.mode} wrapperClassName='absolute -bottom-0.5 -right-0.5 w-4 h-4 shadow-sm' className='w-3 h-3' />
<AppTypeIcon type={app.mode} wrapperClassName='absolute -bottom-0.5 -right-0.5 w-4 h-4 shadow-sm' className='h-3 w-3' />
</div>
<div className='grow w-0 py-[1px]'>
<div className='flex items-center text-sm leading-5 font-semibold text-text-secondary'>
<div className='w-0 grow py-[1px]'>
<div className='flex items-center text-sm font-semibold leading-5 text-text-secondary'>
<div className='truncate' title={app.name}>{app.name}</div>
</div>
<div className='flex items-center text-[10px] leading-[18px] text-text-tertiary font-medium'>
<div className='flex items-center text-[10px] font-medium leading-[18px] text-text-tertiary'>
{app.mode === 'advanced-chat' && <div className='truncate'>{t('app.types.advanced').toUpperCase()}</div>}
{app.mode === 'chat' && <div className='truncate'>{t('app.types.chatbot').toUpperCase()}</div>}
{app.mode === 'agent-chat' && <div className='truncate'>{t('app.types.agent').toUpperCase()}</div>}
@@ -311,17 +311,17 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
</div>
</div>
<div className={cn(
'absolute bottom-1 left-0 right-0 items-center shrink-0 pt-1 pl-[14px] pr-[6px] pb-[6px] h-[42px]',
'absolute bottom-1 left-0 right-0 h-[42px] shrink-0 items-center pb-[6px] pl-[14px] pr-[6px] pt-1',
tags.length ? 'flex' : '!hidden group-hover:!flex',
)}>
{isCurrentWorkspaceEditor && (
<>
<div className={cn('grow flex items-center gap-1 w-0')} onClick={(e) => {
<div className={cn('flex w-0 grow items-center gap-1')} onClick={(e) => {
e.stopPropagation()
e.preventDefault()
}}>
<div className={cn(
'group-hover:!block group-hover:!mr-0 mr-[41px] grow w-full',
'mr-[41px] w-full grow group-hover:!mr-0 group-hover:!block',
tags.length ? '!block' : '!hidden',
)}>
<TagSelector
@@ -335,23 +335,23 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
/>
</div>
</div>
<div className='!hidden group-hover:!flex shrink-0 mx-1 w-[1px] h-[14px]' />
<div className='!hidden group-hover:!flex shrink-0'>
<div className='mx-1 !hidden h-[14px] w-[1px] shrink-0 group-hover:!flex' />
<div className='!hidden shrink-0 group-hover:!flex'>
<CustomPopover
htmlContent={<Operations />}
position="br"
trigger="click"
btnElement={
<div
className='flex items-center justify-center w-8 h-8 cursor-pointer rounded-md'
className='flex h-8 w-8 cursor-pointer items-center justify-center rounded-md'
>
<RiMoreFill className='w-4 h-4 text-text-tertiary' />
<RiMoreFill className='h-4 w-4 text-text-tertiary' />
</div>
}
btnClassName={open =>
cn(
open ? '!bg-black/5 !shadow-none' : '!bg-transparent',
'h-8 w-8 !p-2 rounded-md border-none hover:!bg-black/5',
'h-8 w-8 rounded-md border-none !p-2 hover:!bg-black/5',
)
}
popupClassName={
@@ -359,7 +359,7 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
? '!w-[256px] translate-x-[-224px]'
: '!w-[160px] translate-x-[-128px]'
}
className={'h-fit !z-20'}
className={'!z-20 h-fit'}
/>
</div>
</>

View File

@@ -78,10 +78,10 @@ const Apps = () => {
const anchorRef = useRef<HTMLDivElement>(null)
const options = [
{ value: 'all', text: t('app.types.all'), icon: <RiApps2Line className='w-[14px] h-[14px] mr-1' /> },
{ value: 'chat', text: t('app.types.chatbot'), icon: <RiMessage3Line className='w-[14px] h-[14px] mr-1' /> },
{ value: 'agent-chat', text: t('app.types.agent'), icon: <RiRobot3Line className='w-[14px] h-[14px] mr-1' /> },
{ value: 'workflow', text: t('app.types.workflow'), icon: <RiExchange2Line className='w-[14px] h-[14px] mr-1' /> },
{ value: 'all', text: t('app.types.all'), icon: <RiApps2Line className='mr-1 h-[14px] w-[14px]' /> },
{ value: 'chat', text: t('app.types.chatbot'), icon: <RiMessage3Line className='mr-1 h-[14px] w-[14px]' /> },
{ value: 'agent-chat', text: t('app.types.agent'), icon: <RiRobot3Line className='mr-1 h-[14px] w-[14px]' /> },
{ value: 'workflow', text: t('app.types.workflow'), icon: <RiExchange2Line className='mr-1 h-[14px] w-[14px]' /> },
]
useEffect(() => {
@@ -134,7 +134,7 @@ const Apps = () => {
return (
<>
<div className='sticky top-0 flex justify-between items-center pt-4 px-12 pb-2 leading-[56px] bg-background-body z-10 flex-wrap gap-y-2'>
<div className='sticky top-0 z-10 flex flex-wrap items-center justify-between gap-y-2 bg-background-body px-12 pb-2 pt-4 leading-[56px]'>
<TabSliderNew
value={activeTab}
onChange={setActiveTab}
@@ -159,14 +159,14 @@ const Apps = () => {
</div>
</div>
{(data && data[0].total > 0)
? <div className='grid content-start grid-cols-1 sm:grid-cols-1 md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-5 2k:grid-cols-6 gap-4 px-12 pt-2 grow relative'>
? <div className='relative grid grow grid-cols-1 content-start gap-4 px-12 pt-2 sm:grid-cols-1 md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-5 2k:grid-cols-6'>
{isCurrentWorkspaceEditor
&& <NewAppCard onSuccess={mutate} />}
{data.map(({ data: apps }) => apps.map(app => (
<AppCard key={app.id} app={app} onRefresh={mutate} />
)))}
</div>
: <div className='grid content-start grid-cols-1 sm:grid-cols-1 md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-5 2k:grid-cols-6 gap-4 px-12 pt-2 grow relative overflow-hidden'>
: <div className='relative grid grow grid-cols-1 content-start gap-4 overflow-hidden px-12 pt-2 sm:grid-cols-1 md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-5 2k:grid-cols-6'>
{isCurrentWorkspaceEditor
&& <NewAppCard className='z-10' onSuccess={mutate} />}
<NoAppsFound />
@@ -186,14 +186,14 @@ function NoAppsFound() {
const { t } = useTranslation()
function renderDefaultCard() {
const defaultCards = Array.from({ length: 36 }, (_, index) => (
<div key={index} className='h-[160px] inline-flex rounded-xl bg-background-default-lighter'></div>
<div key={index} className='inline-flex h-[160px] rounded-xl bg-background-default-lighter'></div>
))
return defaultCards
}
return (
<>
{renderDefaultCard()}
<div className='absolute top-0 left-0 right-0 bottom-0 flex items-center justify-center bg-gradient-to-t from-background-body to-transparent'>
<div className='absolute bottom-0 left-0 right-0 top-0 flex items-center justify-center bg-gradient-to-t from-background-body to-transparent'>
<span className='system-md-medium text-text-tertiary'>{t('app.newApp.noAppsFound')}</span>
</div>
</>

View File

@@ -1,6 +1,6 @@
'use client'
import { forwardRef, useMemo, useState } from 'react'
import { useMemo, useState } from 'react'
import {
useRouter,
useSearchParams,
@@ -18,7 +18,15 @@ export type CreateAppCardProps = {
onSuccess?: () => void
}
const CreateAppCard = forwardRef<HTMLDivElement, CreateAppCardProps>(({ className, onSuccess }, ref) => {
const CreateAppCard = (
{
ref,
className,
onSuccess,
}: CreateAppCardProps & {
ref: React.RefObject<HTMLDivElement>;
},
) => {
const { t } = useTranslation()
const { onPlanInfoChanged } = useProviderContext()
const searchParams = useSearchParams()
@@ -39,22 +47,22 @@ const CreateAppCard = forwardRef<HTMLDivElement, CreateAppCardProps>(({ classNam
return (
<div
ref={ref}
className={cn('relative col-span-1 inline-flex flex-col justify-between h-[160px] bg-components-card-bg rounded-xl border-[0.5px] border-components-card-border', className)}
className={cn('relative col-span-1 inline-flex h-[160px] flex-col justify-between rounded-xl border-[0.5px] border-components-card-border bg-components-card-bg', className)}
>
<div className='grow p-2 rounded-t-xl'>
<div className='px-6 pt-2 pb-1 text-xs font-medium leading-[18px] text-text-tertiary'>{t('app.createApp')}</div>
<button className='w-full flex items-center mb-1 px-6 py-[7px] rounded-lg text-[13px] font-medium leading-[18px] text-text-tertiary cursor-pointer hover:text-text-secondary hover:bg-state-base-hover' onClick={() => setShowNewAppModal(true)}>
<FilePlus01 className='shrink-0 mr-2 w-4 h-4' />
<div className='grow rounded-t-xl p-2'>
<div className='px-6 pb-1 pt-2 text-xs font-medium leading-[18px] text-text-tertiary'>{t('app.createApp')}</div>
<button className='mb-1 flex w-full cursor-pointer items-center rounded-lg px-6 py-[7px] text-[13px] font-medium leading-[18px] text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary' onClick={() => setShowNewAppModal(true)}>
<FilePlus01 className='mr-2 h-4 w-4 shrink-0' />
{t('app.newApp.startFromBlank')}
</button>
<button className='w-full flex items-center px-6 py-[7px] rounded-lg text-[13px] font-medium leading-[18px] text-text-tertiary cursor-pointer hover:text-text-secondary hover:bg-state-base-hover' onClick={() => setShowNewAppTemplateDialog(true)}>
<FilePlus02 className='shrink-0 mr-2 w-4 h-4' />
<button className='flex w-full cursor-pointer items-center rounded-lg px-6 py-[7px] text-[13px] font-medium leading-[18px] text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary' onClick={() => setShowNewAppTemplateDialog(true)}>
<FilePlus02 className='mr-2 h-4 w-4 shrink-0' />
{t('app.newApp.startFromTemplate')}
</button>
<button
onClick={() => setShowCreateFromDSLModal(true)}
className='w-full flex items-center px-6 py-[7px] rounded-lg text-[13px] font-medium leading-[18px] text-text-tertiary cursor-pointer hover:text-text-secondary hover:bg-state-base-hover'>
<FileArrow01 className='shrink-0 mr-2 w-4 h-4' />
className='flex w-full cursor-pointer items-center rounded-lg px-6 py-[7px] text-[13px] font-medium leading-[18px] text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary'>
<FileArrow01 className='mr-2 h-4 w-4 shrink-0' />
{t('app.importDSL')}
</button>
</div>
@@ -103,7 +111,7 @@ const CreateAppCard = forwardRef<HTMLDivElement, CreateAppCardProps>(({ classNam
/>
</div>
)
})
}
CreateAppCard.displayName = 'CreateAppCard'
export default CreateAppCard

View File

@@ -13,17 +13,17 @@ const AppList = () => {
const systemFeatures = useContextSelector(AppContext, v => v.systemFeatures)
return (
<div className='relative flex flex-col overflow-y-auto bg-background-body shrink-0 h-0 grow'>
<div className='relative flex h-0 shrink-0 grow flex-col overflow-y-auto bg-background-body'>
<Apps />
{systemFeatures.license.status === LicenseStatus.NONE && <footer className='px-12 py-6 grow-0 shrink-0'>
<h3 className='text-xl font-semibold leading-tight text-gradient'>{t('app.join')}</h3>
<p className='mt-1 system-sm-regular text-text-tertiary'>{t('app.communityIntro')}</p>
<div className='flex items-center gap-2 mt-3'>
{systemFeatures.license.status === LicenseStatus.NONE && <footer className='shrink-0 grow-0 px-12 py-6'>
<h3 className='text-gradient text-xl font-semibold leading-tight'>{t('app.join')}</h3>
<p className='system-sm-regular mt-1 text-text-tertiary'>{t('app.communityIntro')}</p>
<div className='mt-3 flex items-center gap-2'>
<Link className={style.socialMediaLink} target='_blank' rel='noopener noreferrer' href='https://github.com/langgenius/dify'>
<RiGithubFill className='w-5 h-5 text-text-tertiary' />
<RiGithubFill className='h-5 w-5 text-text-tertiary' />
</Link>
<Link className={style.socialMediaLink} target='_blank' rel='noopener noreferrer' href='https://discord.gg/FngNHpbcY7'>
<RiDiscordFill className='w-5 h-5 text-text-tertiary' />
<RiDiscordFill className='h-5 w-5 text-text-tertiary' />
</Link>
</div>
</footer>}