From 316bacdff52c4d97ef7968b591e1a7c75fc9e24d Mon Sep 17 00:00:00 2001 From: "LocalAI [bot]" <139863280+localai-bot@users.noreply.github.com> Date: Mon, 9 Mar 2026 09:25:27 +0100 Subject: [PATCH] feat: Add tabs to System view for Models and Backends (#8885) feat: add tabs to System view for Models and Backends - Split System view into two tabs: Models and Backends - Use URL search params and localStorage for tab state persistence - Optimize API calls to only fetch data for active tab - Add tab counts in labels showing number of items - Use existing tab CSS patterns from the codebase - Maintain all existing functionality with improved UX Signed-off-by: localai-bot Co-authored-by: localai-bot --- core/http/react-ui/src/pages/Manage.jsx | 67 ++++++++++++++++++------- 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/core/http/react-ui/src/pages/Manage.jsx b/core/http/react-ui/src/pages/Manage.jsx index 522f873d0..56ab73f23 100644 --- a/core/http/react-ui/src/pages/Manage.jsx +++ b/core/http/react-ui/src/pages/Manage.jsx @@ -1,12 +1,20 @@ import { useState, useEffect, useCallback } from 'react' -import { useNavigate, useOutletContext } from 'react-router-dom' +import { useNavigate, useOutletContext, useSearchParams } from 'react-router-dom' import ResourceMonitor from '../components/ResourceMonitor' import { useModels } from '../hooks/useModels' import { backendControlApi, modelsApi, backendsApi, systemApi } from '../utils/api' +const TABS = [ + { key: 'models', label: 'Models', icon: 'fa-brain' }, + { key: 'backends', label: 'Backends', icon: 'fa-server' }, +] + export default function Manage() { const { addToast } = useOutletContext() const navigate = useNavigate() + const [searchParams, setSearchParams] = useSearchParams() + const initialTab = searchParams.get('tab') || localStorage.getItem('manage-tab') || 'models' + const [activeTab, setActiveTab] = useState(TABS.some(t => t.key === initialTab) ? initialTab : 'models') const { models, loading: modelsLoading, refetch: refetchModels } = useModels() const [loadedModelIds, setLoadedModelIds] = useState(new Set()) const [backends, setBackends] = useState([]) @@ -14,6 +22,12 @@ export default function Manage() { const [reloading, setReloading] = useState(false) const [reinstallingBackends, setReinstallingBackends] = useState(new Set()) + const handleTabChange = (tab) => { + setActiveTab(tab) + localStorage.setItem('manage-tab', tab) + setSearchParams({ tab }) + } + const fetchLoadedModels = useCallback(async () => { try { const info = await systemApi.info() @@ -37,9 +51,12 @@ export default function Manage() { }, []) useEffect(() => { - fetchLoadedModels() - fetchBackends() - }, [fetchLoadedModels, fetchBackends]) + if (activeTab === 'models') { + fetchLoadedModels() + } else { + fetchBackends() + } + }, [activeTab, fetchLoadedModels, fetchBackends]) const handleStopModel = async (modelName) => { if (!confirm(`Stop model ${modelName}?`)) return @@ -106,18 +123,33 @@ export default function Manage() { return (
-

Model & Backend Management

+

System

+

Manage installed models and backends

{/* Resource Monitor */} - {/* Models Section */} -
-
-

- Models ({models.length}) -

+ {/* Tabs */} +
+ {TABS.map(t => ( + + ))} +
+ + {/* Models Tab */} + {activeTab === 'models' && ( +
+
)}
+ )} - {/* Backends Section */} -
-
-

- Backends ({backends.length}) -

-
- + {/* Backends Tab */} + {activeTab === 'backends' && ( +
{backendsLoading ? (
Loading backends... @@ -345,6 +373,7 @@ export default function Manage() {
)}
+ )}
) }