forked from defunkt/toes
Add WiFi config and system info endpoints
This commit is contained in:
parent
8f74f9daa0
commit
f8c5890e07
|
|
@ -4,15 +4,8 @@ export const getLogDates = (name: string): Promise<string[]> =>
|
||||||
export const getLogsForDate = (name: string, date: string): Promise<string[]> =>
|
export const getLogsForDate = (name: string, date: string): Promise<string[]> =>
|
||||||
fetch(`/api/apps/${name}/logs?date=${date}`).then(r => r.json())
|
fetch(`/api/apps/${name}/logs?date=${date}`).then(r => r.json())
|
||||||
|
|
||||||
export const getWifiConfig = (): Promise<{ network: string, password: string }> =>
|
export const getSystemInfo = (): Promise<{ version: string, sha: string }> =>
|
||||||
fetch('/api/system/wifi').then(r => r.json())
|
fetch('/api/system/info').then(r => r.json())
|
||||||
|
|
||||||
export const saveWifiConfig = (config: { network: string, password: string }) =>
|
|
||||||
fetch('/api/system/wifi', {
|
|
||||||
method: 'PUT',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify(config),
|
|
||||||
}).then(r => r.json())
|
|
||||||
|
|
||||||
export const shareApp = (name: string) =>
|
export const shareApp = (name: string) =>
|
||||||
fetch(`/api/apps/${name}/tunnel`, { method: 'POST' })
|
fetch(`/api/apps/${name}/tunnel`, { method: 'POST' })
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,9 @@
|
||||||
import { useEffect, useState } from 'hono/jsx'
|
import { useEffect, useState } from 'hono/jsx'
|
||||||
import { getWifiConfig, saveWifiConfig } from '../api'
|
import { getSystemInfo } from '../api'
|
||||||
import { navigate } from '../router'
|
import { navigate } from '../router'
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
DashboardInstallCmd,
|
DashboardInstallCmd,
|
||||||
FormActions,
|
|
||||||
FormField,
|
|
||||||
FormInput,
|
|
||||||
FormLabel,
|
|
||||||
HeaderActions,
|
HeaderActions,
|
||||||
Main,
|
Main,
|
||||||
MainContent,
|
MainContent,
|
||||||
|
|
@ -18,15 +14,13 @@ import {
|
||||||
} from '../styles'
|
} from '../styles'
|
||||||
|
|
||||||
export function SettingsPage({ render }: { render: () => void }) {
|
export function SettingsPage({ render }: { render: () => void }) {
|
||||||
const [network, setNetwork] = useState('')
|
const [version, setVersion] = useState('')
|
||||||
const [password, setPassword] = useState('')
|
const [sha, setSha] = useState('')
|
||||||
const [saving, setSaving] = useState(false)
|
|
||||||
const [saved, setSaved] = useState(false)
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getWifiConfig().then(config => {
|
getSystemInfo().then(info => {
|
||||||
setNetwork(config.network)
|
setVersion(info.version)
|
||||||
setPassword(config.password)
|
setSha(info.sha)
|
||||||
})
|
})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
|
@ -34,15 +28,6 @@ export function SettingsPage({ render }: { render: () => void }) {
|
||||||
navigate('/')
|
navigate('/')
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSave = async (e: Event) => {
|
|
||||||
e.preventDefault()
|
|
||||||
setSaving(true)
|
|
||||||
setSaved(false)
|
|
||||||
await saveWifiConfig({ network, password })
|
|
||||||
setSaving(false)
|
|
||||||
setSaved(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Main>
|
<Main>
|
||||||
<MainHeader centered>
|
<MainHeader centered>
|
||||||
|
|
@ -53,33 +38,11 @@ export function SettingsPage({ render }: { render: () => void }) {
|
||||||
</MainHeader>
|
</MainHeader>
|
||||||
<MainContent centered>
|
<MainContent centered>
|
||||||
<Section>
|
<Section>
|
||||||
<SectionTitle>WiFi</SectionTitle>
|
<SectionTitle>About</SectionTitle>
|
||||||
<form onSubmit={handleSave} style={{ display: 'flex', flexDirection: 'column', gap: 16, maxWidth: 400 }}>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 8, fontSize: 14 }}>
|
||||||
<FormField>
|
<span>Version: {version}</span>
|
||||||
<FormLabel>Network</FormLabel>
|
<span>SHA: {sha}</span>
|
||||||
<FormInput
|
</div>
|
||||||
type="text"
|
|
||||||
value={network}
|
|
||||||
onInput={(e: Event) => setNetwork((e.target as HTMLInputElement).value)}
|
|
||||||
placeholder="SSID"
|
|
||||||
/>
|
|
||||||
</FormField>
|
|
||||||
<FormField>
|
|
||||||
<FormLabel>Password</FormLabel>
|
|
||||||
<FormInput
|
|
||||||
type="password"
|
|
||||||
value={password}
|
|
||||||
onInput={(e: Event) => setPassword((e.target as HTMLInputElement).value)}
|
|
||||||
placeholder="Password"
|
|
||||||
/>
|
|
||||||
</FormField>
|
|
||||||
<FormActions>
|
|
||||||
{saved && <span style={{ fontSize: 13, color: '#888', alignSelf: 'center' }}>Saved</span>}
|
|
||||||
<Button variant="primary" type="submit" disabled={saving}>
|
|
||||||
{saving ? 'Saving...' : 'Save'}
|
|
||||||
</Button>
|
|
||||||
</FormActions>
|
|
||||||
</form>
|
|
||||||
</Section>
|
</Section>
|
||||||
<Section>
|
<Section>
|
||||||
<SectionTitle>Install CLI</SectionTitle>
|
<SectionTitle>Install CLI</SectionTitle>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { allApps, APPS_DIR, onChange, TOES_DIR } from '$apps'
|
import { allApps, APPS_DIR, onChange } from '$apps'
|
||||||
import { onHostLog } from '../tui'
|
import { onHostLog } from '../tui'
|
||||||
import { Hype } from '@because/hype'
|
import { Hype } from '@because/hype'
|
||||||
import { cpus, freemem, platform, totalmem } from 'os'
|
import { cpus, freemem, platform, totalmem } from 'os'
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import { existsSync, mkdirSync, readFileSync, statfsSync, writeFileSync } from 'fs'
|
import { readFileSync, statfsSync } from 'fs'
|
||||||
|
|
||||||
export interface AppMetrics {
|
export interface AppMetrics {
|
||||||
cpu: number
|
cpu: number
|
||||||
|
|
@ -18,11 +18,6 @@ export interface SystemMetrics {
|
||||||
apps: Record<string, AppMetrics>
|
apps: Record<string, AppMetrics>
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WifiConfig {
|
|
||||||
network: string
|
|
||||||
password: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UnifiedLogLine {
|
export interface UnifiedLogLine {
|
||||||
time: number
|
time: number
|
||||||
app: string
|
app: string
|
||||||
|
|
@ -190,36 +185,12 @@ router.sse('/metrics/stream', (send) => {
|
||||||
return () => clearInterval(interval)
|
return () => clearInterval(interval)
|
||||||
})
|
})
|
||||||
|
|
||||||
// WiFi config
|
// System info
|
||||||
const CONFIG_DIR = join(TOES_DIR, 'config')
|
const pkg = JSON.parse(readFileSync(join(import.meta.dir, '../../../package.json'), 'utf-8'))
|
||||||
const WIFI_PATH = join(CONFIG_DIR, 'wifi.json')
|
const sha = Bun.spawnSync(['git', 'rev-parse', '--short', 'HEAD'], { cwd: join(import.meta.dir, '../../..') }).stdout.toString().trim() || 'unknown'
|
||||||
|
|
||||||
function readWifiConfig(): WifiConfig {
|
router.get('/info', c => {
|
||||||
try {
|
return c.json({ version: pkg.version, sha })
|
||||||
if (existsSync(WIFI_PATH)) {
|
|
||||||
return JSON.parse(readFileSync(WIFI_PATH, 'utf-8'))
|
|
||||||
}
|
|
||||||
} catch {}
|
|
||||||
return { network: '', password: '' }
|
|
||||||
}
|
|
||||||
|
|
||||||
function writeWifiConfig(config: WifiConfig) {
|
|
||||||
if (!existsSync(CONFIG_DIR)) mkdirSync(CONFIG_DIR, { recursive: true })
|
|
||||||
writeFileSync(WIFI_PATH, JSON.stringify(config, null, 2))
|
|
||||||
}
|
|
||||||
|
|
||||||
router.get('/wifi', c => {
|
|
||||||
return c.json(readWifiConfig())
|
|
||||||
})
|
|
||||||
|
|
||||||
router.put('/wifi', async c => {
|
|
||||||
const body = await c.req.json<WifiConfig>()
|
|
||||||
const config: WifiConfig = {
|
|
||||||
network: String(body.network ?? ''),
|
|
||||||
password: String(body.password ?? ''),
|
|
||||||
}
|
|
||||||
writeWifiConfig(config)
|
|
||||||
return c.json(config)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Get recent unified logs
|
// Get recent unified logs
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user