beta-0.8
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted, ref } from "vue";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
|
||||
interface Project {
|
||||
name: string;
|
||||
path: string;
|
||||
pool: string | null;
|
||||
running: boolean;
|
||||
}
|
||||
|
||||
interface Pool {
|
||||
name: string;
|
||||
credentialFile: string;
|
||||
credentialType: string;
|
||||
}
|
||||
|
||||
const projects = ref<Project[]>([]);
|
||||
const pools = ref<Pool[]>([]);
|
||||
const error = ref("");
|
||||
|
||||
async function refresh() {
|
||||
try {
|
||||
projects.value = await invoke<Project[]>("list_projects");
|
||||
pools.value = await invoke<Pool[]>("list_pools");
|
||||
error.value = "";
|
||||
} catch (e) {
|
||||
error.value = String(e);
|
||||
}
|
||||
}
|
||||
|
||||
async function start(project: Project) {
|
||||
try {
|
||||
await invoke("start_project", { project: project.name });
|
||||
await refresh();
|
||||
} catch (e) {
|
||||
error.value = String(e);
|
||||
}
|
||||
}
|
||||
|
||||
interface PendingRestart {
|
||||
name: string;
|
||||
from: string | null;
|
||||
to: string;
|
||||
}
|
||||
|
||||
const pending = ref<PendingRestart | null>(null);
|
||||
const restarting = ref(false);
|
||||
|
||||
async function assign(project: Project, event: Event) {
|
||||
const pool = (event.target as HTMLSelectElement).value;
|
||||
const from = project.pool;
|
||||
try {
|
||||
await invoke("assign_pool", { project: project.name, pool });
|
||||
if (project.running && pool !== from) {
|
||||
pending.value = { name: project.name, from, to: pool };
|
||||
}
|
||||
await refresh();
|
||||
} catch (e) {
|
||||
error.value = String(e);
|
||||
}
|
||||
}
|
||||
|
||||
async function restartNow() {
|
||||
const p = pending.value!;
|
||||
restarting.value = true;
|
||||
try {
|
||||
await invoke("restart_project", { project: p.name });
|
||||
pending.value = null;
|
||||
await refresh();
|
||||
} catch (e) {
|
||||
error.value = String(e);
|
||||
pending.value = null;
|
||||
}
|
||||
restarting.value = false;
|
||||
}
|
||||
|
||||
let timer: number;
|
||||
onMounted(() => {
|
||||
refresh();
|
||||
timer = window.setInterval(refresh, 3000);
|
||||
});
|
||||
onUnmounted(() => window.clearInterval(timer));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<p v-if="error" class="error">{{ error }}</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Projekt</th>
|
||||
<th>Pool</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="p in projects" :key="p.name">
|
||||
<td>
|
||||
<span class="dot" :class="{ on: p.running }"></span>
|
||||
</td>
|
||||
<td>
|
||||
<strong>{{ p.name }}</strong>
|
||||
<small>{{ p.path }}</small>
|
||||
</td>
|
||||
<td>
|
||||
<select :value="p.pool ?? ''" @change="assign(p, $event)">
|
||||
<option value="" disabled>– kein Pool –</option>
|
||||
<option v-for="pool in pools" :key="pool.name" :value="pool.name">
|
||||
{{ pool.name }}
|
||||
</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<button @click="start(p)">
|
||||
{{ p.running ? "Aktivieren" : "Starten" }}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div v-if="pending" class="overlay">
|
||||
<div class="dialog">
|
||||
<h3>{{ pending.name }} läuft noch</h3>
|
||||
<p>
|
||||
Der Pool-Wechsel ist gespeichert. Die laufende Session arbeitet aber
|
||||
weiter im alten Pool — der neue gilt erst ab dem nächsten Start.
|
||||
</p>
|
||||
<div class="pools">
|
||||
<span class="chip">{{ pending.from ?? "kein Pool" }}</span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="chip new">{{ pending.to }}</span>
|
||||
</div>
|
||||
<p class="hint">
|
||||
Der Neustart beendet die laufende Session. Der automatische
|
||||
commit+push von claude-sync nach Sessionende entfällt dabei —
|
||||
Ghostty fragt bei laufendem Prozess vor dem Beenden noch einmal nach.
|
||||
</p>
|
||||
<div class="actions">
|
||||
<button @click="pending = null">Weiterlaufen lassen</button>
|
||||
<button class="primary" :disabled="restarting" @click="restartNow">
|
||||
{{ restarting ? "Starte neu …" : "Jetzt neu starten" }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user