mirror of
https://github.com/langgenius/dify.git
synced 2026-05-06 02:18:08 +08:00
fix: use query for main app
This commit is contained in:
@ -7,6 +7,8 @@ import { useCallback, useMemo } from 'react'
|
||||
import { CATEGORY_ALL, DEFAULT_PLUGIN_SORT, DEFAULT_TEMPLATE_SORT, getValidatedPluginCategory, getValidatedTemplateCategory, PLUGIN_CATEGORY_WITH_COLLECTIONS } from './constants'
|
||||
import { CREATION_TYPE, marketplaceSearchParamsParsers } from './search-params'
|
||||
|
||||
export const isMarketplacePlatformAtom = atom<boolean>(false)
|
||||
|
||||
const marketplacePluginSortAtom = atom<PluginsSort>(DEFAULT_PLUGIN_SORT)
|
||||
export function useMarketplacePluginSort() {
|
||||
return useAtom(marketplacePluginSortAtom)
|
||||
@ -33,33 +35,59 @@ export function useSearchText() {
|
||||
return useQueryState('q', marketplaceSearchParamsParsers.q)
|
||||
}
|
||||
export function useActivePluginCategory() {
|
||||
const isAtMarketplace = useAtomValue(isMarketplacePlatformAtom)
|
||||
|
||||
const [category, setCategory] = useQueryState('category', marketplaceSearchParamsParsers.category)
|
||||
|
||||
const router = useRouter()
|
||||
const pathname = usePathname()
|
||||
const segments = pathname.split('/').filter(Boolean)
|
||||
const categoryFromPath = segments[1] || CATEGORY_ALL
|
||||
const validatedCategory = getValidatedPluginCategory(categoryFromPath)
|
||||
const handleChange = (newCategory: string) => {
|
||||
router.push(`/plugins/${newCategory}`)
|
||||
const handleChange = useCallback(
|
||||
(newCategory: string) => {
|
||||
router.push(`/plugins/${newCategory}`)
|
||||
},
|
||||
[router],
|
||||
)
|
||||
|
||||
if (isAtMarketplace) {
|
||||
return [validatedCategory, handleChange] as const
|
||||
}
|
||||
return [validatedCategory, handleChange] as const
|
||||
return [getValidatedPluginCategory(category), setCategory] as const
|
||||
}
|
||||
|
||||
export function useActiveTemplateCategory() {
|
||||
const isAtMarketplace = useAtomValue(isMarketplacePlatformAtom)
|
||||
|
||||
const [category, setCategory] = useQueryState('category', marketplaceSearchParamsParsers.category)
|
||||
|
||||
const router = useRouter()
|
||||
const pathname = usePathname()
|
||||
const segments = pathname.split('/').filter(Boolean)
|
||||
const categoryFromPath = segments[1] || CATEGORY_ALL
|
||||
const validatedCategory = getValidatedTemplateCategory(categoryFromPath)
|
||||
const handleChange = (newCategory: string) => {
|
||||
router.push(`/${CREATION_TYPE.templates}/${newCategory}`)
|
||||
const handleChange = useCallback(
|
||||
(newCategory: string) => {
|
||||
router.push(`/${CREATION_TYPE.templates}/${newCategory}`)
|
||||
},
|
||||
[router],
|
||||
)
|
||||
|
||||
if (isAtMarketplace) {
|
||||
return [validatedCategory, handleChange] as const
|
||||
}
|
||||
return [validatedCategory, handleChange] as const
|
||||
return [getValidatedTemplateCategory(category), setCategory] as const
|
||||
}
|
||||
export function useFilterPluginTags() {
|
||||
return useQueryState('tags', marketplaceSearchParamsParsers.tags)
|
||||
}
|
||||
|
||||
export function useSearchTab() {
|
||||
const isAtMarketplace = useAtomValue(isMarketplacePlatformAtom)
|
||||
|
||||
const state = useQueryState('searchTab', marketplaceSearchParamsParsers.searchTab)
|
||||
|
||||
const router = useRouter()
|
||||
// /search/[searchTab]
|
||||
const { searchTab } = useParams()
|
||||
@ -71,16 +99,27 @@ export function useSearchTab() {
|
||||
},
|
||||
[router],
|
||||
)
|
||||
return [searchTab, handleChange] as const
|
||||
|
||||
if (isAtMarketplace) {
|
||||
return [searchTab, handleChange] as const
|
||||
}
|
||||
return state
|
||||
}
|
||||
|
||||
export function useCreationType() {
|
||||
const isAtMarketplace = useAtomValue(isMarketplacePlatformAtom)
|
||||
|
||||
const [creationType] = useQueryState('creationType', marketplaceSearchParamsParsers.creationType)
|
||||
|
||||
const pathname = usePathname()
|
||||
const segments = pathname.split('/').filter(Boolean)
|
||||
|
||||
if (segments[0] === CREATION_TYPE.templates || segments[0] === 'template')
|
||||
return CREATION_TYPE.templates
|
||||
return CREATION_TYPE.plugins
|
||||
if (isAtMarketplace) {
|
||||
if (segments[0] === CREATION_TYPE.templates || segments[0] === 'template')
|
||||
return CREATION_TYPE.templates
|
||||
return CREATION_TYPE.plugins
|
||||
}
|
||||
return creationType
|
||||
}
|
||||
|
||||
// Search-page-specific filter hooks (separate from list-page category/tags)
|
||||
|
||||
17
web/app/components/plugins/marketplace/hydration-client.tsx
Normal file
17
web/app/components/plugins/marketplace/hydration-client.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
'use client'
|
||||
|
||||
import { useHydrateAtoms } from 'jotai/utils'
|
||||
import { isMarketplacePlatformAtom } from './atoms'
|
||||
|
||||
export function HydrateClient({
|
||||
isMarketplacePlatform = false,
|
||||
children,
|
||||
}: {
|
||||
isMarketplacePlatform?: boolean
|
||||
children?: React.ReactNode
|
||||
}) {
|
||||
useHydrateAtoms([
|
||||
[isMarketplacePlatformAtom, isMarketplacePlatform],
|
||||
])
|
||||
return <>{children}</>
|
||||
}
|
||||
@ -2,6 +2,7 @@ import type { SearchParams } from 'nuqs'
|
||||
import type { Awaitable } from './hydration-server'
|
||||
import { TanstackQueryInitializer } from '@/context/query-client'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { HydrateClient } from './hydration-client'
|
||||
import { HydrateQueryClient } from './hydration-server'
|
||||
import MarketplaceContent from './marketplace-content'
|
||||
import MarketplaceHeader from './marketplace-header'
|
||||
@ -20,7 +21,7 @@ type MarketplaceProps = {
|
||||
marketplaceNav?: React.ReactNode
|
||||
}
|
||||
|
||||
const Marketplace = async ({
|
||||
const Marketplace = ({
|
||||
showInstallButton = true,
|
||||
params,
|
||||
searchParams,
|
||||
@ -30,10 +31,12 @@ const Marketplace = async ({
|
||||
return (
|
||||
<TanstackQueryInitializer>
|
||||
<HydrateQueryClient searchParams={searchParams} params={params}>
|
||||
<MarketplaceHeader descriptionClassName={cn('mx-12 mt-1', isMarketplacePlatform && 'top-0 mx-0 mt-0 rounded-none')} marketplaceNav={marketplaceNav} />
|
||||
<MarketplaceContent
|
||||
showInstallButton={showInstallButton}
|
||||
/>
|
||||
<HydrateClient isMarketplacePlatform={isMarketplacePlatform}>
|
||||
<MarketplaceHeader descriptionClassName={cn('mx-12 mt-1', isMarketplacePlatform && 'top-0 mx-0 mt-0 rounded-none')} marketplaceNav={marketplaceNav} />
|
||||
<MarketplaceContent
|
||||
showInstallButton={showInstallButton}
|
||||
/>
|
||||
</HydrateClient>
|
||||
</HydrateQueryClient>
|
||||
</TanstackQueryInitializer>
|
||||
)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { parseAsArrayOf, parseAsString } from 'nuqs/server'
|
||||
import { parseAsArrayOf, parseAsString, parseAsStringEnum } from 'nuqs/server'
|
||||
|
||||
export const CREATION_TYPE = {
|
||||
plugins: 'plugins',
|
||||
@ -17,4 +17,9 @@ export const marketplaceSearchParamsParsers = {
|
||||
searchLanguages: parseAsArrayOf(parseAsString).withDefault([]).withOptions({ history: 'replace' }),
|
||||
searchType: parseAsString.withDefault('all').withOptions({ history: 'replace' }),
|
||||
searchTags: parseAsArrayOf(parseAsString).withDefault([]).withOptions({ history: 'replace' }),
|
||||
|
||||
// In marketplace, we use path instead of query
|
||||
category: parseAsString.withDefault('all').withOptions({ history: 'replace', clearOnDefault: false }),
|
||||
creationType: parseAsStringEnum<CreationType>([CREATION_TYPE.plugins, CREATION_TYPE.templates]).withDefault(CREATION_TYPE.plugins).withOptions({ history: 'replace' }),
|
||||
searchTab: parseAsStringEnum<SearchTab>(['all', 'plugins', 'templates', 'creators']).withDefault('').withOptions({ history: 'replace' }),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user