feat: enhance model search functionality with status and sync filters
This commit is contained in:
@@ -17,15 +17,15 @@ import (
|
|||||||
func GetAllModelsMeta(c *gin.Context) {
|
func GetAllModelsMeta(c *gin.Context) {
|
||||||
|
|
||||||
pageInfo := common.GetPageQuery(c)
|
pageInfo := common.GetPageQuery(c)
|
||||||
modelsMeta, err := model.GetAllModels(pageInfo.GetStartIdx(), pageInfo.GetPageSize())
|
status := c.Query("status")
|
||||||
|
syncOfficial := c.Query("sync_official")
|
||||||
|
modelsMeta, total, err := model.SearchModels("", "", status, syncOfficial, pageInfo.GetStartIdx(), pageInfo.GetPageSize())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.ApiError(c, err)
|
common.ApiError(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 批量填充附加字段,提升列表接口性能
|
// 批量填充附加字段,提升列表接口性能
|
||||||
enrichModels(modelsMeta)
|
enrichModels(modelsMeta)
|
||||||
var total int64
|
|
||||||
model.DB.Model(&model.Model{}).Count(&total)
|
|
||||||
|
|
||||||
// 统计供应商计数(全部数据,不受分页影响)
|
// 统计供应商计数(全部数据,不受分页影响)
|
||||||
vendorCounts, _ := model.GetVendorModelCounts()
|
vendorCounts, _ := model.GetVendorModelCounts()
|
||||||
@@ -46,18 +46,27 @@ func SearchModelsMeta(c *gin.Context) {
|
|||||||
|
|
||||||
keyword := c.Query("keyword")
|
keyword := c.Query("keyword")
|
||||||
vendor := c.Query("vendor")
|
vendor := c.Query("vendor")
|
||||||
|
status := c.Query("status")
|
||||||
|
syncOfficial := c.Query("sync_official")
|
||||||
pageInfo := common.GetPageQuery(c)
|
pageInfo := common.GetPageQuery(c)
|
||||||
|
|
||||||
modelsMeta, total, err := model.SearchModels(keyword, vendor, pageInfo.GetStartIdx(), pageInfo.GetPageSize())
|
modelsMeta, total, err := model.SearchModels(keyword, vendor, status, syncOfficial, pageInfo.GetStartIdx(), pageInfo.GetPageSize())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.ApiError(c, err)
|
common.ApiError(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 批量填充附加字段,提升列表接口性能
|
// 批量填充附加字段,提升列表接口性能
|
||||||
enrichModels(modelsMeta)
|
enrichModels(modelsMeta)
|
||||||
|
vendorCounts, _ := model.GetVendorModelCounts()
|
||||||
pageInfo.SetTotal(int(total))
|
pageInfo.SetTotal(int(total))
|
||||||
pageInfo.SetItems(modelsMeta)
|
pageInfo.SetItems(modelsMeta)
|
||||||
common.ApiSuccess(c, pageInfo)
|
common.ApiSuccess(c, gin.H{
|
||||||
|
"items": modelsMeta,
|
||||||
|
"total": total,
|
||||||
|
"page": pageInfo.GetPage(),
|
||||||
|
"page_size": pageInfo.GetPageSize(),
|
||||||
|
"vendor_counts": vendorCounts,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetModelMeta 根据 ID 获取单条模型信息
|
// GetModelMeta 根据 ID 获取单条模型信息
|
||||||
|
|||||||
+46
-3
@@ -105,8 +105,7 @@ func GetVendorModelCounts() (map[int64]int64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetAllModels(offset int, limit int) ([]*Model, error) {
|
func GetAllModels(offset int, limit int) ([]*Model, error) {
|
||||||
var models []*Model
|
models, _, err := SearchModels("", "", "", "", offset, limit)
|
||||||
err := DB.Order("id DESC").Offset(offset).Limit(limit).Find(&models).Error
|
|
||||||
return models, err
|
return models, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +191,7 @@ func GetPreferredModelOwnerChannelTypes(modelNames []string, groups []string) (m
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func SearchModels(keyword string, vendor string, offset int, limit int) ([]*Model, int64, error) {
|
func SearchModels(keyword string, vendor string, status string, syncOfficial string, offset int, limit int) ([]*Model, int64, error) {
|
||||||
var models []*Model
|
var models []*Model
|
||||||
db := DB.Model(&Model{})
|
db := DB.Model(&Model{})
|
||||||
if keyword != "" {
|
if keyword != "" {
|
||||||
@@ -206,6 +205,12 @@ func SearchModels(keyword string, vendor string, offset int, limit int) ([]*Mode
|
|||||||
db = db.Joins("JOIN vendors ON vendors.id = models.vendor_id").Where("vendors.name LIKE ?", "%"+vendor+"%")
|
db = db.Joins("JOIN vendors ON vendors.id = models.vendor_id").Where("vendors.name LIKE ?", "%"+vendor+"%")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if statusValue, ok := parseModelStatusFilter(status); ok {
|
||||||
|
db = db.Where("models.status = ?", statusValue)
|
||||||
|
}
|
||||||
|
if syncValue, ok := parseModelSyncFilter(syncOfficial); ok {
|
||||||
|
db = db.Where("models.sync_official = ?", syncValue)
|
||||||
|
}
|
||||||
var total int64
|
var total int64
|
||||||
if err := db.Count(&total).Error; err != nil {
|
if err := db.Count(&total).Error; err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
@@ -215,3 +220,41 @@ func SearchModels(keyword string, vendor string, offset int, limit int) ([]*Mode
|
|||||||
}
|
}
|
||||||
return models, total, nil
|
return models, total, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseModelStatusFilter maps UI/API status values to the models.status column.
|
||||||
|
// Returns ok=false when no status filter should be applied.
|
||||||
|
func parseModelStatusFilter(status string) (value int, ok bool) {
|
||||||
|
switch strings.ToLower(strings.TrimSpace(status)) {
|
||||||
|
case "", "all":
|
||||||
|
return 0, false
|
||||||
|
case "enabled", "1":
|
||||||
|
return 1, true
|
||||||
|
case "disabled", "0":
|
||||||
|
return 0, true
|
||||||
|
default:
|
||||||
|
n, err := strconv.Atoi(status)
|
||||||
|
if err != nil {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return n, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseModelSyncFilter maps UI/API sync values to the models.sync_official column.
|
||||||
|
// Returns ok=false when no sync filter should be applied.
|
||||||
|
func parseModelSyncFilter(syncOfficial string) (value int, ok bool) {
|
||||||
|
switch strings.ToLower(strings.TrimSpace(syncOfficial)) {
|
||||||
|
case "", "all":
|
||||||
|
return 0, false
|
||||||
|
case "yes", "1":
|
||||||
|
return 1, true
|
||||||
|
case "no", "0":
|
||||||
|
return 0, true
|
||||||
|
default:
|
||||||
|
n, err := strconv.Atoi(syncOfficial)
|
||||||
|
if err != nil {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return n, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+58
-60
@@ -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 { type ColumnDef } from '@tanstack/react-table'
|
import type { ColumnDef } from '@tanstack/react-table'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import { BadgeCell, BadgeListCell } from '@/components/data-table'
|
import { BadgeCell, BadgeListCell } from '@/components/data-table'
|
||||||
@@ -99,16 +99,17 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
const id = row.getValue('id') as number
|
const id = row.getValue('id') as number
|
||||||
return <TableId value={id} />
|
return <TableId value={id} />
|
||||||
},
|
},
|
||||||
size: 80,
|
size: 64,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Icon column
|
// Model Name column (with model icon)
|
||||||
{
|
{
|
||||||
accessorKey: 'icon',
|
accessorKey: 'model_name',
|
||||||
header: t('Icon'),
|
header: t('Model Name'),
|
||||||
meta: { mobileHidden: true },
|
meta: { mobileTitle: true },
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const model = row.original
|
const model = row.original
|
||||||
|
const name = row.getValue('model_name') as string
|
||||||
const iconKey =
|
const iconKey =
|
||||||
model.icon ||
|
model.icon ||
|
||||||
vendorMap[model.vendor_id || 0]?.icon ||
|
vendorMap[model.vendor_id || 0]?.icon ||
|
||||||
@@ -117,32 +118,21 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
const icon = getCompactModelIcon(iconKey)
|
const icon = getCompactModelIcon(iconKey)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='ms-1 flex size-5 items-center justify-center overflow-hidden'>
|
<div className='flex max-w-full min-w-0 items-center gap-2'>
|
||||||
{icon}
|
<div className='flex size-5 shrink-0 items-center justify-center overflow-hidden'>
|
||||||
|
{icon}
|
||||||
|
</div>
|
||||||
|
<StatusBadge
|
||||||
|
label={name}
|
||||||
|
variant='neutral'
|
||||||
|
copyText={name}
|
||||||
|
size='sm'
|
||||||
|
className='-ml-1.5 font-mono'
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
size: 70,
|
size: 260,
|
||||||
enableSorting: false,
|
|
||||||
},
|
|
||||||
|
|
||||||
// Model Name column
|
|
||||||
{
|
|
||||||
accessorKey: 'model_name',
|
|
||||||
header: t('Model Name'),
|
|
||||||
meta: { mobileTitle: true },
|
|
||||||
cell: ({ row }) => {
|
|
||||||
const name = row.getValue('model_name') as string
|
|
||||||
return (
|
|
||||||
<StatusBadge
|
|
||||||
label={name}
|
|
||||||
variant='neutral'
|
|
||||||
copyText={name}
|
|
||||||
size='sm'
|
|
||||||
className='-ml-1.5 font-mono'
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
minSize: 200,
|
minSize: 200,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -162,7 +152,6 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
|
|
||||||
const badge = (
|
const badge = (
|
||||||
<StatusBadge
|
<StatusBadge
|
||||||
label={label}
|
|
||||||
variant={
|
variant={
|
||||||
(config.color === 'error' ? 'danger' : config.color) as
|
(config.color === 'error' ? 'danger' : config.color) as
|
||||||
| 'neutral'
|
| 'neutral'
|
||||||
@@ -172,8 +161,10 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
| 'info'
|
| 'info'
|
||||||
}
|
}
|
||||||
size='sm'
|
size='sm'
|
||||||
className='-ml-1.5'
|
className='-ml-1.5 max-w-none shrink-0'
|
||||||
/>
|
>
|
||||||
|
{label}
|
||||||
|
</StatusBadge>
|
||||||
)
|
)
|
||||||
|
|
||||||
// Show tooltip with matched models for non-exact rules
|
// Show tooltip with matched models for non-exact rules
|
||||||
@@ -182,14 +173,16 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
model.matched_models &&
|
model.matched_models &&
|
||||||
model.matched_models.length > 0
|
model.matched_models.length > 0
|
||||||
) {
|
) {
|
||||||
const matchedBadges = model.matched_models.map((m, idx) => (
|
const matchedBadges = model.matched_models.map((m) => (
|
||||||
<StatusBadge key={idx} label={m} autoColor={m} size='sm' />
|
<StatusBadge key={m} label={m} autoColor={m} size='sm' />
|
||||||
))
|
))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger render={<div className='-ml-1.5' />}>
|
<TooltipTrigger
|
||||||
|
render={<div className='inline-flex max-w-full min-w-0' />}
|
||||||
|
>
|
||||||
{badge}
|
{badge}
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent
|
<TooltipContent
|
||||||
@@ -205,7 +198,7 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
|
|
||||||
return badge
|
return badge
|
||||||
},
|
},
|
||||||
size: 140,
|
size: 100,
|
||||||
enableSorting: false,
|
enableSorting: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -221,12 +214,13 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StatusBadge
|
<StatusBadge
|
||||||
label={config.label}
|
|
||||||
variant={config.variant}
|
variant={config.variant}
|
||||||
size='sm'
|
size='sm'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
className='-ml-1.5 max-w-none shrink-0'
|
||||||
/>
|
>
|
||||||
|
{config.label}
|
||||||
|
</StatusBadge>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
filterFn: (row, id, value) => {
|
filterFn: (row, id, value) => {
|
||||||
@@ -236,7 +230,8 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
if (value.includes('disabled')) return status !== 1
|
if (value.includes('disabled')) return status !== 1
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
size: 120,
|
size: 110,
|
||||||
|
minSize: 110,
|
||||||
enableSorting: false,
|
enableSorting: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -262,7 +257,7 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
if (!value || value.length === 0 || value.includes('all')) return true
|
if (!value || value.length === 0 || value.includes('all')) return true
|
||||||
return value.includes(String(row.getValue(id)))
|
return value.includes(String(row.getValue(id)))
|
||||||
},
|
},
|
||||||
size: 150,
|
size: 130,
|
||||||
enableSorting: false,
|
enableSorting: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -293,13 +288,13 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
const tagArray = parseModelTags(tags)
|
const tagArray = parseModelTags(tags)
|
||||||
return (
|
return (
|
||||||
<BadgeListCell
|
<BadgeListCell
|
||||||
items={tagArray.map((tag, idx) => (
|
items={tagArray.map((tag) => (
|
||||||
<StatusBadge key={idx} label={tag} autoColor={tag} size='sm' />
|
<StatusBadge key={tag} label={tag} autoColor={tag} size='sm' />
|
||||||
))}
|
))}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
size: 150,
|
size: 100,
|
||||||
enableSorting: false,
|
enableSorting: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -313,13 +308,14 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
const endpointArray = formatEndpointsDisplay(endpoints)
|
const endpointArray = formatEndpointsDisplay(endpoints)
|
||||||
return (
|
return (
|
||||||
<BadgeListCell
|
<BadgeListCell
|
||||||
items={endpointArray.map((ep, idx) => (
|
max={3}
|
||||||
<StatusBadge key={idx} label={ep} autoColor={ep} size='sm' />
|
items={endpointArray.map((ep) => (
|
||||||
|
<StatusBadge key={ep} label={ep} autoColor={ep} size='sm' />
|
||||||
))}
|
))}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
size: 150,
|
size: 200,
|
||||||
enableSorting: false,
|
enableSorting: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -337,9 +333,9 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
}>
|
}>
|
||||||
return (
|
return (
|
||||||
<BadgeListCell
|
<BadgeListCell
|
||||||
items={(channels ?? []).map((c, idx) => (
|
items={(channels ?? []).map((c) => (
|
||||||
<StatusBadge
|
<StatusBadge
|
||||||
key={idx}
|
key={c.id}
|
||||||
label={`${c.name} (${c.type})`}
|
label={`${c.name} (${c.type})`}
|
||||||
autoColor={c.name}
|
autoColor={c.name}
|
||||||
size='sm'
|
size='sm'
|
||||||
@@ -361,13 +357,14 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
const groups = row.getValue('enable_groups') as string[]
|
const groups = row.getValue('enable_groups') as string[]
|
||||||
return (
|
return (
|
||||||
<BadgeListCell
|
<BadgeListCell
|
||||||
|
max={3}
|
||||||
items={(groups ?? []).map((g) => (
|
items={(groups ?? []).map((g) => (
|
||||||
<GroupBadge key={g} group={g} size='sm' />
|
<GroupBadge key={g} group={g} size='sm' />
|
||||||
))}
|
))}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
size: 150,
|
size: 200,
|
||||||
enableSorting: false,
|
enableSorting: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -380,11 +377,11 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
const quotaTypes = row.getValue('quota_types') as number[]
|
const quotaTypes = row.getValue('quota_types') as number[]
|
||||||
return (
|
return (
|
||||||
<BadgeListCell
|
<BadgeListCell
|
||||||
items={(quotaTypes ?? []).map((qt, idx) => {
|
items={(quotaTypes ?? []).map((qt) => {
|
||||||
const config = QUOTA_TYPE_CONFIG[qt]
|
const config = QUOTA_TYPE_CONFIG[qt]
|
||||||
return (
|
return (
|
||||||
<StatusBadge
|
<StatusBadge
|
||||||
key={idx}
|
key={qt}
|
||||||
label={config?.label || String(qt)}
|
label={config?.label || String(qt)}
|
||||||
variant={
|
variant={
|
||||||
(config?.color === 'error' ? 'danger' : config?.color) as
|
(config?.color === 'error' ? 'danger' : config?.color) as
|
||||||
@@ -414,12 +411,13 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
const syncOfficial = row.getValue('sync_official') as number
|
const syncOfficial = row.getValue('sync_official') as number
|
||||||
return (
|
return (
|
||||||
<StatusBadge
|
<StatusBadge
|
||||||
label={syncOfficial === 1 ? t('Official Sync') : t('No Sync')}
|
|
||||||
variant={syncOfficial === 1 ? 'success' : 'warning'}
|
variant={syncOfficial === 1 ? 'success' : 'warning'}
|
||||||
size='sm'
|
size='sm'
|
||||||
copyable={false}
|
copyable={false}
|
||||||
className='-ml-1.5'
|
className='-ml-1.5 max-w-none shrink-0'
|
||||||
/>
|
>
|
||||||
|
{syncOfficial === 1 ? t('Official Sync') : t('No Sync')}
|
||||||
|
</StatusBadge>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
filterFn: (row, id, value) => {
|
filterFn: (row, id, value) => {
|
||||||
@@ -429,7 +427,7 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
if (value.includes('no')) return syncOfficial !== 1
|
if (value.includes('no')) return syncOfficial !== 1
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
size: 120,
|
size: 100,
|
||||||
enableSorting: false,
|
enableSorting: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -441,12 +439,12 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const timestamp = row.getValue('created_time') as number
|
const timestamp = row.getValue('created_time') as number
|
||||||
return (
|
return (
|
||||||
<div className='min-w-[140px] font-mono text-sm'>
|
<div className='font-mono text-sm whitespace-nowrap'>
|
||||||
{formatTimestampToDate(timestamp)}
|
{formatTimestampToDate(timestamp)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
size: 180,
|
size: 140,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Updated Time column
|
// Updated Time column
|
||||||
@@ -457,12 +455,12 @@ export function useModelsColumns(vendors: Vendor[] = []): ColumnDef<Model>[] {
|
|||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const timestamp = row.getValue('updated_time') as number
|
const timestamp = row.getValue('updated_time') as number
|
||||||
return (
|
return (
|
||||||
<div className='min-w-[140px] font-mono text-sm'>
|
<div className='font-mono text-sm whitespace-nowrap'>
|
||||||
{formatTimestampToDate(timestamp)}
|
{formatTimestampToDate(timestamp)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
size: 180,
|
size: 140,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Actions column
|
// Actions column
|
||||||
|
|||||||
+26
-34
@@ -94,9 +94,6 @@ export function ModelsTable() {
|
|||||||
}))
|
}))
|
||||||
}, [vendors])
|
}, [vendors])
|
||||||
|
|
||||||
// Determine whether to use search or regular list API
|
|
||||||
const shouldSearch = Boolean(globalFilter?.trim())
|
|
||||||
|
|
||||||
// Apply selected vendor from context or filter
|
// Apply selected vendor from context or filter
|
||||||
const activeVendorFilter =
|
const activeVendorFilter =
|
||||||
selectedVendor ||
|
selectedVendor ||
|
||||||
@@ -104,55 +101,50 @@ export function ModelsTable() {
|
|||||||
? vendorFilter[0]
|
? vendorFilter[0]
|
||||||
: undefined)
|
: undefined)
|
||||||
|
|
||||||
|
const statusFilterValue =
|
||||||
|
statusFilter.length > 0 && !statusFilter.includes('all')
|
||||||
|
? statusFilter[0]
|
||||||
|
: undefined
|
||||||
|
const syncFilterValue =
|
||||||
|
syncFilter.length > 0 && !syncFilter.includes('all')
|
||||||
|
? syncFilter[0]
|
||||||
|
: undefined
|
||||||
|
|
||||||
|
// Use search API whenever any filter is active so status/sync are applied server-side
|
||||||
|
const shouldSearch = Boolean(
|
||||||
|
globalFilter?.trim() ||
|
||||||
|
activeVendorFilter ||
|
||||||
|
statusFilterValue ||
|
||||||
|
syncFilterValue
|
||||||
|
)
|
||||||
|
|
||||||
// Fetch models data
|
// Fetch models data
|
||||||
// eslint-disable-next-line @tanstack/query/exhaustive-deps
|
// eslint-disable-next-line @tanstack/query/exhaustive-deps
|
||||||
const { data, isLoading, isFetching } = useQuery({
|
const { data, isLoading, isFetching } = useQuery({
|
||||||
queryKey: modelsQueryKeys.list({
|
queryKey: modelsQueryKeys.list({
|
||||||
keyword: globalFilter,
|
keyword: globalFilter,
|
||||||
vendor: activeVendorFilter,
|
vendor: activeVendorFilter,
|
||||||
status:
|
status: statusFilterValue,
|
||||||
statusFilter.length > 0 && !statusFilter.includes('all')
|
sync_official: syncFilterValue,
|
||||||
? statusFilter[0]
|
|
||||||
: undefined,
|
|
||||||
sync_official:
|
|
||||||
syncFilter.length > 0 && !syncFilter.includes('all')
|
|
||||||
? syncFilter[0]
|
|
||||||
: undefined,
|
|
||||||
p: pagination.pageIndex + 1,
|
p: pagination.pageIndex + 1,
|
||||||
page_size: pagination.pageSize,
|
page_size: pagination.pageSize,
|
||||||
}),
|
}),
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
if (shouldSearch || activeVendorFilter) {
|
if (shouldSearch) {
|
||||||
return searchModels({
|
return searchModels({
|
||||||
keyword: globalFilter,
|
keyword: globalFilter,
|
||||||
vendor: activeVendorFilter,
|
vendor: activeVendorFilter,
|
||||||
status:
|
status: statusFilterValue,
|
||||||
statusFilter.length > 0 && !statusFilter.includes('all')
|
sync_official: syncFilterValue,
|
||||||
? statusFilter[0]
|
|
||||||
: undefined,
|
|
||||||
sync_official:
|
|
||||||
syncFilter.length > 0 && !syncFilter.includes('all')
|
|
||||||
? syncFilter[0]
|
|
||||||
: undefined,
|
|
||||||
p: pagination.pageIndex + 1,
|
|
||||||
page_size: pagination.pageSize,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
return getModels({
|
|
||||||
status:
|
|
||||||
statusFilter.length > 0 && !statusFilter.includes('all')
|
|
||||||
? statusFilter[0]
|
|
||||||
: undefined,
|
|
||||||
sync_official:
|
|
||||||
syncFilter.length > 0 && !syncFilter.includes('all')
|
|
||||||
? syncFilter[0]
|
|
||||||
: undefined,
|
|
||||||
p: pagination.pageIndex + 1,
|
p: pagination.pageIndex + 1,
|
||||||
page_size: pagination.pageSize,
|
page_size: pagination.pageSize,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
return getModels({
|
||||||
|
p: pagination.pageIndex + 1,
|
||||||
|
page_size: pagination.pageSize,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
placeholderData: (previousData) => previousData,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const models = data?.data?.items || []
|
const models = data?.data?.items || []
|
||||||
|
|||||||
Reference in New Issue
Block a user