Load models in the UI without navigating the page (#173)
* Load models in the UI without navigating the page * fix table layout for mobile
This commit is contained in:
@@ -12,6 +12,7 @@ interface APIProviderType {
|
|||||||
models: Model[];
|
models: Model[];
|
||||||
listModels: () => Promise<Model[]>;
|
listModels: () => Promise<Model[]>;
|
||||||
unloadAllModels: () => Promise<void>;
|
unloadAllModels: () => Promise<void>;
|
||||||
|
loadModel: (model: string) => Promise<void>;
|
||||||
enableProxyLogs: (enabled: boolean) => void;
|
enableProxyLogs: (enabled: boolean) => void;
|
||||||
enableUpstreamLogs: (enabled: boolean) => void;
|
enableUpstreamLogs: (enabled: boolean) => void;
|
||||||
enableModelUpdates: (enabled: boolean) => void;
|
enableModelUpdates: (enabled: boolean) => void;
|
||||||
@@ -139,11 +140,26 @@ export function APIProvider({ children }: APIProviderProps) {
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const loadModel = useCallback(async (model: string) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/upstream/${model}/`, {
|
||||||
|
method: "GET",
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Failed to load model: ${response.status}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to load model:", error);
|
||||||
|
throw error; // Re-throw to let calling code handle it
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
const value = useMemo(
|
const value = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
models,
|
models,
|
||||||
listModels,
|
listModels,
|
||||||
unloadAllModels,
|
unloadAllModels,
|
||||||
|
loadModel,
|
||||||
enableProxyLogs,
|
enableProxyLogs,
|
||||||
enableUpstreamLogs,
|
enableUpstreamLogs,
|
||||||
enableModelUpdates,
|
enableModelUpdates,
|
||||||
@@ -154,6 +170,7 @@ export function APIProvider({ children }: APIProviderProps) {
|
|||||||
models,
|
models,
|
||||||
listModels,
|
listModels,
|
||||||
unloadAllModels,
|
unloadAllModels,
|
||||||
|
loadModel,
|
||||||
enableProxyLogs,
|
enableProxyLogs,
|
||||||
enableUpstreamLogs,
|
enableUpstreamLogs,
|
||||||
enableModelUpdates,
|
enableModelUpdates,
|
||||||
|
|||||||
@@ -143,6 +143,10 @@
|
|||||||
@apply bg-surface p-2 px-4 text-sm rounded-full border border-2 transition-colors duration-200 border-btn-border;
|
@apply bg-surface p-2 px-4 text-sm rounded-full border border-2 transition-colors duration-200 border-btn-border;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.btn--sm {
|
.btn--sm {
|
||||||
@apply px-2 py-0.5 text-xs;
|
@apply px-2 py-0.5 text-xs;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { useAPI } from "../contexts/APIProvider";
|
|||||||
import { LogPanel } from "./LogViewer";
|
import { LogPanel } from "./LogViewer";
|
||||||
|
|
||||||
export default function ModelsPage() {
|
export default function ModelsPage() {
|
||||||
const { models, enableModelUpdates, unloadAllModels, upstreamLogs, enableUpstreamLogs } = useAPI();
|
const { models, enableModelUpdates, unloadAllModels, loadModel, upstreamLogs, enableUpstreamLogs } = useAPI();
|
||||||
const [isUnloading, setIsUnloading] = useState(false);
|
const [isUnloading, setIsUnloading] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -43,6 +43,7 @@ export default function ModelsPage() {
|
|||||||
<thead>
|
<thead>
|
||||||
<tr className="border-b border-primary">
|
<tr className="border-b border-primary">
|
||||||
<th className="text-left p-2">Name</th>
|
<th className="text-left p-2">Name</th>
|
||||||
|
<th className="text-left p-2"></th>
|
||||||
<th className="text-left p-2">State</th>
|
<th className="text-left p-2">State</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -50,10 +51,13 @@ export default function ModelsPage() {
|
|||||||
{models.map((model) => (
|
{models.map((model) => (
|
||||||
<tr key={model.id} className="border-b hover:bg-secondary-hover border-border">
|
<tr key={model.id} className="border-b hover:bg-secondary-hover border-border">
|
||||||
<td className="p-2">
|
<td className="p-2">
|
||||||
<a href={`/upstream/${model.id}/`} className="underline" target="top">
|
<a href={`/upstream/${model.id}/`} className="underline" target="_blank">
|
||||||
{model.id}
|
{model.id}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
<td className="p-2">
|
||||||
|
<button className="btn btn--sm" disabled={model.state !== "stopped"} onClick={() => loadModel(model.id)}>Load</button>
|
||||||
|
</td>
|
||||||
<td className="p-2">
|
<td className="p-2">
|
||||||
<span className={`status status--${model.state}`}>{model.state}</span>
|
<span className={`status status--${model.state}`}>{model.state}</span>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
Reference in New Issue
Block a user