fix: marketplace empty page

This commit is contained in:
StyleZhang 2024-11-14 14:26:02 +08:00
parent 44cc6157f1
commit 253abaf1a3
10 changed files with 71 additions and 41 deletions

View File

@ -19,20 +19,20 @@ const Description = async ({
</h1>
<h2 className='shrink-0 flex justify-center items-center text-center body-md-regular text-text-tertiary'>
{t('marketplace.discover')}
<span className="relative ml-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected">
{t('category.models')}
<span className="relative ml-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected z-[1]">
<span className='relative z-[2]'>{t('category.models')}</span>
</span>
,
<span className="relative ml-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected">
{t('category.tools')}
<span className="relative ml-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected z-[1]">
<span className='relative z-[2]'>{t('category.tools')}</span>
</span>
,
<span className="relative ml-1 mr-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected">
{t('category.extensions')}
<span className="relative ml-1 mr-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected z-[1]">
<span className='relative z-[2]'>{t('category.extensions')}</span>
</span>
{t('marketplace.and')}
<span className="relative ml-1 mr-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected">
{t('category.bundles')}
<span className="relative ml-1 mr-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected z-[1]">
<span className='relative z-[2]'>{t('category.bundles')}</span>
</span>
{t('marketplace.inDifyMarketplace')}
</h2>

View File

@ -1,25 +1,31 @@
'use client'
import { useTranslation } from 'react-i18next'
import { Group } from '@/app/components/base/icons/src/vender/other'
import Line from './line'
import cn from '@/utils/classnames'
const Empty = () => {
const { t } = useTranslation()
return (
<div
className='grow relative h-0 grid grid-cols-4 grid-rows-4 gap-3 p-2 overflow-hidden'
className='grow relative h-0 flex flex-wrap p-2 overflow-hidden'
>
{
Array.from({ length: 16 }).map((_, index) => (
<div
key={index}
className='h-[144px] rounded-xl bg-background-section-burn'
className={cn(
'mr-3 mb-3 h-[144px] w-[calc((100%-36px)/4)] rounded-xl bg-background-section-burn',
index % 4 === 3 && 'mr-0',
index > 11 && 'mb-0',
)}
>
</div>
))
}
<div
className='absolute inset-0 z-[1]'
style={{
backgroundImage: 'linear-gradient(180deg, rgba(255,255,255,0.01), #FCFCFD)',
}}
className='absolute inset-0 bg-marketplace-plugin-empty z-[1]'
></div>
<div className='absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-[2] flex flex-col items-center'>
<div className='relative flex items-center justify-center mb-3 w-14 h-14 rounded-xl border border-divider-subtle bg-components-card-bg shadow-lg'>
@ -30,7 +36,7 @@ const Empty = () => {
<Line className='absolute top-full left-1/2 -translate-x-1/2 -translate-y-1/2 rotate-90' />
</div>
<div className='text-center system-md-regular text-text-tertiary'>
No plugin found
{t('plugin.marketplace.noPluginFound')}
</div>
</div>
</div>

View File

@ -1,4 +1,5 @@
'use client'
import { useTranslation } from 'react-i18next'
import type { Plugin } from '../../types'
import type { MarketplaceCollection } from '../types'
import { useMarketplaceContext } from '../context'
@ -18,6 +19,7 @@ const ListWrapper = ({
showInstallButton,
locale,
}: ListWrapperProps) => {
const { t } = useTranslation()
const plugins = useMarketplaceContext(v => v.plugins)
const marketplaceCollectionsFromClient = useMarketplaceContext(v => v.marketplaceCollectionsFromClient)
const marketplaceCollectionPluginsMapFromClient = useMarketplaceContext(v => v.marketplaceCollectionPluginsMapFromClient)
@ -28,7 +30,7 @@ const ListWrapper = ({
{
plugins && (
<div className='flex items-center mb-4 pt-3'>
<div className='title-xl-semi-bold text-text-primary'>{plugins.length} results</div>
<div className='title-xl-semi-bold text-text-primary'>{t('plugin.marketplace.pluginsResult', { num: plugins.length })}</div>
<div className='mx-3 w-[1px] h-3.5 bg-divider-regular'></div>
<SortDropdown />
</div>

View File

@ -4,6 +4,7 @@ import {
RiArrowDownSLine,
RiCheckLine,
} from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import { useMarketplaceContext } from '../context'
import {
PortalToFollowElem,
@ -11,30 +12,30 @@ import {
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
const options = [
{
value: 'install_count',
order: 'DESC',
text: 'Most Popular',
},
{
value: 'version_updated_at',
order: 'DESC',
text: 'Recently Updated',
},
{
value: 'created_at',
order: 'DESC',
text: 'Newly Released',
},
{
value: 'created_at',
order: 'ASC',
text: 'First Released',
},
]
const SortDropdown = () => {
const { t } = useTranslation()
const options = [
{
value: 'install_count',
order: 'DESC',
text: t('plugin.marketplace.sortOption.mostPopular'),
},
{
value: 'version_updated_at',
order: 'DESC',
text: t('plugin.marketplace.sortOption.recentlyUpdated'),
},
{
value: 'created_at',
order: 'DESC',
text: t('plugin.marketplace.sortOption.newlyReleased'),
},
{
value: 'created_at',
order: 'ASC',
text: t('plugin.marketplace.sortOption.firstReleased'),
},
]
const sort = useMarketplaceContext(v => v.sort)
const handleSortChange = useMarketplaceContext(v => v.handleSortChange)
const [open, setOpen] = useState(false)
@ -53,7 +54,7 @@ const SortDropdown = () => {
<PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}>
<div className='flex items-center px-2 pr-3 h-8 rounded-lg bg-state-base-hover-alt cursor-pointer'>
<span className='mr-1 system-sm-regular'>
Sort by
{t('plugin.marketplace.sortBy')}
</span>
<span className='mr-1 system-sm-medium'>
{selectedOption.text}

View File

@ -25,7 +25,7 @@ const Marketplace = ({
} = useMarketplace(searchPluginText, filterPluginTags)
return (
<div className='shrink-0 sticky -bottom-[442px] h-[530px] overflow-y-auto px-12 py-2 pt-0 bg-background-default-subtle'>
<div className='flex flex-col shrink-0 sticky -bottom-[442px] h-[530px] overflow-y-auto px-12 py-2 pt-0 bg-background-default-subtle'>
<RiArrowUpDoubleLine
className='absolute top-2 left-1/2 -translate-x-1/2 w-4 h-4 text-text-quaternary cursor-pointer'
onClick={() => onMarketplaceScroll()}

View File

@ -128,6 +128,15 @@ const translation = {
and: 'and',
inDifyMarketplace: 'in Dify Marketplace',
moreFrom: 'More from Marketplace',
noPluginFound: 'No plugin found',
pluginsResult: '{{num}} results',
sortBy: 'Sort by',
sortOption: {
mostPopular: 'Most Popular',
recentlyUpdated: 'Recently Updated',
newlyReleased: 'Newly Released',
firstReleased: 'First Released',
},
},
task: {
installing: 'Installing {{installingLength}}/{{totalLength}} plugins...',

View File

@ -128,6 +128,15 @@ const translation = {
and: '和',
inDifyMarketplace: '在 Dify 市场中',
moreFrom: '更多来自市场',
noPluginFound: '未找到插件',
pluginsResult: '{{num}} 个插件结果',
sortBy: '排序方式',
sortOption: {
mostPopular: '最受欢迎',
recentlyUpdated: '最近更新',
newlyReleased: '最新发布',
firstReleased: '首次发布',
},
},
task: {
installing: '{{installingLength}}/{{totalLength}} 插件安装中...',

View File

@ -88,6 +88,7 @@ const config = {
'chat-bubble-bg': 'var(--color-chat-bubble-bg)',
'workflow-process-bg': 'var(--color-workflow-process-bg)',
'marketplace-divider-bg': 'var(--color-marketplace-divider-bg)',
'marketplace-plugin-empty': 'var(--color-marketplace-plugin-empty)',
},
animation: {
'spin-slow': 'spin 2s linear infinite',

View File

@ -695,4 +695,5 @@ html[data-theme="dark"] {
--color-third-party-model-bg-default: #0B0B0E;
--color-workflow-process-bg: linear-gradient(90deg, rgba(24, 24, 27, 0.25) 0%, rgba(24, 24, 27, 0.04) 100%);
--color-marketplace-divider-bg: linear-gradient(90deg, rgba(200, 206, 218, 0.14) 0%, rgba(0, 0, 0, 0) 100%);
--color-marketplace-plugin-empty: linear-gradient(180deg, rgba(0, 0, 0, 0.00) 0%, #222225 100%);
}

View File

@ -695,4 +695,5 @@ html[data-theme="light"] {
--color-third-party-model-bg-default: #F9FAFB;
--color-workflow-process-bg: linear-gradient(90deg, rgba(200, 206, 218, 0.20) 0%, rgba(200, 206, 218, 0.04) 100%);
--color-marketplace-divider-bg: linear-gradient(90deg, rgba(16, 24, 40, 0.08) 0%, rgba(255, 255, 255, 0) 100%);
--color-marketplace-plugin-empty: linear-gradient(180deg, rgba(255, 255, 255, 0.00) 0%, #FCFCFD 100%);
}