mirror of
https://github.com/langgenius/dify.git
synced 2026-05-10 05:56:31 +08:00
feat: add utility functions for building search parameters and marketplace URLs
This commit is contained in:
parent
7934b0222d
commit
61b6b838de
@ -13,7 +13,7 @@ import { cn } from '@/utils/classnames'
|
||||
import { getIconFromMarketPlace } from '@/utils/get-icon'
|
||||
import { formatUsedCount } from '@/utils/template'
|
||||
import { getMarketplaceUrl } from '@/utils/var'
|
||||
import { getTemplateIconUrl } from '../utils'
|
||||
import { buildSearchParamsString, getTemplateIconUrl } from '../utils'
|
||||
|
||||
type TemplateCardProps = {
|
||||
template: Template
|
||||
@ -45,7 +45,7 @@ const TemplateCardComponent = ({
|
||||
}
|
||||
return includeSource
|
||||
? getMarketplaceUrl(`/template/${publisher_handle}/${template_name}`, queryParams)
|
||||
: `${MARKETPLACE_URL_PREFIX}/template/${publisher_handle}/${template_name}?${new URLSearchParams(queryParams).toString()}`
|
||||
: `${MARKETPLACE_URL_PREFIX}/template/${publisher_handle}/${template_name}?${buildSearchParamsString(queryParams)}`
|
||||
}, [publisher_handle, template_name, theme, locale, id, includeSource])
|
||||
|
||||
const visibleDepsPlugins = deps_plugins?.slice(0, MAX_VISIBLE_DEPS_PLUGINS) || []
|
||||
|
||||
@ -9,9 +9,8 @@ import { useCategories } from '@/app/components/plugins/hooks'
|
||||
import { useRenderI18nObject } from '@/hooks/use-i18n'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { formatUsedCount } from '@/utils/template'
|
||||
import { getMarketplaceUrl } from '@/utils/var'
|
||||
import { MARKETPLACE_TYPE_ICON_COMPONENTS } from '../../plugin-type-icons'
|
||||
import { getCreatorAvatarUrl, getPluginDetailLinkInMarketplace, getTemplateIconUrl } from '../../utils'
|
||||
import { buildMarketplaceHref, getCreatorAvatarUrl, getPluginDetailLinkInMarketplace, getTemplateIconUrl } from '../../utils'
|
||||
|
||||
const DROPDOWN_PANEL = 'w-[472px] max-h-[710px] overflow-y-auto rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-xl backdrop-blur-sm'
|
||||
const ICON_BOX_BASE = 'flex shrink-0 items-center justify-center overflow-hidden border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge'
|
||||
@ -79,29 +78,6 @@ const ItemMeta = ({ items }: { items: (React.ReactNode | string)[] }) => (
|
||||
</div>
|
||||
)
|
||||
|
||||
const getSearchParamsString = (params?: Record<string, string | undefined>) => {
|
||||
const searchParams = new URLSearchParams()
|
||||
if (params) {
|
||||
Object.keys(params).forEach((key) => {
|
||||
const value = params[key]
|
||||
if (value !== undefined && value !== null)
|
||||
searchParams.append(key, value)
|
||||
})
|
||||
}
|
||||
return searchParams.toString()
|
||||
}
|
||||
|
||||
const getDropdownMarketplaceUrl = (
|
||||
path: string,
|
||||
params: Record<string, string | undefined> | undefined,
|
||||
includeSource: boolean,
|
||||
) => {
|
||||
if (includeSource)
|
||||
return getMarketplaceUrl(path, params)
|
||||
const query = getSearchParamsString(params)
|
||||
return query ? `${path}?${query}` : path
|
||||
}
|
||||
|
||||
type SearchDropdownProps = {
|
||||
query: string
|
||||
plugins: Plugin[]
|
||||
@ -226,7 +202,7 @@ function TemplatesSection({ templates, includeSource, t }: {
|
||||
return (
|
||||
<DropdownItem
|
||||
key={template.id}
|
||||
href={getDropdownMarketplaceUrl(
|
||||
href={buildMarketplaceHref(
|
||||
`/template/${template.publisher_handle}/${template.template_name}`,
|
||||
{ templateId: template.id },
|
||||
includeSource,
|
||||
@ -326,7 +302,7 @@ function CreatorsSection({ creators, includeSource, t }: {
|
||||
<a
|
||||
key={creator.unique_handle}
|
||||
className="flex items-center gap-2 rounded-lg px-3 py-2 hover:bg-state-base-hover"
|
||||
href={getDropdownMarketplaceUrl(`/creators/${creator.unique_handle}`, undefined, includeSource)}
|
||||
href={buildMarketplaceHref(`/creators/${creator.unique_handle}`, undefined, includeSource)}
|
||||
>
|
||||
<div className="flex h-8 w-8 shrink-0 items-center justify-center overflow-hidden rounded-full border-[0.5px] border-divider-regular">
|
||||
<img
|
||||
|
||||
41
web/app/components/plugins/marketplace/utils.spec.ts
Normal file
41
web/app/components/plugins/marketplace/utils.spec.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { buildMarketplaceHref, buildSearchParamsString } from './utils'
|
||||
|
||||
describe('buildSearchParamsString', () => {
|
||||
it('filters undefined and null values', () => {
|
||||
const query = buildSearchParamsString({
|
||||
theme: undefined,
|
||||
language: 'en-US',
|
||||
templateId: 'tpl-1',
|
||||
empty: null as unknown as string,
|
||||
})
|
||||
expect(query).toBe('language=en-US&templateId=tpl-1')
|
||||
expect(query).not.toContain('theme=undefined')
|
||||
expect(query).not.toContain('empty=')
|
||||
})
|
||||
})
|
||||
|
||||
describe('buildMarketplaceHref', () => {
|
||||
it('returns relative path with filtered query when includeSource is false', () => {
|
||||
const href = buildMarketplaceHref('/template/foo/bar', {
|
||||
theme: undefined,
|
||||
language: 'en-US',
|
||||
templateId: 'tpl-1',
|
||||
}, false)
|
||||
|
||||
expect(href).toBe('/template/foo/bar?language=en-US&templateId=tpl-1')
|
||||
expect(href).not.toContain('theme=undefined')
|
||||
})
|
||||
|
||||
it('delegates to marketplace source URL when includeSource is true', () => {
|
||||
const href = buildMarketplaceHref('/template/foo/bar', {
|
||||
language: 'en-US',
|
||||
templateId: 'tpl-1',
|
||||
}, true)
|
||||
|
||||
expect(href).toContain('/template/foo/bar?')
|
||||
expect(href).toContain('source=')
|
||||
expect(href).toContain('language=en-US')
|
||||
expect(href).toContain('templateId=tpl-1')
|
||||
})
|
||||
})
|
||||
@ -102,6 +102,28 @@ export const getPluginDetailLinkInMarketplace = (plugin: Plugin) => {
|
||||
return `/plugin/${plugin.org}/${plugin.name}`
|
||||
}
|
||||
|
||||
export const buildSearchParamsString = (params?: Record<string, string | undefined>) => {
|
||||
const searchParams = new URLSearchParams()
|
||||
if (params) {
|
||||
for (const [key, value] of Object.entries(params)) {
|
||||
if (value !== undefined && value !== null)
|
||||
searchParams.append(key, value)
|
||||
}
|
||||
}
|
||||
return searchParams.toString()
|
||||
}
|
||||
|
||||
export const buildMarketplaceHref = (
|
||||
path: string,
|
||||
params: Record<string, string | undefined> | undefined,
|
||||
includeSource: boolean,
|
||||
) => {
|
||||
if (includeSource)
|
||||
return getMarketplaceUrl(path, params)
|
||||
const query = buildSearchParamsString(params)
|
||||
return query ? `${path}?${query}` : path
|
||||
}
|
||||
|
||||
export const getMarketplacePluginsByCollectionId = async (
|
||||
collectionId: string,
|
||||
query?: CollectionsAndPluginsSearchParams,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user