Initial SQL-only 1C adapter baseline
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
const $ = (id) => document.getElementById(id);
|
||||
const state = { bases: [], requests: [] };
|
||||
|
||||
function headers(json = false) {
|
||||
const value = {};
|
||||
if (json) value["Content-Type"] = "application/json";
|
||||
return value;
|
||||
}
|
||||
|
||||
async function request(path, options = {}) {
|
||||
const response = await fetch(path, { ...options, headers: { ...headers(Boolean(options.body)), ...(options.headers || {}) } });
|
||||
let data = {};
|
||||
try { data = await response.json(); } catch (_) { /* empty response */ }
|
||||
if (!response.ok) throw new Error(data.message || data.error || `HTTP ${response.status}`);
|
||||
return data;
|
||||
}
|
||||
|
||||
function notice(message = "", error = false) {
|
||||
$("notice").hidden = !message;
|
||||
$("notice").textContent = message;
|
||||
$("notice").className = `notice${error ? " error" : ""}`;
|
||||
}
|
||||
|
||||
function render() {
|
||||
$("bases").replaceChildren(...state.bases.map((base) => {
|
||||
const row = document.createElement("tr");
|
||||
const cells = [base.base_id, base.server, base.database, base.user];
|
||||
cells.forEach((value) => { const td = document.createElement("td"); td.textContent = value; row.append(td); });
|
||||
const password = document.createElement("td");
|
||||
password.innerHTML = `<span class="badge ${base.has_password ? "" : "missing"}">${base.password_env ? "ENV · " + escapeHtml(base.password_env) : base.has_password ? "Сохранён" : "Не задан"}</span>`;
|
||||
row.append(password);
|
||||
const actions = document.createElement("td"); actions.className = "actions";
|
||||
const edit = document.createElement("button"); edit.className = "text-button"; edit.textContent = "Изменить"; edit.onclick = () => openEditor(base);
|
||||
const remove = document.createElement("button"); remove.className = "text-button danger"; remove.textContent = "Удалить"; remove.onclick = () => deleteBase(base);
|
||||
actions.append(edit, remove); row.append(actions); return row;
|
||||
}));
|
||||
$("empty").hidden = state.bases.length > 0;
|
||||
$("count").textContent = `${state.bases.length} ${state.bases.length === 1 ? "подключение" : "подключений"}`;
|
||||
}
|
||||
|
||||
function renderRequests() {
|
||||
$("requests").replaceChildren(...state.requests.map((item) => {
|
||||
const row = document.createElement("tr");
|
||||
const values = [item.request_id, item.base_id, item.status, (item.objects || []).join(", "), item.created_at ? new Date(item.created_at * 1000).toLocaleString("ru-RU") : "—"];
|
||||
values.forEach((value, index) => { const td = document.createElement("td"); td.textContent = value || "—"; if (index === 2) td.className = `request-status ${item.status || ""}`; if (index === 3) td.className = "request-objects"; row.append(td); });
|
||||
return row;
|
||||
}));
|
||||
$("requestsEmpty").hidden = state.requests.length > 0;
|
||||
$("requestCount").textContent = `${state.requests.length} заявок`;
|
||||
}
|
||||
|
||||
function escapeHtml(value) {
|
||||
const div = document.createElement("div"); div.textContent = value; return div.innerHTML;
|
||||
}
|
||||
|
||||
async function load() {
|
||||
try {
|
||||
notice();
|
||||
const [data, repository] = await Promise.all([request("/admin/api/bases"), request("/admin/api/repository/requests")]);
|
||||
state.bases = data.bases || [];
|
||||
state.requests = repository.requests || [];
|
||||
$("statusDot").classList.add("online"); $("connectionText").textContent = "Адаптер подключён";
|
||||
render();
|
||||
renderRequests();
|
||||
} catch (error) {
|
||||
$("statusDot").classList.remove("online"); $("connectionText").textContent = "Требуется подключение";
|
||||
notice(error.message === "bearer_token_required" ? "Введите Bearer-токен адаптера." : error.message, true);
|
||||
}
|
||||
}
|
||||
|
||||
function openEditor(base = null) {
|
||||
$("editorTitle").textContent = base ? "Редактировать базу" : "Новая база";
|
||||
$("originalId").value = base?.base_id || "";
|
||||
$("baseId").value = base?.base_id || ""; $("server").value = base?.server || "";
|
||||
$("database").value = base?.database || ""; $("user").value = base?.user || "";
|
||||
$("password").value = ""; $("passwordEnv").value = base?.password_env || "";
|
||||
$("repositoryEnabled").checked = Boolean(base?.repository);
|
||||
$("repositoryBackend").value = base?.repository?.backend || "direct";
|
||||
$("repositoryLayer").value = base?.repository?.layer || "base";
|
||||
$("repositoryLockMode").value = base?.repository?.lock_mode || "automatic";
|
||||
$("repositoryBridgeId").value = base?.repository?.bridge_id || "";
|
||||
$("repositoryUser").value = base?.repository?.repository_user || "";
|
||||
$("passwordHint").textContent = base?.has_password ? "Пароль уже задан. Оставьте пустым, чтобы сохранить текущий." : "Задайте пароль или переменную окружения.";
|
||||
$("editor").showModal(); setTimeout(() => $("baseId").focus(), 30);
|
||||
}
|
||||
|
||||
async function save(event) {
|
||||
event.preventDefault();
|
||||
if (!$("baseForm").reportValidity()) return;
|
||||
const original = $("originalId").value;
|
||||
const payload = { base_id: $("baseId").value.trim(), server: $("server").value.trim(), database: $("database").value.trim(), user: $("user").value.trim(), password: $("password").value, password_env: $("passwordEnv").value.trim(), repository: $("repositoryEnabled").checked ? { backend: $("repositoryBackend").value, layer: $("repositoryLayer").value, lock_mode: $("repositoryLockMode").value, bridge_id: $("repositoryBridgeId").value.trim(), repository_user: $("repositoryUser").value.trim() } : { enabled: false } };
|
||||
$("saveButton").disabled = true;
|
||||
try {
|
||||
await request(original ? `/admin/api/bases/${encodeURIComponent(original)}` : "/admin/api/bases", { method: original ? "PUT" : "POST", body: JSON.stringify(payload) });
|
||||
$("editor").close(); await load(); notice(original ? "Подключение обновлено." : "Подключение добавлено.");
|
||||
} catch (error) { notice(error.message, true); } finally { $("saveButton").disabled = false; }
|
||||
}
|
||||
|
||||
async function deleteBase(base) {
|
||||
if (!confirm(`Удалить подключение «${base.base_id}»?`)) return;
|
||||
try { await request(`/admin/api/bases/${encodeURIComponent(base.base_id)}`, { method: "DELETE" }); await load(); notice("Подключение удалено."); }
|
||||
catch (error) { notice(error.message, true); }
|
||||
}
|
||||
|
||||
$("refreshButton").onclick = load; $("addButton").onclick = () => openEditor(); $("baseForm").onsubmit = save;
|
||||
load();
|
||||
Reference in New Issue
Block a user