mirror of
https://github.com/langgenius/dify.git
synced 2026-04-15 01:38:19 +08:00
fix(trigger): readme style
This commit is contained in:
parent
c05fa9963a
commit
90753b2782
@ -3,33 +3,46 @@
|
||||
* Extracted from the main markdown renderer for modularity.
|
||||
* Uses the ImageGallery component to display images.
|
||||
*/
|
||||
import React, { useEffect, useMemo } from 'react'
|
||||
import React, { useEffect, useMemo, useState } from 'react'
|
||||
import ImageGallery from '@/app/components/base/image-gallery'
|
||||
import { getMarkdownImageURL } from './utils'
|
||||
import { usePluginReadmeAsset } from '@/service/use-plugins'
|
||||
import type { SimplePluginInfo } from '../markdown/react-markdown-wrapper'
|
||||
|
||||
const Img = ({ src, pluginInfo }: { src: string, pluginInfo?: SimplePluginInfo }) => {
|
||||
type ImgProps = {
|
||||
src: string
|
||||
pluginInfo?: SimplePluginInfo
|
||||
}
|
||||
|
||||
const Img: React.FC<ImgProps> = ({ src, pluginInfo }) => {
|
||||
const { plugin_unique_identifier, plugin_id } = pluginInfo || {}
|
||||
const { data: assetData } = usePluginReadmeAsset({ plugin_unique_identifier, file_name: src })
|
||||
|
||||
const blobUrl = useMemo(() => {
|
||||
if (assetData)
|
||||
return URL.createObjectURL(assetData)
|
||||
|
||||
return getMarkdownImageURL(src, plugin_id)
|
||||
}, [assetData, plugin_id, src])
|
||||
const [blobUrl, setBlobUrl] = useState<string>()
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (blobUrl && assetData)
|
||||
URL.revokeObjectURL(blobUrl)
|
||||
if (!assetData) {
|
||||
setBlobUrl(undefined)
|
||||
return
|
||||
}
|
||||
}, [blobUrl, assetData])
|
||||
|
||||
const objectUrl = URL.createObjectURL(assetData)
|
||||
setBlobUrl(objectUrl)
|
||||
|
||||
return () => {
|
||||
URL.revokeObjectURL(objectUrl)
|
||||
}
|
||||
}, [assetData])
|
||||
|
||||
const imageUrl = useMemo(() => {
|
||||
if (blobUrl)
|
||||
return blobUrl
|
||||
|
||||
return getMarkdownImageURL(src, plugin_id)
|
||||
}, [blobUrl, plugin_id, src])
|
||||
|
||||
return (
|
||||
<div className='markdown-img-wrapper'>
|
||||
<ImageGallery srcs={[blobUrl]} />
|
||||
<div className="markdown-img-wrapper">
|
||||
<ImageGallery srcs={[imageUrl]} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -3,44 +3,65 @@
|
||||
* Extracted from the main markdown renderer for modularity.
|
||||
* Handles special rendering for paragraphs that directly contain an image.
|
||||
*/
|
||||
import React, { useEffect, useMemo } from 'react'
|
||||
import React, { useEffect, useMemo, useState } from 'react'
|
||||
import ImageGallery from '@/app/components/base/image-gallery'
|
||||
import { getMarkdownImageURL } from './utils'
|
||||
import { usePluginReadmeAsset } from '@/service/use-plugins'
|
||||
import type { SimplePluginInfo } from '../markdown/react-markdown-wrapper'
|
||||
|
||||
const Paragraph = (props: { pluginInfo?: SimplePluginInfo, node?: any, children?: any }) => {
|
||||
const { node, pluginInfo, children } = props
|
||||
type ParagraphProps = {
|
||||
pluginInfo?: SimplePluginInfo
|
||||
node?: any
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
const Paragraph: React.FC<ParagraphProps> = ({ pluginInfo, node, children }) => {
|
||||
const { plugin_unique_identifier, plugin_id } = pluginInfo || {}
|
||||
const children_node = node.children
|
||||
const { data: assetData } = usePluginReadmeAsset({ plugin_unique_identifier, file_name: children_node?.[0]?.tagName !== 'img' ? '' : children_node[0].properties?.src })
|
||||
const childrenNode = node?.children as Array<any> | undefined
|
||||
const firstChild = childrenNode?.[0]
|
||||
const isImageParagraph = firstChild?.tagName === 'img'
|
||||
const imageSrc = isImageParagraph ? firstChild?.properties?.src : undefined
|
||||
|
||||
const blobUrl = useMemo(() => {
|
||||
if (assetData)
|
||||
return URL.createObjectURL(assetData)
|
||||
const { data: assetData } = usePluginReadmeAsset({
|
||||
plugin_unique_identifier,
|
||||
file_name: isImageParagraph && imageSrc ? imageSrc : '',
|
||||
})
|
||||
|
||||
if (children_node?.[0]?.tagName === 'img' && children_node[0].properties?.src)
|
||||
return getMarkdownImageURL(children_node[0].properties.src, plugin_id)
|
||||
|
||||
return ''
|
||||
}, [assetData, children_node, plugin_id])
|
||||
const [blobUrl, setBlobUrl] = useState<string>()
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (blobUrl && assetData)
|
||||
URL.revokeObjectURL(blobUrl)
|
||||
if (!assetData) {
|
||||
setBlobUrl(undefined)
|
||||
return
|
||||
}
|
||||
}, [blobUrl, assetData])
|
||||
|
||||
if (children_node?.[0]?.tagName === 'img') {
|
||||
const objectUrl = URL.createObjectURL(assetData)
|
||||
setBlobUrl(objectUrl)
|
||||
|
||||
return () => {
|
||||
URL.revokeObjectURL(objectUrl)
|
||||
}
|
||||
}, [assetData])
|
||||
|
||||
const imageUrl = useMemo(() => {
|
||||
if (blobUrl)
|
||||
return blobUrl
|
||||
|
||||
if (isImageParagraph && imageSrc)
|
||||
return getMarkdownImageURL(imageSrc, plugin_id)
|
||||
|
||||
return ''
|
||||
}, [blobUrl, imageSrc, isImageParagraph, plugin_id])
|
||||
|
||||
if (isImageParagraph) {
|
||||
const remainingChildren = Array.isArray(children) && children.length > 1 ? children.slice(1) : undefined
|
||||
|
||||
return (
|
||||
<div className="markdown-img-wrapper">
|
||||
<ImageGallery srcs={[blobUrl]} />
|
||||
{
|
||||
Array.isArray(children) && children.length > 1 && (
|
||||
<div className="mt-2">{children.slice(1)}</div>
|
||||
)
|
||||
}
|
||||
<ImageGallery srcs={[imageUrl]} />
|
||||
{remainingChildren && (
|
||||
<div className="mt-2">{remainingChildren}</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,7 +1,26 @@
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Confirm from '@/app/components/base/confirm'
|
||||
import { Github } from '@/app/components/base/icons/src/public/common'
|
||||
import { BoxSparkleFill } from '@/app/components/base/icons/src/vender/plugin'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { AuthCategory, PluginAuth } from '@/app/components/plugins/plugin-auth'
|
||||
import OperationDropdown from '@/app/components/plugins/plugin-detail-panel/operation-dropdown'
|
||||
import PluginInfo from '@/app/components/plugins/plugin-page/plugin-info'
|
||||
import UpdateFromMarketplace from '@/app/components/plugins/update-plugin/from-market-place'
|
||||
import PluginVersionPicker from '@/app/components/plugins/update-plugin/plugin-version-picker'
|
||||
import { API_PREFIX } from '@/config'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useGlobalPublicStore } from '@/context/global-public-context'
|
||||
import { useGetLanguage, useI18N } from '@/context/i18n'
|
||||
import { useModalContext } from '@/context/modal-context'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { uninstallPlugin } from '@/service/plugins'
|
||||
import { useAllToolProviders, useInvalidateAllToolProviders } from '@/service/use-tools'
|
||||
import cn from '@/utils/classnames'
|
||||
import { getMarketplaceUrl } from '@/utils/var'
|
||||
import {
|
||||
RiArrowLeftRightLine,
|
||||
RiBugLine,
|
||||
@ -9,54 +28,35 @@ import {
|
||||
RiHardDrive3Line,
|
||||
RiVerifiedBadgeLine,
|
||||
} from '@remixicon/react'
|
||||
import type { PluginDetail } from '../types'
|
||||
import { PluginCategoryEnum, PluginSource } from '../types'
|
||||
import Description from '../card/base/description'
|
||||
import Icon from '../card/base/card-icon'
|
||||
import Title from '../card/base/title'
|
||||
import OrgInfo from '../card/base/org-info'
|
||||
import { useGitHubReleases } from '../install-plugin/hooks'
|
||||
import PluginVersionPicker from '@/app/components/plugins/update-plugin/plugin-version-picker'
|
||||
import UpdateFromMarketplace from '@/app/components/plugins/update-plugin/from-market-place'
|
||||
import OperationDropdown from '@/app/components/plugins/plugin-detail-panel/operation-dropdown'
|
||||
import PluginInfo from '@/app/components/plugins/plugin-page/plugin-info'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
import Confirm from '@/app/components/base/confirm'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { BoxSparkleFill } from '@/app/components/base/icons/src/vender/plugin'
|
||||
import { Github } from '@/app/components/base/icons/src/public/common'
|
||||
import { uninstallPlugin } from '@/service/plugins'
|
||||
import { useGetLanguage, useI18N } from '@/context/i18n'
|
||||
import { useModalContext } from '@/context/modal-context'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { useInvalidateAllToolProviders } from '@/service/use-tools'
|
||||
import { API_PREFIX } from '@/config'
|
||||
import cn from '@/utils/classnames'
|
||||
import { getMarketplaceUrl } from '@/utils/var'
|
||||
import { PluginAuth } from '@/app/components/plugins/plugin-auth'
|
||||
import { AuthCategory } from '@/app/components/plugins/plugin-auth'
|
||||
import { useAllToolProviders } from '@/service/use-tools'
|
||||
import DeprecationNotice from '../base/deprecation-notice'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import { useTheme } from 'next-themes'
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { AutoUpdateLine } from '../../base/icons/src/vender/system'
|
||||
import { convertUTCDaySecondsToLocalSeconds, timeOfDayToDayjs } from '../reference-setting-modal/auto-update-setting/utils'
|
||||
import DeprecationNotice from '../base/deprecation-notice'
|
||||
import Icon from '../card/base/card-icon'
|
||||
import Description from '../card/base/description'
|
||||
import OrgInfo from '../card/base/org-info'
|
||||
import Title from '../card/base/title'
|
||||
import { useGitHubReleases } from '../install-plugin/hooks'
|
||||
import useReferenceSetting from '../plugin-page/use-reference-setting'
|
||||
import { AUTO_UPDATE_MODE } from '../reference-setting-modal/auto-update-setting/types'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useGlobalPublicStore } from '@/context/global-public-context'
|
||||
import { convertUTCDaySecondsToLocalSeconds, timeOfDayToDayjs } from '../reference-setting-modal/auto-update-setting/utils'
|
||||
import type { PluginDetail } from '../types'
|
||||
import { PluginCategoryEnum, PluginSource } from '../types'
|
||||
|
||||
const i18nPrefix = 'plugin.action'
|
||||
|
||||
type Props = {
|
||||
detail: PluginDetail
|
||||
onHide: () => void
|
||||
onUpdate: (isDelete?: boolean) => void
|
||||
isReadmeView?: boolean
|
||||
onHide?: () => void
|
||||
onUpdate?: (isDelete?: boolean) => void
|
||||
}
|
||||
|
||||
const DetailHeader = ({
|
||||
detail,
|
||||
isReadmeView = false,
|
||||
onHide,
|
||||
onUpdate,
|
||||
}: Props) => {
|
||||
@ -156,7 +156,7 @@ const DetailHeader = ({
|
||||
if (needUpdate) {
|
||||
setShowUpdatePluginModal({
|
||||
onSaveCallback: () => {
|
||||
onUpdate()
|
||||
onUpdate?.()
|
||||
},
|
||||
payload: {
|
||||
type: PluginSource.github,
|
||||
@ -176,7 +176,7 @@ const DetailHeader = ({
|
||||
}
|
||||
|
||||
const handleUpdatedFromMarketplace = () => {
|
||||
onUpdate()
|
||||
onUpdate?.()
|
||||
hideUpdateModal()
|
||||
}
|
||||
|
||||
@ -201,7 +201,7 @@ const DetailHeader = ({
|
||||
hideDeleting()
|
||||
if (res.success) {
|
||||
hideDeleteConfirm()
|
||||
onUpdate(true)
|
||||
onUpdate?.(true)
|
||||
if (PluginCategoryEnum.model.includes(category))
|
||||
refreshModelProviders()
|
||||
if (PluginCategoryEnum.tool.includes(category))
|
||||
@ -210,17 +210,17 @@ const DetailHeader = ({
|
||||
}, [showDeleting, installation_id, hideDeleting, hideDeleteConfirm, onUpdate, category, refreshModelProviders, invalidateAllToolProviders])
|
||||
|
||||
return (
|
||||
<div className={cn('shrink-0 border-b border-divider-subtle bg-components-panel-bg p-4 pb-3')}>
|
||||
<div className={cn('shrink-0 border-b border-divider-subtle bg-components-panel-bg p-4 pb-3', isReadmeView && 'border-b-0 bg-transparent p-0')}>
|
||||
<div className="flex">
|
||||
<div className='overflow-hidden rounded-xl border border-components-panel-border-subtle'>
|
||||
<div className={cn('overflow-hidden rounded-xl border border-components-panel-border-subtle', isReadmeView && 'bg-components-panel-bg')}>
|
||||
<Icon src={`${API_PREFIX}/workspaces/current/plugin/icon?tenant_id=${tenant_id}&filename=${icon}`} />
|
||||
</div>
|
||||
<div className="ml-3 w-0 grow">
|
||||
<div className="flex h-5 items-center">
|
||||
<Title title={label[locale]} />
|
||||
{verified && <RiVerifiedBadgeLine className="ml-0.5 h-4 w-4 shrink-0 text-text-accent" />}
|
||||
{verified && !isReadmeView && <RiVerifiedBadgeLine className="ml-0.5 h-4 w-4 shrink-0 text-text-accent" />}
|
||||
<PluginVersionPicker
|
||||
disabled={!isFromMarketplace}
|
||||
disabled={!isFromMarketplace || isReadmeView}
|
||||
isShow={isShow}
|
||||
onShowChange={setIsShow}
|
||||
pluginID={plugin_id}
|
||||
@ -240,7 +240,7 @@ const DetailHeader = ({
|
||||
text={
|
||||
<>
|
||||
<div>{isFromGitHub ? meta!.version : version}</div>
|
||||
{isFromMarketplace && <RiArrowLeftRightLine className='ml-1 h-3 w-3 text-text-tertiary' />}
|
||||
{isFromMarketplace && !isReadmeView && <RiArrowLeftRightLine className='ml-1 h-3 w-3 text-text-tertiary' />}
|
||||
</>
|
||||
}
|
||||
hasRedCornerMark={hasNewVersion}
|
||||
@ -248,7 +248,7 @@ const DetailHeader = ({
|
||||
}
|
||||
/>
|
||||
{/* Auto update info */}
|
||||
{isAutoUpgradeEnabled && (
|
||||
{isAutoUpgradeEnabled && !isReadmeView && (
|
||||
<Tooltip popupContent={t('plugin.autoUpdate.nextUpdateTime', { time: timeOfDayToDayjs(convertUTCDaySecondsToLocalSeconds(autoUpgradeInfo?.upgrade_time_of_day || 0, timezone!)).format('hh:mm A') })}>
|
||||
{/* add a a div to fix tooltip hover not show problem */}
|
||||
<div>
|
||||
@ -302,18 +302,19 @@ const DetailHeader = ({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex gap-1'>
|
||||
<OperationDropdown
|
||||
source={detail.source}
|
||||
onInfo={showPluginInfo}
|
||||
onCheckVersion={handleUpdate}
|
||||
onRemove={showDeleteConfirm}
|
||||
detailUrl={detailUrl}
|
||||
/>
|
||||
<ActionButton onClick={onHide}>
|
||||
<RiCloseLine className='h-4 w-4' />
|
||||
</ActionButton>
|
||||
</div>
|
||||
{!isReadmeView && (
|
||||
<div className='flex gap-1'>
|
||||
<OperationDropdown
|
||||
source={detail.source}
|
||||
onInfo={showPluginInfo}
|
||||
onCheckVersion={handleUpdate}
|
||||
onRemove={showDeleteConfirm}
|
||||
detailUrl={detailUrl}
|
||||
/>
|
||||
<ActionButton onClick={onHide}>
|
||||
<RiCloseLine className='h-4 w-4' />
|
||||
</ActionButton>
|
||||
</div>)}
|
||||
</div>
|
||||
{isFromMarketplace && (
|
||||
<DeprecationNotice
|
||||
@ -324,9 +325,9 @@ const DetailHeader = ({
|
||||
className='mt-3'
|
||||
/>
|
||||
)}
|
||||
<Description className='mb-2 mt-3 h-auto' text={description[locale]} descriptionLineRows={2}></Description>
|
||||
{!isReadmeView && <Description className='mb-2 mt-3 h-auto' text={description[locale]} descriptionLineRows={2}></Description>}
|
||||
{
|
||||
category === PluginCategoryEnum.tool && (
|
||||
category === PluginCategoryEnum.tool && !isReadmeView && (
|
||||
<PluginAuth
|
||||
pluginPayload={{
|
||||
provider: provider?.name || '',
|
||||
|
||||
@ -1,118 +0,0 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
RiBugLine,
|
||||
RiHardDrive3Line,
|
||||
RiVerifiedBadgeLine,
|
||||
} from '@remixicon/react'
|
||||
import { BoxSparkleFill } from '@/app/components/base/icons/src/vender/plugin'
|
||||
import { Github } from '@/app/components/base/icons/src/public/common'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
import { API_PREFIX } from '@/config'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import type { PluginDetail } from '@/app/components/plugins/types'
|
||||
import { PluginSource } from '@/app/components/plugins/types'
|
||||
import OrgInfo from '@/app/components/plugins/card/base/org-info'
|
||||
import Icon from '@/app/components/plugins/card/base/card-icon'
|
||||
import type { TypeWithI18N } from '../../base/form/types'
|
||||
|
||||
type PluginInfoProps = {
|
||||
detail: PluginDetail & { icon?: string, label?: TypeWithI18N<string>, author?: string, name?: string, verified?: boolean }
|
||||
size?: 'default' | 'large'
|
||||
}
|
||||
|
||||
const PluginInfo: FC<PluginInfoProps> = ({
|
||||
detail,
|
||||
size = 'default',
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { currentWorkspace } = useAppContext()
|
||||
const locale = useLanguage()
|
||||
|
||||
const tenant_id = currentWorkspace?.id
|
||||
const {
|
||||
version,
|
||||
source,
|
||||
} = detail
|
||||
|
||||
const icon = detail.declaration?.icon || detail?.icon
|
||||
const label = detail.declaration?.label || detail?.label
|
||||
const author = detail.declaration?.author || detail?.author
|
||||
const name = detail.declaration?.name || detail?.name
|
||||
const verified = detail.declaration?.verified || detail?.verified
|
||||
|
||||
const isLarge = size === 'large'
|
||||
const iconSize = isLarge ? 'h-10 w-10' : 'h-8 w-8'
|
||||
const titleSize = isLarge ? 'text-sm' : 'text-xs'
|
||||
|
||||
return (
|
||||
<div className={`flex items-center ${isLarge ? 'gap-3' : 'gap-2'}`}>
|
||||
{/* Plugin Icon */}
|
||||
<div className={`shrink-0 overflow-hidden rounded-lg border border-components-panel-border-subtle ${iconSize}`}>
|
||||
<Icon src={icon?.startsWith('http') ? icon : `${API_PREFIX}/workspaces/current/plugin/icon?tenant_id=${tenant_id}&filename=${icon}`} />
|
||||
</div>
|
||||
|
||||
{/* Plugin Details */}
|
||||
<div className="min-w-0 flex-1">
|
||||
{/* Name and Version */}
|
||||
<div className="mb-0.5 flex items-center gap-1">
|
||||
<h3 className={`truncate font-semibold text-text-secondary ${titleSize}`}>
|
||||
{label?.[locale]}
|
||||
</h3>
|
||||
{verified && <RiVerifiedBadgeLine className="h-3 w-3 shrink-0 text-text-accent" />}
|
||||
<Badge
|
||||
className="mx-1"
|
||||
uppercase={false}
|
||||
text={version ?? detail.plugin_unique_identifier.split(':')[1]?.split('@')?.[0]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Organization and Source */}
|
||||
<div className="flex items-center text-xs">
|
||||
<OrgInfo
|
||||
packageNameClassName="w-auto"
|
||||
orgName={author}
|
||||
packageName={name}
|
||||
/>
|
||||
<div className="ml-1 mr-0.5 text-text-quaternary">·</div>
|
||||
|
||||
{/* Source Icon */}
|
||||
{source === PluginSource.marketplace && (
|
||||
<Tooltip popupContent={t('plugin.detailPanel.categoryTip.marketplace')}>
|
||||
<div>
|
||||
<BoxSparkleFill className="h-3.5 w-3.5 text-text-tertiary hover:text-text-accent" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
{source === PluginSource.github && (
|
||||
<Tooltip popupContent={t('plugin.detailPanel.categoryTip.github')}>
|
||||
<div>
|
||||
<Github className="h-3.5 w-3.5 text-text-secondary hover:text-text-primary" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
{source === PluginSource.local && (
|
||||
<Tooltip popupContent={t('plugin.detailPanel.categoryTip.local')}>
|
||||
<div>
|
||||
<RiHardDrive3Line className="h-3.5 w-3.5 text-text-tertiary" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
{source === PluginSource.debugging && (
|
||||
<Tooltip popupContent={t('plugin.detailPanel.categoryTip.debugging')}>
|
||||
<div>
|
||||
<RiBugLine className="h-3.5 w-3.5 text-text-tertiary hover:text-text-warning" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default PluginInfo
|
||||
@ -1,18 +1,17 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiBookReadLine, RiCloseLine } from '@remixicon/react'
|
||||
import cn from '@/utils/classnames'
|
||||
import Drawer from '@/app/components/base/drawer'
|
||||
import { Markdown } from '@/app/components/base/markdown'
|
||||
import { usePluginReadme } from '@/service/use-plugins'
|
||||
// import type { PluginDetail } from '@/app/components/plugins/types'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import PluginTitleInfo from '@/app/components/plugins/plugin-title-info'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Drawer from '@/app/components/base/drawer'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import { Markdown } from '@/app/components/base/markdown'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import { usePluginReadme } from '@/service/use-plugins'
|
||||
import cn from '@/utils/classnames'
|
||||
import { RiBookReadLine, RiCloseLine } from '@remixicon/react'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import DetailHeader from '../plugin-detail-panel/detail-header'
|
||||
import { ReadmeShowType, useReadmePanelStore } from './store'
|
||||
|
||||
const ReadmePanel: FC = () => {
|
||||
@ -47,8 +46,7 @@ const ReadmePanel: FC = () => {
|
||||
<RiCloseLine className='h-4 w-4' />
|
||||
</ActionButton>
|
||||
</div>
|
||||
|
||||
<PluginTitleInfo detail={detail} size="large" />
|
||||
<DetailHeader detail={detail} isReadmeView={true} />
|
||||
</div>
|
||||
|
||||
<div className="flex-1 overflow-y-auto px-4 py-3">
|
||||
@ -64,7 +62,7 @@ const ReadmePanel: FC = () => {
|
||||
if (error) {
|
||||
return (
|
||||
<div className="py-8 text-center text-text-tertiary">
|
||||
<p>{t('plugin.readmeInfo.noReadmeAvailable')}</p>
|
||||
<p>{t('plugin.readmeInfo.failedToFetch')}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -73,7 +71,6 @@ const ReadmePanel: FC = () => {
|
||||
return (
|
||||
<Markdown
|
||||
content={readmeData.readme}
|
||||
className="prose-sm prose max-w-none"
|
||||
pluginInfo={{ plugin_unique_identifier: pluginUniqueIdentifier, plugin_id: detail.plugin_id }}
|
||||
/>
|
||||
)
|
||||
|
||||
@ -313,6 +313,7 @@ const translation = {
|
||||
title: 'README',
|
||||
needHelpCheckReadme: 'Need help? Check the README.',
|
||||
noReadmeAvailable: 'No README available',
|
||||
failedToFetch: 'Failed to fetch README',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -313,6 +313,7 @@ const translation = {
|
||||
title: 'README',
|
||||
needHelpCheckReadme: '需要帮助?查看 README。',
|
||||
noReadmeAvailable: 'README 文档不可用',
|
||||
failedToFetch: '获取 README 文档失败',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -693,15 +693,17 @@ export const useFetchDynamicOptions = (plugin_id: string, provider: string, acti
|
||||
export const usePluginReadme = ({ plugin_unique_identifier, language }: { plugin_unique_identifier: string, language?: string }) => {
|
||||
return useQuery({
|
||||
queryKey: ['pluginReadme', plugin_unique_identifier, language],
|
||||
queryFn: () => get<{ readme: string }>('/workspaces/current/plugin/readme', { params: { plugin_unique_identifier, language } }),
|
||||
queryFn: () => get<{ readme: string }>('/workspaces/current/plugin/readme', { params: { plugin_unique_identifier, language } }, { silent: true }),
|
||||
enabled: !!plugin_unique_identifier,
|
||||
retry: 0,
|
||||
})
|
||||
}
|
||||
|
||||
export const usePluginReadmeAsset = ({ file_name, plugin_unique_identifier }: { file_name?: string, plugin_unique_identifier?: string }) => {
|
||||
const normalizedFileName = file_name?.replace(/(^\.\/_assets\/|^_assets\/)/, '')
|
||||
return useQuery({
|
||||
queryKey: ['pluginReadmeAsset', plugin_unique_identifier, file_name],
|
||||
queryFn: () => get<Blob>('/workspaces/current/plugin/asset', { params: { plugin_unique_identifier, file_name } }, { silent: true }),
|
||||
queryFn: () => get<Blob>('/workspaces/current/plugin/asset', { params: { plugin_unique_identifier, file_name: normalizedFileName } }, { silent: true }),
|
||||
enabled: !!plugin_unique_identifier && !!file_name && /(^\.\/_assets|^_assets)/.test(file_name),
|
||||
})
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user