瀏覽代碼

Feat/use searchparams as state (#2554)

Co-authored-by: crazywoola <427733928@qq.com>
tags/0.5.7
Rozstone 1 年之前
父節點
當前提交
d93288f711
No account linked to committer's email address

+ 4
- 1
web/app/(commonLayout)/apps/Apps.tsx 查看文件

import { useAppContext } from '@/context/app-context' import { useAppContext } from '@/context/app-context'
import { NEED_REFRESH_APP_LIST_KEY } from '@/config' import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
import { CheckModal } from '@/hooks/use-pay' import { CheckModal } from '@/hooks/use-pay'
import { useTabSearchParams } from '@/hooks/use-tab-searchparams'
import TabSlider from '@/app/components/base/tab-slider' import TabSlider from '@/app/components/base/tab-slider'
import { SearchLg } from '@/app/components/base/icons/src/vender/line/general' import { SearchLg } from '@/app/components/base/icons/src/vender/line/general'
import { XCircle } from '@/app/components/base/icons/src/vender/solid/general' import { XCircle } from '@/app/components/base/icons/src/vender/solid/general'
const Apps = () => { const Apps = () => {
const { t } = useTranslation() const { t } = useTranslation()
const { isCurrentWorkspaceManager } = useAppContext() const { isCurrentWorkspaceManager } = useAppContext()
const [activeTab, setActiveTab] = useState('all')
const [activeTab, setActiveTab] = useTabSearchParams({
defaultTab: 'all',
})
const [keywords, setKeywords] = useState('') const [keywords, setKeywords] = useState('')
const [searchKeywords, setSearchKeywords] = useState('') const [searchKeywords, setSearchKeywords] = useState('')



+ 7
- 2
web/app/(commonLayout)/datasets/Container.tsx 查看文件

'use client' 'use client'


// Libraries // Libraries
import { useRef, useState } from 'react'
import { useRef } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import useSWR from 'swr' import useSWR from 'swr'


// Services // Services
import { fetchDatasetApiBaseUrl } from '@/service/datasets' import { fetchDatasetApiBaseUrl } from '@/service/datasets'


// Hooks
import { useTabSearchParams } from '@/hooks/use-tab-searchparams'

const Container = () => { const Container = () => {
const { t } = useTranslation() const { t } = useTranslation()


{ value: 'api', text: t('dataset.datasetsApi') }, { value: 'api', text: t('dataset.datasetsApi') },
] ]


const [activeTab, setActiveTab] = useState('dataset')
const [activeTab, setActiveTab] = useTabSearchParams({
defaultTab: 'dataset',
})
const containerRef = useRef<HTMLDivElement>(null) const containerRef = useRef<HTMLDivElement>(null)
const { data } = useSWR(activeTab === 'dataset' ? null : '/datasets/api-base-info', fetchDatasetApiBaseUrl) const { data } = useSWR(activeTab === 'dataset' ? null : '/datasets/api-base-info', fetchDatasetApiBaseUrl)



+ 3
- 2
web/app/components/app/annotation/header-opts/index.tsx 查看文件

const { locale } = useContext(I18n) const { locale } = useContext(I18n)
const { CSVDownloader, Type } = useCSVDownloader() const { CSVDownloader, Type } = useCSVDownloader()
const [list, setList] = useState<AnnotationItemBasic[]>([]) const [list, setList] = useState<AnnotationItemBasic[]>([])
const annotationUnavailable = list.length === 0


const listTransformer = (list: AnnotationItemBasic[]) => list.map( const listTransformer = (list: AnnotationItemBasic[]) => list.map(
(item: AnnotationItemBasic) => { (item: AnnotationItemBasic) => {
...list.map(item => [item.question, item.answer]), ...list.map(item => [item.question, item.answer]),
]} ]}
> >
<button className={s.actionItem}>
<button disabled={annotationUnavailable} className={s.actionItem}>
<span className={s.actionName}>CSV</span> <span className={s.actionName}>CSV</span>
</button> </button>
</CSVDownloader> </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> <span className={s.actionName}>JSONL</span>
</button> </button>
</Menu.Items> </Menu.Items>

+ 2
- 2
web/app/components/app/annotation/header-opts/style.module.css 查看文件

} }


.actionItem { .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); width: calc(100% - 0.5rem);
} }


left: 4px; left: 4px;
transform: translateX(-100%); 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); box-shadow: 0px 12px 16px -4px rgba(16, 24, 40, 0.08), 0px 4px 6px -2px rgba(16, 24, 40, 0.03);
}
}

+ 4
- 1
web/app/components/explore/app-list/index.tsx 查看文件

import AppCard from '@/app/components/explore/app-card' import AppCard from '@/app/components/explore/app-card'
import { fetchAppDetail, fetchAppList } from '@/service/explore' import { fetchAppDetail, fetchAppList } from '@/service/explore'
import { createApp } from '@/service/apps' import { createApp } from '@/service/apps'
import { useTabSearchParams } from '@/hooks/use-tab-searchparams'
import CreateAppModal from '@/app/components/explore/create-app-modal' import CreateAppModal from '@/app/components/explore/create-app-modal'
import type { CreateAppModalProps } from '@/app/components/explore/create-app-modal' import type { CreateAppModalProps } from '@/app/components/explore/create-app-modal'
import Loading from '@/app/components/base/loading' import Loading from '@/app/components/base/loading'
const { isCurrentWorkspaceManager } = useAppContext() const { isCurrentWorkspaceManager } = useAppContext()
const router = useRouter() const router = useRouter()
const { hasEditPermission } = useContext(ExploreContext) const { hasEditPermission } = useContext(ExploreContext)
const [currCategory, setCurrCategory] = React.useState<AppCategory | ''>('')
const [currCategory, setCurrCategory] = useTabSearchParams({
defaultTab: '',
})
const [allList, setAllList] = React.useState<App[]>([]) const [allList, setAllList] = React.useState<App[]>([])
const [isLoaded, setIsLoaded] = React.useState(false) const [isLoaded, setIsLoaded] = React.useState(false)



+ 4
- 1
web/app/components/tools/index.tsx 查看文件

import NoCustomTool from './info/no-custom-tool' import NoCustomTool from './info/no-custom-tool'
import NoSearchRes from './info/no-search-res' import NoSearchRes from './info/no-search-res'
import NoCustomToolPlaceholder from './no-custom-tool-placeholder' import NoCustomToolPlaceholder from './no-custom-tool-placeholder'
import { useTabSearchParams } from '@/hooks/use-tab-searchparams'
import TabSlider from '@/app/components/base/tab-slider' import TabSlider from '@/app/components/base/tab-slider'
import { createCustomCollection, fetchCollectionList as doFetchCollectionList, fetchBuiltInToolList, fetchCustomToolList } from '@/service/tools' import { createCustomCollection, fetchCollectionList as doFetchCollectionList, fetchBuiltInToolList, fetchCustomToolList } from '@/service/tools'
import type { AgentTool } from '@/types/app' import type { AgentTool } from '@/types/app'
})() })()


const [query, setQuery] = useState('') const [query, setQuery] = useState('')
const [collectionType, setCollectionType] = useState<CollectionType>(collectionTypeOptions[0].value)
const [collectionType, setCollectionType] = useTabSearchParams({
defaultTab: collectionTypeOptions[0].value,
})


const showCollectionList = (() => { const showCollectionList = (() => {
let typeFilteredList: Collection[] = [] let typeFilteredList: Collection[] = []

+ 34
- 0
web/hooks/use-tab-searchparams.ts 查看文件

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…
取消
儲存