Pools: Anzeigename von Pool-ID (UUID-Ordner) getrennt + Umbenennen; API-Keys in Keychain/Keyring, Datei-Fallback nur nach Rückfrage
This commit is contained in:
@@ -12,6 +12,7 @@ interface Project {
|
||||
}
|
||||
|
||||
interface Pool {
|
||||
id: string;
|
||||
name: string;
|
||||
credentialType: string;
|
||||
hasCredentials: boolean;
|
||||
@@ -19,10 +20,16 @@ interface Pool {
|
||||
|
||||
function poolReady(p: Project): boolean {
|
||||
if (!p.pool) return false;
|
||||
const pool = pools.value.find((x) => x.name === p.pool);
|
||||
const pool = pools.value.find((x) => x.id === p.pool);
|
||||
return pool !== undefined && pool.hasCredentials;
|
||||
}
|
||||
|
||||
// Projekt-Configs tragen die Pool-ID; angezeigt wird der Name aus pool.json.
|
||||
function poolName(id: string | null): string | null {
|
||||
if (!id) return null;
|
||||
return pools.value.find((x) => x.id === id)?.name ?? id;
|
||||
}
|
||||
|
||||
function startBlockedReason(p: Project): string | undefined {
|
||||
if (poolReady(p)) return undefined;
|
||||
return p.pool ? "projects.needsKey" : "projects.needsPool";
|
||||
@@ -32,6 +39,35 @@ const projects = ref<Project[]>([]);
|
||||
const pools = ref<Pool[]>([]);
|
||||
const error = ref("");
|
||||
|
||||
// data-URLs pro (Projekt, Icon-Pfad) — Fehlversuche werden als "" gemerkt,
|
||||
// damit der 3s-Poll nicht dieselbe Fehlermeldung wiederholt.
|
||||
const icons = ref<Record<string, string>>({});
|
||||
|
||||
function iconKey(p: Project): string | null {
|
||||
return p.terminal.icon ? `${p.name}:${p.terminal.icon}` : null;
|
||||
}
|
||||
|
||||
function projIcon(p: Project): string | undefined {
|
||||
const key = iconKey(p);
|
||||
return key ? icons.value[key] || undefined : undefined;
|
||||
}
|
||||
|
||||
async function loadIcons() {
|
||||
for (const p of projects.value) {
|
||||
const key = iconKey(p);
|
||||
if (!key || key in icons.value) continue;
|
||||
try {
|
||||
const data = await invoke<string | null>("project_icon", {
|
||||
project: p.name,
|
||||
});
|
||||
icons.value[key] = data ?? "";
|
||||
} catch (e) {
|
||||
error.value = String(e);
|
||||
icons.value[key] = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function refresh() {
|
||||
try {
|
||||
projects.value = await invoke<Project[]>("list_projects");
|
||||
@@ -40,6 +76,7 @@ async function refresh() {
|
||||
} catch (e) {
|
||||
error.value = String(e);
|
||||
}
|
||||
await loadIcons();
|
||||
}
|
||||
|
||||
async function stop(project: Project) {
|
||||
@@ -103,6 +140,14 @@ const THEME_NAMES: [string, string][] = [
|
||||
["solarized-dark", "Solarized Dark"],
|
||||
["gruvbox", "Gruvbox"],
|
||||
["one-dark", "One Dark"],
|
||||
["nord", "Nord"],
|
||||
["tokyo-night", "Tokyo Night"],
|
||||
["monokai", "Monokai"],
|
||||
["rose-pine", "Rosé Pine"],
|
||||
["everforest", "Everforest"],
|
||||
["solarized-light", "Solarized Light"],
|
||||
["catppuccin-latte", "Catppuccin Latte"],
|
||||
["one-light", "One Light"],
|
||||
];
|
||||
|
||||
interface TerminalSettings {
|
||||
@@ -292,13 +337,16 @@ onUnmounted(() => window.clearInterval(timer));
|
||||
<span class="dot" :class="{ on: p.running }"></span>
|
||||
</td>
|
||||
<td class="cell-name">
|
||||
<strong>{{ p.name }}</strong>
|
||||
<span class="name-row">
|
||||
<img v-if="projIcon(p)" class="proj-icon" :src="projIcon(p)" />
|
||||
<strong>{{ p.name }}</strong>
|
||||
</span>
|
||||
<small>{{ p.path }}</small>
|
||||
</td>
|
||||
<td>
|
||||
<select :value="p.pool ?? ''" @change="assign(p, $event)">
|
||||
<option value="" disabled>{{ $t("projects.noPool") }}</option>
|
||||
<option v-for="pool in pools" :key="pool.name" :value="pool.name">
|
||||
<option v-for="pool in pools" :key="pool.id" :value="pool.id">
|
||||
{{ pool.name }}
|
||||
</option>
|
||||
</select>
|
||||
@@ -349,7 +397,7 @@ onUnmounted(() => window.clearInterval(timer));
|
||||
{{ $t("projects.pool") }}
|
||||
<select v-model="wizard.pool">
|
||||
<option value="">{{ $t("projects.noPool") }}</option>
|
||||
<option v-for="pool in pools" :key="pool.name" :value="pool.name">
|
||||
<option v-for="pool in pools" :key="pool.id" :value="pool.id">
|
||||
{{ pool.name }}
|
||||
</option>
|
||||
</select>
|
||||
@@ -493,9 +541,9 @@ onUnmounted(() => window.clearInterval(timer));
|
||||
<h3>{{ $t("projects.stillRunning", { name: pending.name }) }}</h3>
|
||||
<p>{{ $t("projects.poolChangeSaved") }}</p>
|
||||
<div class="pools">
|
||||
<span class="chip">{{ pending.from ?? $t("projects.noPoolAssigned") }}</span>
|
||||
<span class="chip">{{ poolName(pending.from) ?? $t("projects.noPoolAssigned") }}</span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="chip new">{{ pending.to }}</span>
|
||||
<span class="chip new">{{ poolName(pending.to) }}</span>
|
||||
</div>
|
||||
<p class="hint">{{ $t("projects.restartHint") }}</p>
|
||||
<div class="actions">
|
||||
|
||||
Reference in New Issue
Block a user