dify/web/app/components/plugins/card/index.tsx

87 lines
2.9 KiB
TypeScript
Raw Normal View History

2024-10-10 10:40:26 +08:00
import React from 'react'
import { RiVerifiedBadgeLine } from '@remixicon/react'
import type { Plugin } from '../types'
2024-10-11 14:10:24 +08:00
import Icon from '../card/base/card-icon'
2024-10-15 14:56:59 +08:00
import { Group } from '../../base/icons/src/vender/other'
2024-10-10 10:40:26 +08:00
import CornerMark from './base/corner-mark'
import Title from './base/title'
import OrgInfo from './base/org-info'
import Description from './base/description'
import cn from '@/utils/classnames'
2024-10-11 12:39:27 +08:00
import type { Locale } from '@/i18n'
2024-10-10 10:40:26 +08:00
type Props = {
className?: string
payload: Plugin
2024-10-11 14:24:43 +08:00
locale: Locale // The component is used in both client and server side, so we can't get the locale from both side(getLocaleOnServer and useContext)
titleLeft?: React.ReactNode
2024-10-10 10:40:26 +08:00
installed?: boolean
descriptionLineRows?: number
footer?: React.ReactNode
2024-10-11 12:39:27 +08:00
serverLocale?: Locale
2024-10-15 14:56:59 +08:00
isLoading?: boolean
loadingFileName?: string
2024-10-10 10:40:26 +08:00
}
const Card = ({
className,
payload,
titleLeft,
2024-10-10 10:40:26 +08:00
installed,
descriptionLineRows = 2,
footer,
2024-10-11 14:24:43 +08:00
locale,
2024-10-15 14:56:59 +08:00
isLoading = false,
loadingFileName,
2024-10-10 10:40:26 +08:00
}: Props) => {
2024-10-15 14:56:59 +08:00
const { type, name, org, label, brief, icon } = payload
const getLocalizedText = (obj: Record<string, string> | undefined) =>
obj?.[locale] || obj?.['en-US'] || ''
const LoadingPlaceholder = ({ className }: { className?: string }) => (
<div className={cn('h-2 rounded-sm opacity-20 bg-text-quaternary', className)} />
)
2024-10-10 10:40:26 +08:00
return (
<div className={cn('relative p-4 pb-3 border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg hover-bg-components-panel-on-panel-item-bg rounded-xl shadow-xs', className)}>
2024-10-15 14:56:59 +08:00
{!isLoading && <CornerMark text={type} />}
2024-10-10 10:40:26 +08:00
{/* Header */}
<div className="flex">
2024-10-15 14:56:59 +08:00
{isLoading
? (<div
className='flex max-w-10 max-h-10 p-1 justify-center items-center gap-2 flex-grow rounded-[10px]
border-[0.5px] border-components-panel-border bg-background-default backdrop-blur-sm'>
<div className='flex w-5 h-5 justify-center items-center'>
<Group className='text-text-tertiary' />
</div>
</div>)
: <Icon src={icon} installed={installed} />}
2024-10-10 10:40:26 +08:00
<div className="ml-3 grow">
<div className="flex items-center h-5">
2024-10-15 14:56:59 +08:00
<Title title={loadingFileName || getLocalizedText(label)} />
{!isLoading && <RiVerifiedBadgeLine className="shrink-0 ml-0.5 w-4 h-4 text-text-accent" />}
{titleLeft} {/* This can be version badge */}
2024-10-10 10:40:26 +08:00
</div>
<OrgInfo
className="mt-0.5"
orgName={org}
packageName={name}
2024-10-15 14:56:59 +08:00
isLoading={isLoading}
2024-10-10 10:40:26 +08:00
/>
</div>
</div>
2024-10-15 14:56:59 +08:00
{isLoading
? <LoadingPlaceholder className="mt-3 w-[420px]" />
: <Description
className="mt-3"
text={getLocalizedText(brief)}
descriptionLineRows={descriptionLineRows}
/>}
2024-10-10 10:40:26 +08:00
{footer && <div>{footer}</div>}
</div>
)
}
export default Card