ken_nogi/NodeJS/postfixConsole_org/public/app.js
Kenichiro NOGI 88a402ce0f up
2026-07-10 18:13:30 +09:00

221 lines
7.1 KiB
JavaScript

const statusEl = document.getElementById("status");
const loginPanelEl = document.getElementById("loginPanel");
const appPanelEl = document.getElementById("appPanel");
const loginFormEl = document.getElementById("loginForm");
const passwordInputEl = document.getElementById("passwordInput");
const postfixInfoEl = document.getElementById("postfixInfo");
const postfixFileSelectEl = document.getElementById("postfixFileSelect");
const postfixConfigInputEl = document.getElementById("postfixConfigInput");
const logInfoEl = document.getElementById("logInfo");
const logOutputEl = document.getElementById("logOutput");
const reloadLogButton = document.getElementById("reloadLog");
const reloadPostfixConfigButton = document.getElementById("reloadPostfixConfig");
const savePostfixConfigButton = document.getElementById("savePostfixConfig");
const logoutButton = document.getElementById("logoutButton");
let postfixSettings = [];
function setStatus(message, isError = false) {
statusEl.textContent = message;
statusEl.classList.toggle("error", isError);
}
function setAuthenticatedView(isAuthenticated) {
loginPanelEl.classList.toggle("app-hidden", isAuthenticated);
appPanelEl.classList.toggle("app-hidden", !isAuthenticated);
}
async function checkAuthStatus() {
const response = await fetch("/api/auth/status");
const data = await response.json();
return Boolean(data.authenticated);
}
async function login(password) {
const response = await fetch("/api/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ password }),
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.message || "ログインに失敗しました。");
}
}
async function logout() {
const response = await fetch("/api/auth/logout", {
method: "POST",
});
await response.json();
}
async function loadPostfixSettingList() {
const response = await fetch("/api/postfix-settings");
const data = await response.json();
if (!response.ok) {
throw new Error(data.message || "Postfix設定一覧の取得に失敗しました。");
}
postfixSettings = data.items;
postfixFileSelectEl.innerHTML = "";
for (const item of postfixSettings) {
const option = document.createElement("option");
option.value = item.id;
const state = item.readError
? " (読込不可)"
: (item.exists ? "" : " (未作成)");
option.textContent = `${item.label}${state}`;
postfixFileSelectEl.appendChild(option);
}
if (postfixSettings.length > 0) {
const preferred = postfixSettings.find((item) => !item.readError) || postfixSettings[0];
postfixFileSelectEl.value = preferred.id;
}
postfixInfoEl.textContent = `設定ディレクトリ: ${data.baseDir} / 管理対象: ${postfixSettings.length}`;
}
async function loadPostfixSettingContent() {
const id = postfixFileSelectEl.value;
if (!id) {
postfixConfigInputEl.value = "";
return;
}
const selected = postfixSettings.find((item) => item.id === id);
if (selected?.readError) {
throw new Error(`${selected.label}: ${selected.readError.message} (code: ${selected.readError.code})`);
}
const response = await fetch(`/api/postfix-settings/${encodeURIComponent(id)}`);
const data = await response.json();
if (!response.ok) {
throw new Error(data.message || "設定ファイルの読み込みに失敗しました。");
}
postfixConfigInputEl.value = data.content;
postfixInfoEl.textContent = `編集中: ${data.label} / ファイル: ${data.filePath} / 行数: ${data.lines}`;
}
async function savePostfixSettingContent() {
const id = postfixFileSelectEl.value;
if (!id) {
throw new Error("保存対象の設定ファイルが未選択です。");
}
const response = await fetch(`/api/postfix-settings/${encodeURIComponent(id)}`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ content: postfixConfigInputEl.value }),
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.message || "設定ファイルの保存に失敗しました。");
}
setStatus(`保存しました: ${data.filePath}`);
await loadPostfixSettingList();
postfixFileSelectEl.value = id;
await loadPostfixSettingContent();
}
async function loadMaillog() {
try {
const response = await fetch("/api/maillog?lines=100");
const data = await response.json();
if (!response.ok) {
throw new Error(data.message || "maillog読込に失敗しました。");
}
logInfoEl.textContent = `ファイル: ${data.maillogPath} / 表示行数: ${data.count}`;
logOutputEl.textContent = data.lines.join("\n");
setStatus("maillogを更新しました。");
} catch (error) {
logInfoEl.textContent = "maillogを読み込めませんでした。";
logOutputEl.textContent = "";
setStatus(error.message, true);
}
}
reloadLogButton.addEventListener("click", loadMaillog);
reloadPostfixConfigButton.addEventListener("click", async () => {
try {
await loadPostfixSettingContent();
setStatus("Postfix設定を再読込しました。");
} catch (error) {
setStatus(error.message, true);
}
});
savePostfixConfigButton.addEventListener("click", async () => {
try {
await savePostfixSettingContent();
} catch (error) {
setStatus(error.message, true);
}
});
postfixFileSelectEl.addEventListener("change", async () => {
try {
await loadPostfixSettingContent();
} catch (error) {
setStatus(error.message, true);
}
});
loginFormEl.addEventListener("submit", async (event) => {
event.preventDefault();
try {
await login(passwordInputEl.value);
passwordInputEl.value = "";
setAuthenticatedView(true);
await loadPostfixSettingList();
try {
await loadPostfixSettingContent();
} catch (error) {
setStatus(error.message, true);
}
await loadMaillog();
setStatus("認証に成功しました。");
} catch (error) {
setStatus(error.message, true);
}
});
logoutButton.addEventListener("click", async () => {
await logout();
setAuthenticatedView(false);
setStatus("ログアウトしました。");
});
async function bootstrap() {
try {
const authenticated = await checkAuthStatus();
setAuthenticatedView(authenticated);
if (authenticated) {
await loadPostfixSettingList();
try {
await loadPostfixSettingContent();
} catch (error) {
setStatus(error.message, true);
}
await loadMaillog();
} else {
setStatus("パスワードを入力してください。");
}
} catch (error) {
setStatus("初期化に失敗しました。", true);
}
}
bootstrap();