feat: 10. Мини-админка (vanilla JS + GraphQL)
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
async function api(path, body) {
|
||||
const res = await fetch(path, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
const json = await res.json().catch(() => ({}));
|
||||
if (!res.ok) {
|
||||
throw new Error(json.detail || res.statusText);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
async function gql(query, variables) {
|
||||
const headers = { "Content-Type": "application/json" };
|
||||
const token = localStorage.getItem("access_token");
|
||||
if (token) {
|
||||
headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
const res = await fetch("/graphql", {
|
||||
method: "POST",
|
||||
headers,
|
||||
body: JSON.stringify({ query, variables }),
|
||||
});
|
||||
const json = await res.json();
|
||||
if (json.errors && json.errors.length) {
|
||||
throw new Error(json.errors[0].message);
|
||||
}
|
||||
return json.data;
|
||||
}
|
||||
|
||||
const CLIENTS_QUERY = `
|
||||
query { clients { id clientId name isConfidential redirectUris createdAt } }
|
||||
`;
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const loginForm = document.getElementById("login-form");
|
||||
const panel = document.getElementById("panel");
|
||||
const statusEl = document.getElementById("status");
|
||||
const clientsBody = document.getElementById("clients-body");
|
||||
const createBtn = document.getElementById("create-client");
|
||||
const logoutBtn = document.getElementById("logout");
|
||||
|
||||
function setStatus(message, ok = false) {
|
||||
statusEl.textContent = message || "";
|
||||
statusEl.classList.toggle("ok", ok);
|
||||
}
|
||||
|
||||
function setLoggedIn(isLoggedIn) {
|
||||
loginForm.classList.toggle("hidden", isLoggedIn);
|
||||
panel.classList.toggle("hidden", !isLoggedIn);
|
||||
}
|
||||
|
||||
function renderClients(clients) {
|
||||
clientsBody.textContent = "";
|
||||
for (const client of clients) {
|
||||
const row = document.createElement("tr");
|
||||
const cells = [
|
||||
client.id,
|
||||
client.clientId,
|
||||
client.name,
|
||||
client.isConfidential ? "yes" : "no",
|
||||
(client.redirectUris || []).join(", "),
|
||||
client.createdAt,
|
||||
];
|
||||
for (const value of cells) {
|
||||
const td = document.createElement("td");
|
||||
td.textContent = value;
|
||||
row.appendChild(td);
|
||||
}
|
||||
clientsBody.appendChild(row);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadClients() {
|
||||
try {
|
||||
const data = await gql(CLIENTS_QUERY);
|
||||
renderClients(data.clients);
|
||||
setStatus("");
|
||||
} catch (err) {
|
||||
renderClients([]);
|
||||
setStatus(err.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleLogin(event) {
|
||||
event.preventDefault();
|
||||
setStatus("");
|
||||
const email = document.getElementById("email").value;
|
||||
const password = document.getElementById("password").value;
|
||||
try {
|
||||
const { access_token } = await api("/auth/login", { email, password });
|
||||
localStorage.setItem("access_token", access_token);
|
||||
setLoggedIn(true);
|
||||
await loadClients();
|
||||
} catch (err) {
|
||||
setStatus(err.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleCreateClient() {
|
||||
const name = prompt("Название клиента");
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await gql(
|
||||
"mutation ($name: String!) { createClient(name: $name) { id clientId name } }",
|
||||
{ name }
|
||||
);
|
||||
setStatus("");
|
||||
await loadClients();
|
||||
} catch (err) {
|
||||
setStatus(err.message);
|
||||
}
|
||||
}
|
||||
|
||||
function handleLogout() {
|
||||
localStorage.removeItem("access_token");
|
||||
setLoggedIn(false);
|
||||
setStatus("");
|
||||
loginForm.reset();
|
||||
}
|
||||
|
||||
loginForm.addEventListener("submit", handleLogin);
|
||||
createBtn.addEventListener("click", handleCreateClient);
|
||||
logoutBtn.addEventListener("click", handleLogout);
|
||||
|
||||
if (localStorage.getItem("access_token")) {
|
||||
setLoggedIn(true);
|
||||
loadClients();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user