@@ -72,9 +72,9 @@ const sortOrder = ref<'asc' | 'desc'>(
7272 ? route .query .sort_order
7373 : ' desc' ) as ' asc' | ' desc' ,
7474);
75- // Search + sort + pagination run client-side over the fetched `list`
76- // (backend doesn't support these query params). Status is still backend-driven
77- // via fetchList .
75+ // Backend /models-serving doesn't support any filter/sort/page params, so the
76+ // full pipeline runs client-side: status (exact match) → search → sort →
77+ // paginate .
7878const {
7979 filteredAndSorted : filteredAndSortedList,
8080 paginated : paginatedList,
@@ -88,6 +88,7 @@ const {
8888 {
8989 searchFields: [' isvc_name' , ' model_name' , ' status' ],
9090 sortField: ' creation_timestamp' ,
91+ exactFilters: [{ field: ' status' , value: statusFilter , allValue: ' all' }],
9192 },
9293);
9394
@@ -99,6 +100,7 @@ const SORT_OPTIONS = [
99100const STATUS_OPTIONS = [
100101 { value: ' all' , label: ' All status' },
101102 { value: ' ready' , label: ' Ready' },
103+ { value: ' not_ready' , label: ' Not ready' },
102104 { value: ' pending' , label: ' Pending' },
103105 { value: ' failed' , label: ' Failed' },
104106 { value: ' terminating' , label: ' Terminating' },
@@ -251,16 +253,6 @@ watch(
251253 { deep: true },
252254);
253255
254- // Status filter still goes to the backend, so refetch when it changes.
255- watch (
256- () => route .query .status ,
257- () => {
258- if (viewMode .value !== ' cards' ) return ;
259- isRefreshing .value = true ;
260- fetchList ();
261- },
262- );
263-
264256// Watch status filter - update route
265257watch (statusFilter , () => {
266258 const query = { ... route .query } as Record <string , string >;
@@ -368,6 +360,8 @@ const tableColumns = [
368360 const statusClasses: Record <string , string > = {
369361 ready:
370362 ' bg-green-100 text-green-700 dark:bg-green-800 dark:text-green-100' ,
363+ not_ready:
364+ ' bg-orange-100 text-orange-700 dark:bg-orange-800 dark:text-orange-100' ,
371365 pending:
372366 ' bg-yellow-100 text-yellow-700 dark:bg-yellow-800 dark:text-yellow-100' ,
373367 failed: ' bg-red-100 text-red-700 dark:bg-red-800 dark:text-red-100' ,
@@ -447,13 +441,9 @@ async function fetchList() {
447441 if (! isRefreshing .value ) loading .value = true ;
448442 error .value = null ;
449443 try {
450- // Backend /models-serving does not support page/limit/search/sort_by/sort_order
451- // query params, so we don't send them. Status is kept conditionally because
452- // it's only added when the user picks a non-"all" filter.
453- const res = await getModelsServing ({
454- ... (statusFilter .value &&
455- statusFilter .value !== ' all' && { status: statusFilter .value }),
456- });
444+ // Backend /models-serving doesn't support any filter/sort/page params,
445+ // so we just fetch the full list and do everything client-side.
446+ const res = await getModelsServing ({});
457447 const data = res ?.data ;
458448 list .value = Array .isArray (data ) ? data : [];
459449 } catch (e ) {
@@ -465,6 +455,53 @@ async function fetchList() {
465455 }
466456}
467457
458+ // Table view's `dataSource`. AppTable calls this with route-derived params
459+ // (page, limit, search, sort_by, sort_order, status, isvc_name, etc.); we
460+ // run the same client-side pipeline as the cards view over `list.value` and
461+ // return the slice in AppTable's expected shape. Performs a lazy fetch on
462+ // the first call so the table view also works on direct entry.
463+ async function tableDataSource(params : Record <string , unknown > = {}): Promise <{
464+ status_code: number ;
465+ data: ModelServing [];
466+ pagination: {
467+ total_items: number ;
468+ page: number ;
469+ limit: number ;
470+ total_pages: number ;
471+ };
472+ }> {
473+ if (list .value .length === 0 ) await fetchList ();
474+
475+ const page = parseInt (String (params .page ?? 1 )) || 1 ;
476+ const pageSizeParam = parseInt (String (params .limit ?? 10 )) || 10 ;
477+ const order: ' asc' | ' desc' =
478+ String (params .sort_order ?? ' desc' ) === ' asc' ? ' asc' : ' desc' ;
479+ const search =
480+ (params .isvc_name as string ) || (params .search as string ) || ' ' ;
481+ const status = (params .status as string ) || ' all' ;
482+
483+ const { data, total } = filterSortPaginate <ModelServing >(list .value , {
484+ search ,
485+ searchFields: [' isvc_name' , ' model_name' , ' status' ],
486+ sortField: ' creation_timestamp' ,
487+ sortOrder: order ,
488+ page ,
489+ pageSize: pageSizeParam ,
490+ exactFilters: [{ field: ' status' , value: status , allValue: ' all' }],
491+ });
492+
493+ return {
494+ status_code: 200 ,
495+ data ,
496+ pagination: {
497+ total_items: total ,
498+ page ,
499+ limit: pageSizeParam ,
500+ total_pages: Math .max (1 , Math .ceil (total / pageSizeParam )),
501+ },
502+ };
503+ }
504+
468505const cardsTotalPages = computed (() =>
469506 Math .ceil (cardsTotalItems .value / cardsPageSize .value ),
470507);
@@ -548,7 +585,7 @@ onMounted(() => {
548585 v-if =" viewMode === ' table' "
549586 ref="tableRef"
550587 :columns =" tableColumns "
551- :data-source =" getModelsServing "
588+ :data-source =" tableDataSource "
552589 :sortable-columns =" [' creation_timestamp' ] "
553590 :filterable-columns =" [' status' ] "
554591 :page-size =" 10 "
0 commit comments