mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-09-06 17:46:23 +00:00
fix(channels): remove effect-driven test dialog state resets
This commit is contained in:
+70
-34
@@ -16,7 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
For commercial licensing, please contact support@quantumnous.com
|
For commercial licensing, please contact support@quantumnous.com
|
||||||
*/
|
*/
|
||||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
import { type ChangeEvent, useCallback, useMemo, useState } from 'react'
|
||||||
import { useQueryClient } from '@tanstack/react-query'
|
import { useQueryClient } from '@tanstack/react-query'
|
||||||
import {
|
import {
|
||||||
type ColumnDef,
|
type ColumnDef,
|
||||||
@@ -73,7 +73,11 @@ import {
|
|||||||
formatResponseTime,
|
formatResponseTime,
|
||||||
handleTestChannel,
|
handleTestChannel,
|
||||||
} from '../../lib'
|
} from '../../lib'
|
||||||
import type { GetChannelsResponse, SearchChannelsResponse } from '../../types'
|
import type {
|
||||||
|
Channel,
|
||||||
|
GetChannelsResponse,
|
||||||
|
SearchChannelsResponse,
|
||||||
|
} from '../../types'
|
||||||
import { useChannels } from '../channels-provider'
|
import { useChannels } from '../channels-provider'
|
||||||
|
|
||||||
type ChannelTestDialogProps = {
|
type ChannelTestDialogProps = {
|
||||||
@@ -81,6 +85,10 @@ type ChannelTestDialogProps = {
|
|||||||
onOpenChange: (open: boolean) => void
|
onOpenChange: (open: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ChannelTestDialogContentProps = ChannelTestDialogProps & {
|
||||||
|
currentRow: Channel
|
||||||
|
}
|
||||||
|
|
||||||
type ModelRow = {
|
type ModelRow = {
|
||||||
model: string
|
model: string
|
||||||
}
|
}
|
||||||
@@ -257,10 +265,30 @@ export function ChannelTestDialog({
|
|||||||
open,
|
open,
|
||||||
onOpenChange,
|
onOpenChange,
|
||||||
}: ChannelTestDialogProps) {
|
}: ChannelTestDialogProps) {
|
||||||
const { t } = useTranslation()
|
|
||||||
const { currentRow } = useChannels()
|
const { currentRow } = useChannels()
|
||||||
|
|
||||||
|
if (!currentRow) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ChannelTestDialogContent
|
||||||
|
key={currentRow.id}
|
||||||
|
open={open}
|
||||||
|
onOpenChange={onOpenChange}
|
||||||
|
currentRow={currentRow}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ChannelTestDialogContent({
|
||||||
|
open,
|
||||||
|
onOpenChange,
|
||||||
|
currentRow,
|
||||||
|
}: ChannelTestDialogContentProps) {
|
||||||
|
const { t } = useTranslation()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const currentChannelId = currentRow?.id
|
const currentChannelId = currentRow.id
|
||||||
const [endpointType, setEndpointType] = useState('auto')
|
const [endpointType, setEndpointType] = useState('auto')
|
||||||
const [isStreamTest, setIsStreamTest] = useState(false)
|
const [isStreamTest, setIsStreamTest] = useState(false)
|
||||||
const [searchTerm, setSearchTerm] = useState('')
|
const [searchTerm, setSearchTerm] = useState('')
|
||||||
@@ -297,23 +325,30 @@ export function ChannelTestDialog({
|
|||||||
setPagination({ pageIndex: 0, pageSize: 10 })
|
setPagination({ pageIndex: 0, pageSize: 10 })
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (open && currentRow) {
|
|
||||||
resetState()
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [open, currentRow?.id, resetState])
|
|
||||||
|
|
||||||
const streamDisabled = STREAM_INCOMPATIBLE_ENDPOINTS.has(endpointType)
|
const streamDisabled = STREAM_INCOMPATIBLE_ENDPOINTS.has(endpointType)
|
||||||
|
const effectiveStreamTest = !streamDisabled && isStreamTest
|
||||||
|
|
||||||
useEffect(() => {
|
const handleEndpointTypeChange = useCallback((value: string | null) => {
|
||||||
if (streamDisabled) {
|
if (value === null) return
|
||||||
|
|
||||||
|
setEndpointType(value)
|
||||||
|
if (STREAM_INCOMPATIBLE_ENDPOINTS.has(value)) {
|
||||||
setIsStreamTest(false)
|
setIsStreamTest(false)
|
||||||
}
|
}
|
||||||
}, [streamDisabled])
|
}, [])
|
||||||
|
|
||||||
const modelsValue = currentRow?.models ?? ''
|
const handleSearchTermChange = useCallback(
|
||||||
const defaultTestModel = currentRow?.test_model?.trim()
|
(event: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setSearchTerm(event.target.value)
|
||||||
|
setPagination((prev) =>
|
||||||
|
prev.pageIndex === 0 ? prev : { ...prev, pageIndex: 0 }
|
||||||
|
)
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
|
const modelsValue = currentRow.models
|
||||||
|
const defaultTestModel = currentRow.test_model?.trim()
|
||||||
|
|
||||||
const models = useMemo(() => {
|
const models = useMemo(() => {
|
||||||
if (!modelsValue) return []
|
if (!modelsValue) return []
|
||||||
@@ -329,10 +364,6 @@ export function ChannelTestDialog({
|
|||||||
return models.filter((model) => model.toLowerCase().includes(keyword))
|
return models.filter((model) => model.toLowerCase().includes(keyword))
|
||||||
}, [models, searchTerm])
|
}, [models, searchTerm])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setPagination((prev) => ({ ...prev, pageIndex: 0 }))
|
|
||||||
}, [searchTerm, modelsValue])
|
|
||||||
|
|
||||||
const tableData = useMemo<ModelRow[]>(
|
const tableData = useMemo<ModelRow[]>(
|
||||||
() => filteredModels.map((model) => ({ model })),
|
() => filteredModels.map((model) => ({ model })),
|
||||||
[filteredModels]
|
[filteredModels]
|
||||||
@@ -360,7 +391,7 @@ export function ChannelTestDialog({
|
|||||||
|
|
||||||
const updateChannelTestCache = useCallback(
|
const updateChannelTestCache = useCallback(
|
||||||
(patch?: ChannelTestCachePatch) => {
|
(patch?: ChannelTestCachePatch) => {
|
||||||
if (!patch || currentChannelId === undefined) return
|
if (!patch) return
|
||||||
|
|
||||||
queryClient.setQueriesData<ChannelListCache>(
|
queryClient.setQueriesData<ChannelListCache>(
|
||||||
{ queryKey: channelsQueryKeys.lists() },
|
{ queryKey: channelsQueryKeys.lists() },
|
||||||
@@ -424,7 +455,7 @@ export function ChannelTestDialog({
|
|||||||
{
|
{
|
||||||
testModel: model,
|
testModel: model,
|
||||||
endpointType: endpointType === 'auto' ? undefined : endpointType,
|
endpointType: endpointType === 'auto' ? undefined : endpointType,
|
||||||
stream: isStreamTest || undefined,
|
stream: effectiveStreamTest || undefined,
|
||||||
silent,
|
silent,
|
||||||
},
|
},
|
||||||
(success, responseTime, error, errorCode) => {
|
(success, responseTime, error, errorCode) => {
|
||||||
@@ -462,7 +493,7 @@ export function ChannelTestDialog({
|
|||||||
[
|
[
|
||||||
currentRow,
|
currentRow,
|
||||||
endpointType,
|
endpointType,
|
||||||
isStreamTest,
|
effectiveStreamTest,
|
||||||
markModelTesting,
|
markModelTesting,
|
||||||
refreshChannelLists,
|
refreshChannelLists,
|
||||||
t,
|
t,
|
||||||
@@ -518,10 +549,19 @@ export function ChannelTestDialog({
|
|||||||
[refreshChannelLists, t, testSingleModel]
|
[refreshChannelLists, t, testSingleModel]
|
||||||
)
|
)
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = useCallback(() => {
|
||||||
resetState()
|
resetState()
|
||||||
onOpenChange(false)
|
onOpenChange(false)
|
||||||
}
|
}, [onOpenChange, resetState])
|
||||||
|
|
||||||
|
const handleDialogOpenChange = useCallback(
|
||||||
|
(nextOpen: boolean) => {
|
||||||
|
if (!nextOpen) {
|
||||||
|
handleClose()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[handleClose]
|
||||||
|
)
|
||||||
|
|
||||||
const isAnyTesting = testingModels.size > 0 || isBatchTesting
|
const isAnyTesting = testingModels.size > 0 || isBatchTesting
|
||||||
|
|
||||||
@@ -641,15 +681,11 @@ export function ChannelTestDialog({
|
|||||||
withFacetedRowModel: false,
|
withFacetedRowModel: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!currentRow) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Dialog
|
<Dialog
|
||||||
open={open}
|
open={open}
|
||||||
onOpenChange={handleClose}
|
onOpenChange={handleDialogOpenChange}
|
||||||
title={t('Test Channel Connection')}
|
title={t('Test Channel Connection')}
|
||||||
description={
|
description={
|
||||||
<>
|
<>
|
||||||
@@ -675,7 +711,7 @@ export function ChannelTestDialog({
|
|||||||
<Select
|
<Select
|
||||||
items={endpointSelectItems}
|
items={endpointSelectItems}
|
||||||
value={endpointType}
|
value={endpointType}
|
||||||
onValueChange={(v) => v !== null && setEndpointType(v)}
|
onValueChange={handleEndpointTypeChange}
|
||||||
>
|
>
|
||||||
<SelectTrigger id='endpoint-type'>
|
<SelectTrigger id='endpoint-type'>
|
||||||
<SelectValue placeholder={t('Auto detect (default)')} />
|
<SelectValue placeholder={t('Auto detect (default)')} />
|
||||||
@@ -701,12 +737,12 @@ export function ChannelTestDialog({
|
|||||||
<div className='flex items-center gap-2'>
|
<div className='flex items-center gap-2'>
|
||||||
<Switch
|
<Switch
|
||||||
id='stream-toggle'
|
id='stream-toggle'
|
||||||
checked={isStreamTest}
|
checked={effectiveStreamTest}
|
||||||
onCheckedChange={setIsStreamTest}
|
onCheckedChange={setIsStreamTest}
|
||||||
disabled={streamDisabled}
|
disabled={streamDisabled}
|
||||||
/>
|
/>
|
||||||
<span className='text-sm'>
|
<span className='text-sm'>
|
||||||
{isStreamTest ? t('Enabled') : t('Disabled')}
|
{effectiveStreamTest ? t('Enabled') : t('Disabled')}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<p className='text-muted-foreground text-xs'>
|
<p className='text-muted-foreground text-xs'>
|
||||||
@@ -726,7 +762,7 @@ export function ChannelTestDialog({
|
|||||||
<Input
|
<Input
|
||||||
placeholder={t('Filter models...')}
|
placeholder={t('Filter models...')}
|
||||||
value={searchTerm}
|
value={searchTerm}
|
||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
onChange={handleSearchTermChange}
|
||||||
className='sm:w-64'
|
className='sm:w-64'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user