feat(openwrt): add TollGate provision button and direct-download fallback
- OpenWrtGateway.vue: add "Install TollGate" button when not installed; tracks connected credentials for reuse in the provision call - install.rs: fall back to wget download from GitHub releases when the package is not in any opkg feed (mips_24kc and other arches supported) - openwrt.rs: provision-tollgate now falls back to saved router_config for credentials, matching the behaviour of get-status Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -48,6 +48,13 @@ const sshPassword = ref('')
|
||||
const showConnectForm = ref(false)
|
||||
const connecting = ref(false)
|
||||
|
||||
// Credentials used for the last successful connection (reused for provisioning)
|
||||
const connectedParams = ref<Record<string, string> | null>(null)
|
||||
|
||||
const provisioning = ref(false)
|
||||
const provisionError = ref('')
|
||||
const provisionSuccess = ref(false)
|
||||
|
||||
async function load(params?: Record<string, string>) {
|
||||
loading.value = true
|
||||
error.value = ''
|
||||
@@ -58,6 +65,7 @@ async function load(params?: Record<string, string>) {
|
||||
timeout: 30000,
|
||||
})
|
||||
showConnectForm.value = false
|
||||
if (params) connectedParams.value = params
|
||||
} catch (e) {
|
||||
const msg = e instanceof Error ? e.message : String(e)
|
||||
if (msg.includes('No router configured')) {
|
||||
@@ -81,6 +89,28 @@ async function connect() {
|
||||
}
|
||||
}
|
||||
|
||||
async function provisionTollgate() {
|
||||
provisioning.value = true
|
||||
provisionError.value = ''
|
||||
provisionSuccess.value = false
|
||||
try {
|
||||
const params: Record<string, unknown> = {
|
||||
// Use explicitly connected creds if available, otherwise fall back to
|
||||
// host from the loaded status (backend will use saved router_config).
|
||||
host: connectedParams.value?.host ?? status.value?.host,
|
||||
ssh_user: connectedParams.value?.ssh_user ?? sshUser.value,
|
||||
ssh_password: connectedParams.value?.ssh_password ?? sshPassword.value,
|
||||
}
|
||||
await rpcClient.call({ method: 'openwrt.provision-tollgate', params, timeout: 180000 })
|
||||
provisionSuccess.value = true
|
||||
await load(connectedParams.value ?? undefined)
|
||||
} catch (e) {
|
||||
provisionError.value = e instanceof Error ? e.message : String(e)
|
||||
} finally {
|
||||
provisioning.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function formatUptime(secs: number): string {
|
||||
const d = Math.floor(secs / 86400)
|
||||
const h = Math.floor((secs % 86400) / 3600)
|
||||
@@ -229,9 +259,23 @@ onMounted(() => load())
|
||||
<div class="rounded-xl border border-white/10 bg-white/5 p-5 mb-4">
|
||||
<h2 class="text-sm font-semibold text-white/80 mb-4">TollGate</h2>
|
||||
|
||||
<div v-if="!status.tollgate.installed" class="flex items-center gap-3">
|
||||
<span class="w-2 h-2 rounded-full bg-white/20 inline-block"></span>
|
||||
<span class="text-sm text-white/50">Not installed</span>
|
||||
<div v-if="!status.tollgate.installed">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<span class="w-2 h-2 rounded-full bg-white/20 inline-block"></span>
|
||||
<span class="text-sm text-white/50">Not installed</span>
|
||||
</div>
|
||||
<button
|
||||
:disabled="provisioning"
|
||||
class="w-full py-2 rounded-lg text-sm font-medium transition-colors"
|
||||
:class="provisioning
|
||||
? 'bg-white/5 text-white/30 cursor-not-allowed'
|
||||
: 'bg-blue-600 hover:bg-blue-500 text-white'"
|
||||
@click="provisionTollgate"
|
||||
>
|
||||
{{ provisioning ? 'Installing TollGate… (may take a few minutes)' : 'Install TollGate' }}
|
||||
</button>
|
||||
<p v-if="provisionError" class="mt-2 text-xs text-red-400">{{ provisionError }}</p>
|
||||
<p v-if="provisionSuccess && !provisioning" class="mt-2 text-xs text-green-400">TollGate provisioned successfully.</p>
|
||||
</div>
|
||||
|
||||
<template v-else>
|
||||
|
||||
Reference in New Issue
Block a user