Merge Stufe 4a (#764): WebUI-Texte ueber Sprachschluessel
This commit is contained in:
@@ -233,16 +233,16 @@ function aktualisiereInstanzPlakette() {
|
||||
const res = await api(`/verwaltung/instanzen/${encodeURIComponent(aktive.id)}/start`, {
|
||||
method: "POST"
|
||||
});
|
||||
zeigeMeldung(res?.meldung || `Instanz '${aktive.name}' gestartet.`, "erfolg");
|
||||
zeigeMeldung(res?.meldung || t("header.instanceStarted", { name: aktive.name }), "erfolg");
|
||||
await aktualisiereInstanzenListe();
|
||||
if (window.location.hash) {
|
||||
window.dispatchEvent(new HashChangeEvent("hashchange"));
|
||||
}
|
||||
} catch (err) {
|
||||
if (err.lizenzFehlt) {
|
||||
zeigeMeldung("Start abgelehnt: Ohne gültige Lizenz startet keine Instanz (HTTP 402).", "gefahr", 6000);
|
||||
zeigeMeldung(t("header.startNoLicense"), "gefahr", 6000);
|
||||
} else {
|
||||
zeigeMeldung(`Start fehlgeschlagen: ${err.message}`, "gefahr");
|
||||
zeigeMeldung(t("header.startFailed", { error: err.message }), "gefahr");
|
||||
}
|
||||
startBtn.disabled = false;
|
||||
startBtn.textContent = t("header.startInstance");
|
||||
@@ -319,9 +319,11 @@ async function aktualisiereKopfStatus() {
|
||||
try {
|
||||
const status = await api("/status");
|
||||
if (kopfOpenRouter && status) {
|
||||
// #764: The field is apiReachable (StatusDto); isApiReachable never existed, so without
|
||||
// credits text this always said "offline".
|
||||
kopfOpenRouter.textContent = status.creditsText
|
||||
? `OpenRouter: ${status.creditsText}`
|
||||
: (status.isApiReachable ? "OpenRouter: OK" : "OpenRouter: offline");
|
||||
? t("header.openRouterCredits", { credits: status.creditsText })
|
||||
: (status.apiReachable ? t("header.openRouterOk") : t("header.openRouterOffline"));
|
||||
}
|
||||
} catch (err) {
|
||||
if (kopfOpenRouter) {
|
||||
|
||||
@@ -669,6 +669,59 @@
|
||||
"logs.empty": "Noch keine Protokolleinträge vorhanden.",
|
||||
|
||||
"settings.title": "Einstellungen & Systemarchitektur",
|
||||
"common.error": "Fehler",
|
||||
"common.errorWith": "Fehler: {error}",
|
||||
"header.instanceStarted": "Instanz '{name}' gestartet.",
|
||||
"header.startNoLicense": "Start abgelehnt: Ohne gültige Lizenz startet keine Instanz (HTTP 402).",
|
||||
"header.startFailed": "Start fehlgeschlagen: {error}",
|
||||
"header.openRouterCredits": "OpenRouter: {credits}",
|
||||
"header.openRouterOk": "OpenRouter: OK",
|
||||
"header.openRouterOffline": "OpenRouter: offline",
|
||||
"login.tokenRejected": "Kein gültiges Token. Bitte neu anmelden.",
|
||||
"backup.loadFailed": "Sicherungen konnten nicht geladen werden: {error}",
|
||||
"backup.ftpLoadFailed": "Einstellungen nicht ladbar: {error}",
|
||||
"info.agentEngine": "Agent-Engine",
|
||||
"info.scheduler": "Scanner / Planer",
|
||||
"info.apiOk": "OK",
|
||||
"info.apiOffline": "Offline",
|
||||
"info.credits": "Guthaben",
|
||||
"instances.starting": "'{name}' wird gestartet…",
|
||||
"instances.stopTitle": "Instanz anhalten",
|
||||
"instances.stopExplanation": "Das Anhalten von '{name}' fährt alle laufenden Agenten und Prozesse geordnet herunter.",
|
||||
"instances.instance": "Instanz",
|
||||
"instances.confirmLocked": "Bestätigung gesperrt: {seconds}s…",
|
||||
"instances.confirmUnlocked": "Entsperrt — bereit zur Bestätigung.",
|
||||
"instances.stopping": "Wird angehalten…",
|
||||
"instances.stopped": "'{name}' angehalten.",
|
||||
"instances.stopFailed": "Anhalten fehlgeschlagen: {error}",
|
||||
"logs.level.debug": "Debug",
|
||||
"logs.level.info": "Info",
|
||||
"logs.level.warning": "Warnung",
|
||||
"logs.level.error": "Fehler",
|
||||
"logs.level.critical": "Kritisch",
|
||||
"logs.live": "Live",
|
||||
"services.enabledMsg": "'{name}' aktiviert.",
|
||||
"services.disabledMsg": "'{name}' deaktiviert.",
|
||||
"services.deleteConfirm": "Dienst '{name}' ({id}) löschen?",
|
||||
"services.deleted": "Dienst '{name}' gelöscht.",
|
||||
"services.created": "Dienst '{name}' angelegt.",
|
||||
"services.namePlaceholder": "z. B. WebHookService",
|
||||
"services.typePlaceholder": "z. B. HTTP, TCP, Socket",
|
||||
"services.portPlaceholder": "z. B. 8081 (optional)",
|
||||
"tasks.loadError": "Fehler im Taskboard",
|
||||
"tasks.untitled": "Aufgabe {id}",
|
||||
"tasks.assignNewRun": "{name} (neuer Lauf)",
|
||||
"tasks.assignChatHistory": "{name} (Chatverlauf)",
|
||||
"tasks.assignHuman": "Mensch (kein Agent)",
|
||||
"tasks.chatHistoryNotice": "⚠ Wiederkehrende Aufgaben im Chatverlauf lassen Kontext und Kosten wachsen.",
|
||||
"tasks.scheduleValue": "Wert:",
|
||||
"tasks.timezone": "Zeitzone:",
|
||||
"tasks.acceptance": "Abnahmekriterien:",
|
||||
"agents.modelPlaceholder": "z. B. anthropic/claude-sonnet-4-5",
|
||||
"org.unitNamePlaceholder": "z. B. Marketing",
|
||||
"org.workspaceNamePlaceholder": "z. B. Artikelstamm",
|
||||
"org.protectedPathsPlaceholder": "z. B. prices, archive",
|
||||
"org.votersPlaceholder": "buchhaltung\nlogistik\nmarketing",
|
||||
"settings.updateCard": "Update",
|
||||
"settings.updateInstalled": "Installiert",
|
||||
"settings.updateLatest": "Neueste",
|
||||
|
||||
@@ -669,6 +669,59 @@
|
||||
"logs.empty": "No log messages yet.",
|
||||
|
||||
"settings.title": "Settings & System Architecture",
|
||||
"common.error": "Error",
|
||||
"common.errorWith": "Error: {error}",
|
||||
"header.instanceStarted": "Instance '{name}' started.",
|
||||
"header.startNoLicense": "Start refused: without a valid license no instance starts (HTTP 402).",
|
||||
"header.startFailed": "Start failed: {error}",
|
||||
"header.openRouterCredits": "OpenRouter: {credits}",
|
||||
"header.openRouterOk": "OpenRouter: OK",
|
||||
"header.openRouterOffline": "OpenRouter: offline",
|
||||
"login.tokenRejected": "No valid token. Please sign in again.",
|
||||
"backup.loadFailed": "Backups could not be loaded: {error}",
|
||||
"backup.ftpLoadFailed": "Settings could not be loaded: {error}",
|
||||
"info.agentEngine": "Agent engine",
|
||||
"info.scheduler": "Scanner / scheduler",
|
||||
"info.apiOk": "OK",
|
||||
"info.apiOffline": "Offline",
|
||||
"info.credits": "Credits",
|
||||
"instances.starting": "Starting '{name}'…",
|
||||
"instances.stopTitle": "Stop instance",
|
||||
"instances.stopExplanation": "Stopping instance '{name}' winds down all running agents and processes in order.",
|
||||
"instances.instance": "Instance",
|
||||
"instances.confirmLocked": "Confirmation locked: {seconds}s…",
|
||||
"instances.confirmUnlocked": "Unlocked — ready to confirm.",
|
||||
"instances.stopping": "Stopping…",
|
||||
"instances.stopped": "'{name}' stopped.",
|
||||
"instances.stopFailed": "Stop failed: {error}",
|
||||
"logs.level.debug": "Debug",
|
||||
"logs.level.info": "Info",
|
||||
"logs.level.warning": "Warning",
|
||||
"logs.level.error": "Error",
|
||||
"logs.level.critical": "Critical",
|
||||
"logs.live": "Live",
|
||||
"services.enabledMsg": "'{name}' enabled.",
|
||||
"services.disabledMsg": "'{name}' disabled.",
|
||||
"services.deleteConfirm": "Delete service '{name}' ({id})?",
|
||||
"services.deleted": "Service '{name}' deleted.",
|
||||
"services.created": "Service '{name}' created.",
|
||||
"services.namePlaceholder": "e.g. WebHookService",
|
||||
"services.typePlaceholder": "e.g. HTTP, TCP, Socket",
|
||||
"services.portPlaceholder": "e.g. 8081 (optional)",
|
||||
"tasks.loadError": "Taskboard error",
|
||||
"tasks.untitled": "Task {id}",
|
||||
"tasks.assignNewRun": "{name} (new run)",
|
||||
"tasks.assignChatHistory": "{name} (chat history)",
|
||||
"tasks.assignHuman": "Human (no agent)",
|
||||
"tasks.chatHistoryNotice": "⚠ Recurring tasks in the chat history make the context and the costs grow.",
|
||||
"tasks.scheduleValue": "Value:",
|
||||
"tasks.timezone": "Time zone:",
|
||||
"tasks.acceptance": "Acceptance criteria:",
|
||||
"agents.modelPlaceholder": "e.g. anthropic/claude-sonnet-4-5",
|
||||
"org.unitNamePlaceholder": "e.g. Marketing",
|
||||
"org.workspaceNamePlaceholder": "e.g. Article master",
|
||||
"org.protectedPathsPlaceholder": "e.g. prices, archive",
|
||||
"org.votersPlaceholder": "accounting\nlogistics\nmarketing",
|
||||
"settings.updateCard": "Update",
|
||||
"settings.updateInstalled": "Installed",
|
||||
"settings.updateLatest": "Latest",
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
//
|
||||
// Verwaltet das Zugangstoken im sessionStorage und kapselt fetch-Aufrufe.
|
||||
|
||||
import { t } from "./i18n.js";
|
||||
|
||||
export const TOKEN_SCHLUESSEL = "clawd.token";
|
||||
export const INSTANZ_SCHLUESSEL = "clawd.instanz";
|
||||
|
||||
@@ -145,7 +147,7 @@ export async function api(pfad, optionen = {}) {
|
||||
|
||||
if (antwort.status === 401) {
|
||||
meldeUnberechtigt();
|
||||
const fehler = new Error("Kein gültiges Token. Bitte neu anmelden.");
|
||||
const fehler = new Error(t("login.tokenRejected"));
|
||||
fehler.abgelehnt = true;
|
||||
fehler.status = 401;
|
||||
throw fehler;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// Guide rule 3.1: foreign text is never HTML. No innerHTML anywhere in the tree.
|
||||
|
||||
import { t } from "./i18n.js";
|
||||
import { t, currentLanguage } from "./i18n.js";
|
||||
|
||||
const SVG_NS = "http://www.w3.org/2000/svg";
|
||||
|
||||
@@ -256,11 +256,19 @@ export function erstelleModal(titel, inhalt, aktionen = [], optionen = {}) {
|
||||
* @param {string|Date|number|null} wert
|
||||
* @returns {string}
|
||||
*/
|
||||
/**
|
||||
* #764: The locale of the active language. Dates were always formatted "de-DE", also in the
|
||||
* English interface. en-GB rather than en-US: day before month, like the German format.
|
||||
*/
|
||||
function locale() {
|
||||
return currentLanguage() === "de" ? "de-DE" : "en-GB";
|
||||
}
|
||||
|
||||
export function formatiereZeit(wert) {
|
||||
if (!wert) return "—";
|
||||
const d = wert instanceof Date ? wert : new Date(wert);
|
||||
if (isNaN(d.getTime())) return String(wert);
|
||||
return d.toLocaleTimeString("de-DE", { hour: "2-digit", minute: "2-digit", second: "2-digit" });
|
||||
return d.toLocaleTimeString(locale(), { hour: "2-digit", minute: "2-digit", second: "2-digit" });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,7 +280,7 @@ export function formatiereDatumZeit(wert) {
|
||||
if (!wert) return "—";
|
||||
const d = wert instanceof Date ? wert : new Date(wert);
|
||||
if (isNaN(d.getTime())) return String(wert);
|
||||
return d.toLocaleString("de-DE", {
|
||||
return d.toLocaleString(locale(), {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
|
||||
@@ -389,7 +389,7 @@ function oeffneNeuerAgentDialog() {
|
||||
const modellFeld = erstelleElement("input", {
|
||||
type: "text",
|
||||
required: true,
|
||||
placeholder: "z.B. anthropic/claude-3.5-sonnet",
|
||||
placeholder: t("agents.modelPlaceholder"),
|
||||
value: "anthropic/claude-3.5-sonnet",
|
||||
id: "neu-agent-modell"
|
||||
});
|
||||
|
||||
@@ -187,8 +187,8 @@ export async function rendereSicherung() {
|
||||
inhaltBereich.replaceChildren(erstelleKarte(t("backup.existingBackups", { count: backups.length }), [tabelle]));
|
||||
} catch (err) {
|
||||
inhaltBereich.replaceChildren(
|
||||
erstelleKarte("Fehler", [
|
||||
erstelleElement("p", { klasse: "fehler-meldung", text: `Sicherungen konnten nicht geladen werden: ${err.message}` })
|
||||
erstelleKarte(t("common.error"), [
|
||||
erstelleElement("p", { klasse: "fehler-meldung", text: t("backup.loadFailed", { error: err.message }) })
|
||||
])
|
||||
);
|
||||
}
|
||||
@@ -426,7 +426,7 @@ async function rendereFtp(bereich) {
|
||||
stand = await api("/verwaltung/sicherung/ftp");
|
||||
} catch (err) {
|
||||
bereich.replaceChildren(erstelleKarte(t("backup.ftpTitle"), [
|
||||
erstelleElement("p", { klasse: "fehler-meldung", text: `Einstellungen nicht ladbar: ${err.message}` })
|
||||
erstelleElement("p", { klasse: "fehler-meldung", text: t("backup.ftpLoadFailed", { error: err.message }) })
|
||||
]));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ async function ladeAgenten(gewuenschteId = null) {
|
||||
agentenSelector.value = zielId;
|
||||
await waehleAgent(zielId);
|
||||
} catch (err) {
|
||||
zeigeMeldung(`Fehler: ${err.message}`, "gefahr");
|
||||
zeigeMeldung(t("common.errorWith", { error: err.message }), "gefahr");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,9 +64,9 @@ export async function rendereInfo() {
|
||||
// 2. Teilsysteme
|
||||
const dlSysteme = erstelleElement("dl", { klasse: "datenliste" });
|
||||
dlSysteme.append(
|
||||
erstelleElement("dt", { text: "Agent Engine" }),
|
||||
erstelleElement("dt", { text: t("info.agentEngine") }),
|
||||
erstelleElement("dd", {}, erstellePlakette(info.engineActive ? (t("status.running")) : (t("status.stopped")), info.engineActive ? "erfolg" : "neutral")),
|
||||
erstelleElement("dt", { text: "Scanner / Scheduler" }),
|
||||
erstelleElement("dt", { text: t("info.scheduler") }),
|
||||
erstelleElement("dd", {}, erstellePlakette(info.schedulerActive ? (t("status.running")) : (t("status.stopped")), info.schedulerActive ? "erfolg" : "neutral")),
|
||||
erstelleElement("dt", { text: t("nav.staging") }),
|
||||
erstelleElement("dd", {}, erstellePlakette(info.stagingActive ? (t("status.running")) : (t("status.stopped")), info.stagingActive ? "erfolg" : "neutral")),
|
||||
@@ -81,10 +81,10 @@ export async function rendereInfo() {
|
||||
if (status) {
|
||||
dlStatus.append(
|
||||
erstelleElement("dt", { text: "API" }),
|
||||
erstelleElement("dd", {}, erstellePlakette(status.isApiReachable ? "OK" : "Offline", status.isApiReachable ? "erfolg" : "gefahr")),
|
||||
erstelleElement("dd", {}, erstellePlakette(status.apiReachable ? t("info.apiOk") : t("info.apiOffline"), status.apiReachable ? "erfolg" : "gefahr")),
|
||||
erstelleElement("dt", { text: t("common.status") }),
|
||||
erstelleElement("dd", { text: status.statusText || "—" }),
|
||||
erstelleElement("dt", { text: "Credits" }),
|
||||
erstelleElement("dt", { text: t("info.credits") }),
|
||||
erstelleElement("dd", {}, erstelleElement("strong", { text: status.creditsText || "—" }))
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -188,7 +188,7 @@ async function ladeInstanzen(istHintergrund = false) {
|
||||
} catch (err) {
|
||||
if (!istHintergrund) {
|
||||
raster.replaceChildren(
|
||||
erstelleElement("div", { klasse: "fehler-zentriert", text: `Error: ${err.message}` })
|
||||
erstelleElement("div", { klasse: "fehler-zentriert", text: t("common.errorWith", { error: err.message }) })
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -199,16 +199,16 @@ async function starteInstanz(instanz) {
|
||||
const antwort = await api(`/verwaltung/instanzen/${encodeURIComponent(instanz.id)}/start`, {
|
||||
method: "POST"
|
||||
});
|
||||
zeigeMeldung(antwort?.meldung || `Starting '${instanz.name}'…`, "erfolg");
|
||||
zeigeMeldung(antwort?.meldung || t("instances.starting", { name: instanz.name }), "erfolg");
|
||||
if (!holeAktiveInstanz()) {
|
||||
setzeAktiveInstanz(instanz.id);
|
||||
}
|
||||
await ladeInstanzen();
|
||||
} catch (err) {
|
||||
if (err.lizenzFehlt) {
|
||||
zeigeMeldung("License required (HTTP 402).", "gefahr", 6000);
|
||||
zeigeMeldung(t("header.startNoLicense"), "gefahr", 6000);
|
||||
} else {
|
||||
zeigeMeldung(`Failed to start: ${err.message}`, "gefahr");
|
||||
zeigeMeldung(t("header.startFailed", { error: err.message }), "gefahr");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -228,16 +228,16 @@ function oeffneSicherheitsStoppDialog(instanz) {
|
||||
"h3",
|
||||
{},
|
||||
erstelleIcon(PFADE.ausrufezeichen, 18),
|
||||
erstelleElement("span", { text: " Stop Instance" })
|
||||
erstelleElement("span", { text: ` ${t("instances.stopTitle")}` })
|
||||
);
|
||||
const boxText1 = erstelleElement("p", {
|
||||
text: `Stopping instance '${instanz.name}' will gracefully shut down all active agents and processes.`
|
||||
text: t("instances.stopExplanation", { name: instanz.name })
|
||||
});
|
||||
sicherheitsBox.append(boxTitel, boxText1);
|
||||
|
||||
const dl = erstelleElement("dl", { klasse: "datenliste" });
|
||||
dl.append(
|
||||
erstelleElement("dt", { text: "Instance" }),
|
||||
erstelleElement("dt", { text: t("instances.instance") }),
|
||||
erstelleElement("dd", {}, erstelleElement("strong", { text: instanz.name })),
|
||||
erstelleElement("dt", { text: "ID" }),
|
||||
erstelleElement("dd", {}, erstelleElement("code", { text: instanz.id })),
|
||||
@@ -247,7 +247,7 @@ function oeffneSicherheitsStoppDialog(instanz) {
|
||||
|
||||
const countdownBox = erstelleElement("div", {
|
||||
klasse: "sicherheits-countdown",
|
||||
text: `Confirmation locked: ${verbleibend}s…`
|
||||
text: t("instances.confirmLocked", { seconds: verbleibend })
|
||||
});
|
||||
|
||||
inhalt.append(sicherheitsBox, dl, countdownBox);
|
||||
@@ -287,7 +287,7 @@ function oeffneSicherheitsStoppDialog(instanz) {
|
||||
timerId = setInterval(() => {
|
||||
verbleibend--;
|
||||
if (verbleibend > 0) {
|
||||
countdownBox.textContent = `Confirmation locked: ${verbleibend}s…`;
|
||||
countdownBox.textContent = t("instances.confirmLocked", { seconds: verbleibend });
|
||||
const textSpan = anhaltenBtn.querySelector("span");
|
||||
if (textSpan) textSpan.textContent = ` ${t("instances.stop")} (${verbleibend}s)`;
|
||||
} else {
|
||||
@@ -297,7 +297,7 @@ function oeffneSicherheitsStoppDialog(instanz) {
|
||||
const textSpan = anhaltenBtn.querySelector("span");
|
||||
if (textSpan) textSpan.textContent = ` ${t("instances.stop")}`;
|
||||
countdownBox.className = "sicherheits-countdown abgelaufen";
|
||||
countdownBox.textContent = "Unlocked — confirmation ready.";
|
||||
countdownBox.textContent = t("instances.confirmUnlocked");
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
@@ -305,17 +305,17 @@ function oeffneSicherheitsStoppDialog(instanz) {
|
||||
if (verbleibend > 0) return;
|
||||
anhaltenBtn.disabled = true;
|
||||
const textSpan = anhaltenBtn.querySelector("span");
|
||||
if (textSpan) textSpan.textContent = " Stopping…";
|
||||
if (textSpan) textSpan.textContent = ` ${t("instances.stopping")}`;
|
||||
|
||||
try {
|
||||
const antwort = await api(`/verwaltung/instanzen/${encodeURIComponent(instanz.id)}/stop`, {
|
||||
method: "POST"
|
||||
});
|
||||
modal.schliessen();
|
||||
zeigeMeldung(antwort?.meldung || `'${instanz.name}' stopped.`, "info");
|
||||
zeigeMeldung(antwort?.meldung || t("instances.stopped", { name: instanz.name }), "info");
|
||||
await ladeInstanzen();
|
||||
} catch (err) {
|
||||
zeigeMeldung(`Stop failed: ${err.message}`, "gefahr");
|
||||
zeigeMeldung(t("instances.stopFailed", { error: err.message }), "gefahr");
|
||||
anhaltenBtn.disabled = false;
|
||||
if (textSpan) textSpan.textContent = ` ${t("instances.stop")}`;
|
||||
}
|
||||
|
||||
@@ -70,11 +70,11 @@ export async function rendereProtokoll() {
|
||||
});
|
||||
const levelOptionen = [
|
||||
["All", t("common.all")],
|
||||
["Debug", "Debug"],
|
||||
["Information", "Info"],
|
||||
["Warning", "Warning"],
|
||||
["Error", "Error"],
|
||||
["Critical", "Critical"]
|
||||
["Debug", t("logs.level.debug")],
|
||||
["Information", t("logs.level.info")],
|
||||
["Warning", t("logs.level.warning")],
|
||||
["Error", t("logs.level.error")],
|
||||
["Critical", t("logs.level.critical")]
|
||||
];
|
||||
for (const [val, label] of levelOptionen) {
|
||||
levelSelect.append(erstelleElement("option", { value: val, text: label }));
|
||||
@@ -252,7 +252,7 @@ function togglePause() {
|
||||
|
||||
function aktualisiereStatus(offen, text = null) {
|
||||
if (!streamStatusPlakette) return;
|
||||
const statusT = text || (offen ? "Live" : "—");
|
||||
const statusT = text || (offen ? t("logs.live") : "—");
|
||||
const art = offen ? "erfolg" : "neutral";
|
||||
const neuePlakette = erstellePlakette(statusT, art);
|
||||
streamStatusPlakette.replaceWith(neuePlakette);
|
||||
|
||||
@@ -270,7 +270,7 @@ function select(sel) {
|
||||
|
||||
function openCreateUnit(parentId = null) {
|
||||
const id = erstelleElement("input", { type: "text", placeholder: "marketing", required: true });
|
||||
const name = erstelleElement("input", { type: "text", placeholder: "Marketing", required: true });
|
||||
const name = erstelleElement("input", { type: "text", placeholder: t("org.unitNamePlaceholder"), required: true });
|
||||
const parent = unitOptions(erstelleElement("select"), parentId);
|
||||
const goal = erstelleElement("textarea", { rows: 2 });
|
||||
|
||||
@@ -668,7 +668,7 @@ function votesCard(unit) {
|
||||
const current = unit.votes;
|
||||
const ops = erstelleElement("textarea", { rows: 2, placeholder: "Database.insert" });
|
||||
ops.value = (current?.operations ?? []).join("\n");
|
||||
const voters = erstelleElement("textarea", { rows: 3, placeholder: "accounting\nlogistics\nmarketing" });
|
||||
const voters = erstelleElement("textarea", { rows: 3, placeholder: t("org.votersPlaceholder") });
|
||||
voters.value = (current?.voters ?? []).join("\n");
|
||||
const number = (value, min) => erstelleElement("input", { type: "number", min: String(min), step: "1", value: String(value) });
|
||||
const approveAt = number(current?.approveAt ?? 3, 1);
|
||||
@@ -944,7 +944,7 @@ function unitWorkspaceCard(unit) {
|
||||
|
||||
function openCreateWorkspace() {
|
||||
const id = erstelleElement("input", { type: "text", placeholder: "articles", required: true });
|
||||
const name = erstelleElement("input", { type: "text", placeholder: "Article master", required: true });
|
||||
const name = erstelleElement("input", { type: "text", placeholder: t("org.workspaceNamePlaceholder"), required: true });
|
||||
const purpose = erstelleElement("textarea", { rows: 2 });
|
||||
const owner = unitOptions(erstelleElement("select"), null, new Set(), t("org.noOwner"));
|
||||
|
||||
@@ -982,7 +982,7 @@ function workspacePanel(workspace) {
|
||||
const name = erstelleElement("input", { type: "text", value: workspace.name });
|
||||
const purpose = erstelleElement("textarea", { rows: 2 });
|
||||
purpose.value = workspace.purpose ?? "";
|
||||
const protectedPaths = erstelleElement("input", { type: "text", value: workspace.protectedPaths.join(", "), placeholder: "prices, archive" });
|
||||
const protectedPaths = erstelleElement("input", { type: "text", value: workspace.protectedPaths.join(", "), placeholder: t("org.protectedPathsPlaceholder") });
|
||||
|
||||
const general = erstelleKarte(workspace.name, [
|
||||
erstelleElement("p", { klasse: "gedaempft text-klein",
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
// ClawdDotNet — Platzhalter-Ansichten für noch nicht freigegebene Kern-Endpunkte
|
||||
//
|
||||
// Leitfaden Abschnitt 7: Sicherung, Einstellungen und Agenten-Chats (Analyse).
|
||||
|
||||
import { erstelleElement, erstelleKarte, erstelleIcon, PFADE } from "../modules/dom.js";
|
||||
|
||||
export function rendereSicherung() {
|
||||
const container = document.getElementById("ansicht-inhalt");
|
||||
if (!container) return;
|
||||
container.replaceChildren();
|
||||
|
||||
const layout = erstelleElement("div", { klasse: "platzhalter-ansicht" });
|
||||
layout.append(erstelleElement("h1", { text: "Datensicherung & Wiederherstellung" }));
|
||||
|
||||
const karte = erstelleKarte("In Vorbereitung", [
|
||||
erstelleElement("p", {
|
||||
klasse: "gedaempft",
|
||||
text: "Die API-Endpunkte für die automatisierte Sicherung und Rücksicherung über das WebUI befinden sich in Arbeit."
|
||||
}),
|
||||
erstelleElement("p", {
|
||||
klasse: "hinweis",
|
||||
text: "Bitte verwende für die Sicherung von Instanzen aktuell die Desktop-Oberfläche von ClawdDotNet."
|
||||
})
|
||||
]);
|
||||
|
||||
layout.append(karte);
|
||||
container.append(layout);
|
||||
}
|
||||
|
||||
|
||||
export function rendereAgentenChats() {
|
||||
const container = document.getElementById("ansicht-inhalt");
|
||||
if (!container) return;
|
||||
container.replaceChildren();
|
||||
|
||||
const layout = erstelleElement("div", { klasse: "platzhalter-ansicht" });
|
||||
layout.append(erstelleElement("h1", { text: "Agenten-Kommunikation" }));
|
||||
|
||||
const karte = erstelleKarte("Analyse: Interne Agenten-Chats", [
|
||||
erstelleElement("p", {
|
||||
klasse: "gedaempft",
|
||||
text: "Die Protokollierung und Auswertung der direkten Kommunikation zwischen zwei Agenten (A2A) wird mit Vorhaben #208 bereitgestellt."
|
||||
}),
|
||||
erstelleElement("p", {
|
||||
klasse: "hinweis",
|
||||
text: "Direkte Chats mit Agenten können im Bereich 'Chat' geführt werden."
|
||||
})
|
||||
]);
|
||||
|
||||
layout.append(karte);
|
||||
container.append(layout);
|
||||
}
|
||||
@@ -111,10 +111,10 @@ async function ladeDienste() {
|
||||
method: "PUT"
|
||||
});
|
||||
s.enabled = aktiv;
|
||||
zeigeMeldung(`'${s.name}' ${aktiv ? "enabled" : "disabled"}.`, "info");
|
||||
zeigeMeldung(t(aktiv ? "services.enabledMsg" : "services.disabledMsg", { name: s.name }), "info");
|
||||
} catch (err) {
|
||||
e.target.checked = !aktiv;
|
||||
zeigeMeldung(`Error: ${err.message}`, "gefahr");
|
||||
zeigeMeldung(t("common.errorWith", { error: err.message }), "gefahr");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -152,14 +152,14 @@ async function ladeDienste() {
|
||||
}
|
||||
|
||||
async function loescheDienst(s) {
|
||||
if (!confirm(`Delete service '${s.name}' (${s.id})?`)) return;
|
||||
if (!confirm(t("services.deleteConfirm", { name: s.name, id: s.id }))) return;
|
||||
|
||||
try {
|
||||
await api(`/services/${encodeURIComponent(s.id)}`, { method: "DELETE" });
|
||||
zeigeMeldung(`Service '${s.name}' deleted.`, "info");
|
||||
zeigeMeldung(t("services.deleted", { name: s.name }), "info");
|
||||
await ladeDienste();
|
||||
} catch (err) {
|
||||
zeigeMeldung(`Failed: ${err.message}`, "gefahr");
|
||||
zeigeMeldung(t("common.errorWith", { error: err.message }), "gefahr");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,20 +169,20 @@ function oeffneNeuerDienstDialog() {
|
||||
const nameFeld = erstelleElement("input", {
|
||||
type: "text",
|
||||
required: true,
|
||||
placeholder: "e.g. WebHookService"
|
||||
placeholder: t("services.namePlaceholder")
|
||||
});
|
||||
|
||||
const typFeld = erstelleElement("input", {
|
||||
type: "text",
|
||||
required: true,
|
||||
placeholder: "e.g. HTTP, TCP, Socket"
|
||||
placeholder: t("services.typePlaceholder")
|
||||
});
|
||||
|
||||
const portFeld = erstelleElement("input", {
|
||||
type: "number",
|
||||
min: "1",
|
||||
max: "65535",
|
||||
placeholder: "e.g. 8081 (optional)"
|
||||
placeholder: t("services.portPlaceholder")
|
||||
});
|
||||
|
||||
const descFeld = erstelleElement("textarea", {
|
||||
@@ -231,10 +231,10 @@ function oeffneNeuerDienstDialog() {
|
||||
}
|
||||
});
|
||||
modal.schliessen();
|
||||
zeigeMeldung(`Service '${nameFeld.value.trim()}' created.`, "erfolg");
|
||||
zeigeMeldung(t("services.created", { name: nameFeld.value.trim() }), "erfolg");
|
||||
await ladeDienste();
|
||||
} catch (err) {
|
||||
zeigeMeldung(`Error: ${err.message}`, "gefahr");
|
||||
zeigeMeldung(t("common.errorWith", { error: err.message }), "gefahr");
|
||||
} finally {
|
||||
anlegenBtn.disabled = false;
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ async function ladeTaskboard() {
|
||||
container.append(raster);
|
||||
} catch (err) {
|
||||
container.replaceChildren(
|
||||
erstelleKarte("Taskboard Error", [
|
||||
erstelleKarte(t("tasks.loadError"), [
|
||||
erstelleElement("p", { klasse: "gedaempft", text: err.message })
|
||||
])
|
||||
);
|
||||
@@ -343,7 +343,7 @@ function erstelleAufgabenKarte(task) {
|
||||
);
|
||||
zeilen.push(aktionen);
|
||||
|
||||
return erstelleKarte(task.title || `Task ${task.id}`, zeilen);
|
||||
return erstelleKarte(task.title || t("tasks.untitled", { id: task.id }), zeilen);
|
||||
}
|
||||
|
||||
async function fuehreAus(task) {
|
||||
@@ -352,7 +352,7 @@ async function fuehreAus(task) {
|
||||
zeigeMeldung(res?.message || t("tasks.runTriggered"), "erfolg");
|
||||
setTimeout(ladeTaskboard, 1500);
|
||||
} catch (err) {
|
||||
zeigeMeldung(`Error: ${err.message}`, "gefahr");
|
||||
zeigeMeldung(t("common.errorWith", { error: err.message }), "gefahr");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,7 +362,7 @@ async function setzeAktiv(task, aktiv) {
|
||||
zeigeMeldung(res?.message || (aktiv ? t("tasks.resume") : t("tasks.pause")), "info");
|
||||
await ladeTaskboard();
|
||||
} catch (err) {
|
||||
zeigeMeldung(`Error: ${err.message}`, "gefahr");
|
||||
zeigeMeldung(t("common.errorWith", { error: err.message }), "gefahr");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,11 +384,11 @@ async function oeffneAufgabenDialog(task) {
|
||||
const zuordnung = erstelleElement("select", { required: true });
|
||||
for (const a of agenten) {
|
||||
zuordnung.append(
|
||||
erstelleElement("option", { value: `@new:${a.agentId}`, text: `${a.displayName} (New Run)` }),
|
||||
erstelleElement("option", { value: `@${a.agentId}`, text: `${a.displayName} (Chat History)` })
|
||||
erstelleElement("option", { value: `@new:${a.agentId}`, text: t("tasks.assignNewRun", { name: a.displayName }) }),
|
||||
erstelleElement("option", { value: `@${a.agentId}`, text: t("tasks.assignChatHistory", { name: a.displayName }) })
|
||||
);
|
||||
}
|
||||
zuordnung.append(erstelleElement("option", { value: "@human", text: "Human (No Agent)" }));
|
||||
zuordnung.append(erstelleElement("option", { value: "@human", text: t("tasks.assignHuman") }));
|
||||
if (task?.assignee && ![...zuordnung.options].some((o) => o.value === task.assignee)) {
|
||||
zuordnung.append(erstelleElement("option", { value: task.assignee, text: task.assignee }));
|
||||
}
|
||||
@@ -397,7 +397,7 @@ async function oeffneAufgabenDialog(task) {
|
||||
const terminArt = erstelleElement("select");
|
||||
terminArt.append(
|
||||
erstelleElement("option", { value: "", text: t("tasks.scheduleNone") }),
|
||||
erstelleElement("option", { value: "cron", text: "Cron" }),
|
||||
erstelleElement("option", { value: "cron", text: t("tasks.scheduleCron") }),
|
||||
erstelleElement("option", { value: "every", text: t("tasks.scheduleInterval") }),
|
||||
erstelleElement("option", { value: "at", text: t("tasks.scheduleAt") })
|
||||
);
|
||||
@@ -439,7 +439,7 @@ async function oeffneAufgabenDialog(task) {
|
||||
const wiederkehrend = terminArt.value === "cron" || terminArt.value === "every";
|
||||
const imVerlauf = zuordnung.value.startsWith("@") && !zuordnung.value.startsWith("@new") && zuordnung.value !== "@human";
|
||||
hinweis.hidden = !(wiederkehrend && imVerlauf);
|
||||
hinweis.textContent = "⚠ Notice: Running recurring tasks in chat history increases context and costs.";
|
||||
hinweis.textContent = t("tasks.chatHistoryNotice");
|
||||
|
||||
const ohneTermin = terminArt.value === "";
|
||||
terminWert.disabled = ohneTermin;
|
||||
@@ -459,9 +459,9 @@ async function oeffneAufgabenDialog(task) {
|
||||
erstelleElement("label", { text: t("tasks.taskMessage") + ":" }), beschreibung,
|
||||
erstelleElement("label", { text: t("tasks.agent") + ":" }), zuordnung,
|
||||
erstelleElement("label", { text: t("tasks.scheduleType") + ":" }), terminArt,
|
||||
erstelleElement("label", { text: "Value:" }), terminWert,
|
||||
erstelleElement("label", { text: "Timezone:" }), zeitzone,
|
||||
erstelleElement("label", { text: "Acceptance Criteria:" }), abnahme,
|
||||
erstelleElement("label", { text: t("tasks.scheduleValue") }), terminWert,
|
||||
erstelleElement("label", { text: t("tasks.timezone") }), zeitzone,
|
||||
erstelleElement("label", { text: t("tasks.acceptance") }), abnahme,
|
||||
erstelleElement("label", { text: t("tasks.parent") + ":" }), eltern,
|
||||
erstelleElement("label", { text: t("tasks.fillBy") + ":", title: t("tasks.fillByHint") }), fuellBis,
|
||||
erstelleElement("label", { text: t("tasks.estimateUsd") + ":" }), schaetzung,
|
||||
@@ -513,7 +513,7 @@ async function oeffneAufgabenDialog(task) {
|
||||
zeigeMeldung(text, "erfolg");
|
||||
await ladeTaskboard();
|
||||
} catch (err) {
|
||||
zeigeMeldung(`Error: ${err.message}`, "gefahr");
|
||||
zeigeMeldung(t("common.errorWith", { error: err.message }), "gefahr");
|
||||
} finally {
|
||||
speichern.disabled = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user