mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-14 03:45:55 +08:00
Feat/use searchparams as state (#2554)
Co-authored-by: crazywoola <427733928@qq.com>
This commit is contained in:
parent
ca69af7b97
commit
d93288f711
@ -11,6 +11,7 @@ import { fetchAppList } from '@/service/apps'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
|
||||
import { CheckModal } from '@/hooks/use-pay'
|
||||
import { useTabSearchParams } from '@/hooks/use-tab-searchparams'
|
||||
import TabSlider from '@/app/components/base/tab-slider'
|
||||
import { SearchLg } from '@/app/components/base/icons/src/vender/line/general'
|
||||
import { XCircle } from '@/app/components/base/icons/src/vender/solid/general'
|
||||
@ -35,7 +36,9 @@ const getKey = (
|
||||
const Apps = () => {
|
||||
const { t } = useTranslation()
|
||||
const { isCurrentWorkspaceManager } = useAppContext()
|
||||
const [activeTab, setActiveTab] = useState('all')
|
||||
const [activeTab, setActiveTab] = useTabSearchParams({
|
||||
defaultTab: 'all',
|
||||
})
|
||||
const [keywords, setKeywords] = useState('')
|
||||
const [searchKeywords, setSearchKeywords] = useState('')
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
// Libraries
|
||||
import { useRef, useState } from 'react'
|
||||
import { useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useSWR from 'swr'
|
||||
|
||||
@ -15,6 +15,9 @@ import TabSlider from '@/app/components/base/tab-slider'
|
||||
// Services
|
||||
import { fetchDatasetApiBaseUrl } from '@/service/datasets'
|
||||
|
||||
// Hooks
|
||||
import { useTabSearchParams } from '@/hooks/use-tab-searchparams'
|
||||
|
||||
const Container = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
@ -23,7 +26,9 @@ const Container = () => {
|
||||
{ value: 'api', text: t('dataset.datasetsApi') },
|
||||
]
|
||||
|
||||
const [activeTab, setActiveTab] = useState('dataset')
|
||||
const [activeTab, setActiveTab] = useTabSearchParams({
|
||||
defaultTab: 'dataset',
|
||||
})
|
||||
const containerRef = useRef<HTMLDivElement>(null)
|
||||
const { data } = useSWR(activeTab === 'dataset' ? null : '/datasets/api-base-info', fetchDatasetApiBaseUrl)
|
||||
|
||||
|
@ -42,6 +42,7 @@ const HeaderOptions: FC<Props> = ({
|
||||
const { locale } = useContext(I18n)
|
||||
const { CSVDownloader, Type } = useCSVDownloader()
|
||||
const [list, setList] = useState<AnnotationItemBasic[]>([])
|
||||
const annotationUnavailable = list.length === 0
|
||||
|
||||
const listTransformer = (list: AnnotationItemBasic[]) => list.map(
|
||||
(item: AnnotationItemBasic) => {
|
||||
@ -116,11 +117,11 @@ const HeaderOptions: FC<Props> = ({
|
||||
...list.map(item => [item.question, item.answer]),
|
||||
]}
|
||||
>
|
||||
<button className={s.actionItem}>
|
||||
<button disabled={annotationUnavailable} className={s.actionItem}>
|
||||
<span className={s.actionName}>CSV</span>
|
||||
</button>
|
||||
</CSVDownloader>
|
||||
<button className={cn(s.actionItem, '!border-0')} onClick={JSONLOutput}>
|
||||
<button disabled={annotationUnavailable} className={cn(s.actionItem, '!border-0')} onClick={JSONLOutput}>
|
||||
<span className={s.actionName}>JSONL</span>
|
||||
</button>
|
||||
</Menu.Items>
|
||||
|
@ -19,7 +19,7 @@
|
||||
}
|
||||
|
||||
.actionItem {
|
||||
@apply h-9 py-2 px-3 mx-1 flex items-center space-x-2 hover:bg-gray-100 rounded-lg cursor-pointer;
|
||||
@apply h-9 py-2 px-3 mx-1 flex items-center space-x-2 hover:bg-gray-100 rounded-lg cursor-pointer disabled:opacity-50;
|
||||
width: calc(100% - 0.5rem);
|
||||
}
|
||||
|
||||
@ -35,4 +35,4 @@
|
||||
left: 4px;
|
||||
transform: translateX(-100%);
|
||||
box-shadow: 0px 12px 16px -4px rgba(16, 24, 40, 0.08), 0px 4px 6px -2px rgba(16, 24, 40, 0.03);
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import Category from '@/app/components/explore/category'
|
||||
import AppCard from '@/app/components/explore/app-card'
|
||||
import { fetchAppDetail, fetchAppList } from '@/service/explore'
|
||||
import { createApp } from '@/service/apps'
|
||||
import { useTabSearchParams } from '@/hooks/use-tab-searchparams'
|
||||
import CreateAppModal from '@/app/components/explore/create-app-modal'
|
||||
import type { CreateAppModalProps } from '@/app/components/explore/create-app-modal'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
@ -24,7 +25,9 @@ const Apps: FC = () => {
|
||||
const { isCurrentWorkspaceManager } = useAppContext()
|
||||
const router = useRouter()
|
||||
const { hasEditPermission } = useContext(ExploreContext)
|
||||
const [currCategory, setCurrCategory] = React.useState<AppCategory | ''>('')
|
||||
const [currCategory, setCurrCategory] = useTabSearchParams({
|
||||
defaultTab: '',
|
||||
})
|
||||
const [allList, setAllList] = React.useState<App[]>([])
|
||||
const [isLoaded, setIsLoaded] = React.useState(false)
|
||||
|
||||
|
@ -16,6 +16,7 @@ import EditCustomToolModal from './edit-custom-collection-modal'
|
||||
import NoCustomTool from './info/no-custom-tool'
|
||||
import NoSearchRes from './info/no-search-res'
|
||||
import NoCustomToolPlaceholder from './no-custom-tool-placeholder'
|
||||
import { useTabSearchParams } from '@/hooks/use-tab-searchparams'
|
||||
import TabSlider from '@/app/components/base/tab-slider'
|
||||
import { createCustomCollection, fetchCollectionList as doFetchCollectionList, fetchBuiltInToolList, fetchCustomToolList } from '@/service/tools'
|
||||
import type { AgentTool } from '@/types/app'
|
||||
@ -68,7 +69,9 @@ const Tools: FC<Props> = ({
|
||||
})()
|
||||
|
||||
const [query, setQuery] = useState('')
|
||||
const [collectionType, setCollectionType] = useState<CollectionType>(collectionTypeOptions[0].value)
|
||||
const [collectionType, setCollectionType] = useTabSearchParams({
|
||||
defaultTab: collectionTypeOptions[0].value,
|
||||
})
|
||||
|
||||
const showCollectionList = (() => {
|
||||
let typeFilteredList: Collection[] = []
|
||||
|
34
web/hooks/use-tab-searchparams.ts
Normal file
34
web/hooks/use-tab-searchparams.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
|
||||
|
||||
type UseTabSearchParamsOptions = {
|
||||
defaultTab: string
|
||||
routingBehavior?: 'push' | 'replace'
|
||||
searchParamName?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom hook to manage tab state via URL search parameters in a Next.js application.
|
||||
* This hook allows for syncing the active tab with the browser's URL, enabling bookmarking and sharing of URLs with a specific tab activated.
|
||||
*
|
||||
* @param {UseTabSearchParamsOptions} options Configuration options for the hook:
|
||||
* - `defaultTab`: The tab to default to when no tab is specified in the URL.
|
||||
* - `routingBehavior`: Optional. Determines how changes to the active tab update the browser's history ('push' or 'replace'). Default is 'push'.
|
||||
* - `searchParamName`: Optional. The name of the search parameter that holds the tab state in the URL. Default is 'category'.
|
||||
* @returns A tuple where the first element is the active tab and the second element is a function to set the active tab.
|
||||
*/
|
||||
export const useTabSearchParams = ({
|
||||
defaultTab,
|
||||
routingBehavior = 'push',
|
||||
searchParamName = 'category',
|
||||
}: UseTabSearchParamsOptions) => {
|
||||
const router = useRouter()
|
||||
const pathName = usePathname()
|
||||
const searchParams = useSearchParams()
|
||||
const activeTab = searchParams.get(searchParamName) || defaultTab
|
||||
|
||||
const setActiveTab = (newActiveTab: string) => {
|
||||
router[routingBehavior](`${pathName}?${searchParamName}=${newActiveTab}`)
|
||||
}
|
||||
|
||||
return [activeTab, setActiveTab] as const
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user