mirror of
https://github.com/mudler/LocalAI.git
synced 2026-07-31 18:38:23 -04:00
feat(ui): add useP2PMode hook and embedded prop to Nodes and P2P pages
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
committed by
localai-org-maint-bot
parent
60921de0ba
commit
9ecc9fe6eb
31
core/http/react-ui/src/hooks/useP2PMode.js
vendored
Normal file
31
core/http/react-ui/src/hooks/useP2PMode.js
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { p2pApi } from '../utils/api'
|
||||
|
||||
// useP2PMode reports whether p2p / swarm mode is available, mirroring
|
||||
// useDistributedMode. Availability is "a network token exists" (the same signal
|
||||
// the standalone P2P page used). One-shot probe on mount plus a manual refetch.
|
||||
//
|
||||
// Returns:
|
||||
// enabled — true when a non-empty network token is present
|
||||
// loading — true until the first probe completes
|
||||
// refetch — manual trigger to re-run the probe
|
||||
export function useP2PMode() {
|
||||
const [enabled, setEnabled] = useState(false)
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
const probe = useCallback(async () => {
|
||||
setLoading(true)
|
||||
try {
|
||||
const token = await p2pApi.getToken()
|
||||
setEnabled(!!(token && String(token).trim()))
|
||||
} catch {
|
||||
setEnabled(false)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => { probe() }, [probe])
|
||||
|
||||
return { enabled, loading, refetch: probe }
|
||||
}
|
||||
@@ -107,7 +107,7 @@ function WorkerHintCard({ addToast, activeTab, hasWorkers }) {
|
||||
)
|
||||
}
|
||||
|
||||
export default function Nodes() {
|
||||
export default function Nodes({ embedded = false }) {
|
||||
const { addToast } = useOutletContext()
|
||||
const { t } = useTranslation('admin')
|
||||
const [nodesList, setNodesList] = useState([])
|
||||
@@ -309,16 +309,18 @@ export default function Nodes() {
|
||||
: activeTab === 'agent' ? agentNodes : backendNodes
|
||||
|
||||
return (
|
||||
<div className="page page--wide">
|
||||
<PageHeader
|
||||
title={
|
||||
<>
|
||||
<i className="fas fa-network-wired" style={{ marginRight: 'var(--spacing-sm)' }} />
|
||||
{t('nodes.title')}
|
||||
</>
|
||||
}
|
||||
supporting={t('nodes.subtitle')}
|
||||
/>
|
||||
<div className={embedded ? '' : 'page page--wide'}>
|
||||
{!embedded && (
|
||||
<PageHeader
|
||||
title={
|
||||
<>
|
||||
<i className="fas fa-network-wired" style={{ marginRight: 'var(--spacing-sm)' }} />
|
||||
{t('nodes.title')}
|
||||
</>
|
||||
}
|
||||
supporting={t('nodes.subtitle')}
|
||||
/>
|
||||
)}
|
||||
|
||||
<ClusterPulse nodes={nodesList} />
|
||||
<AttentionCallout nodes={nodesList} onApprove={handleApprove} />
|
||||
|
||||
@@ -103,7 +103,7 @@ function StepNumber({ n, bg, color }) {
|
||||
)
|
||||
}
|
||||
|
||||
export default function P2P() {
|
||||
export default function P2P({ embedded = false }) {
|
||||
const { addToast } = useOutletContext()
|
||||
const { t } = useTranslation('admin')
|
||||
const [workers, setWorkers] = useState([])
|
||||
@@ -173,7 +173,7 @@ export default function P2P() {
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="page page--narrow" style={{ display: 'flex', justifyContent: 'center', padding: 'var(--spacing-xl)' }}>
|
||||
<div className={embedded ? '' : 'page page--narrow'} style={{ display: 'flex', justifyContent: 'center', padding: 'var(--spacing-xl)' }}>
|
||||
<LoadingSpinner size="lg" />
|
||||
</div>
|
||||
)
|
||||
@@ -182,7 +182,7 @@ export default function P2P() {
|
||||
// ── P2P Disabled ──
|
||||
if (!enabled) {
|
||||
return (
|
||||
<div className="page page--narrow">
|
||||
<div className={embedded ? '' : 'page page--narrow'}>
|
||||
<div style={{ textAlign: 'center', padding: 'var(--spacing-xl) 0' }}>
|
||||
<i className="fas fa-network-wired" style={{ fontSize: '3rem', color: 'var(--color-primary)', marginBottom: 'var(--spacing-md)' }} />
|
||||
<h1 style={{ fontSize: '1.5rem', fontWeight: 600, marginBottom: 'var(--spacing-sm)' }}>
|
||||
@@ -295,25 +295,27 @@ export default function P2P() {
|
||||
const mlxTotal = stats.mlx_workers?.total ?? 0
|
||||
|
||||
return (
|
||||
<div className="page page--narrow">
|
||||
<PageHeader
|
||||
title={
|
||||
<>
|
||||
<i className="fas fa-circle-nodes" style={{ marginRight: 'var(--spacing-sm)' }} />
|
||||
{t('p2p.title')}
|
||||
</>
|
||||
}
|
||||
supporting={
|
||||
<>
|
||||
{t('p2p.subtitle')}
|
||||
{' '}
|
||||
<a href="https://localai.io/features/distribute/" target="_blank" rel="noopener noreferrer"
|
||||
style={{ color: 'var(--color-primary)' }}>
|
||||
<i className="fas fa-circle-info" />
|
||||
</a>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<div className={embedded ? '' : 'page page--narrow'}>
|
||||
{!embedded && (
|
||||
<PageHeader
|
||||
title={
|
||||
<>
|
||||
<i className="fas fa-circle-nodes" style={{ marginRight: 'var(--spacing-sm)' }} />
|
||||
{t('p2p.title')}
|
||||
</>
|
||||
}
|
||||
supporting={
|
||||
<>
|
||||
{t('p2p.subtitle')}
|
||||
{' '}
|
||||
<a href="https://localai.io/features/distribute/" target="_blank" rel="noopener noreferrer"
|
||||
style={{ color: 'var(--color-primary)' }}>
|
||||
<i className="fas fa-circle-info" />
|
||||
</a>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Network Token */}
|
||||
<div style={{
|
||||
|
||||
Reference in New Issue
Block a user