Files
rmm-openwrt/docs/design-preview/preview.js
2026-07-21 00:21:13 +03:00

113 lines
5.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use strict";
const concepts = {
evolution: {
number: "1",
title: "Эволюция текущего интерфейса",
description: "Сохраняет тёмный стиль и знакомую структуру, но переносит навигацию вниз, сокращает шапку и делает состояния понятнее.",
risk: "Минимальный риск миграции",
audience: "Для дома и небольших парков",
},
friendly: {
number: "2",
title: "Friendly mobile",
description: "Светлый, спокойный интерфейс с крупными зонами нажатия и человеческими формулировками. Ближе к приложениям Keenetic и домашним облачным сервисам.",
risk: "Средний объём изменений",
audience: "Для частных пользователей и малого бизнеса",
},
console: {
number: "3",
title: "Professional console",
description: "Более плотная операторская консоль: высокая информационная ёмкость, быстрые статусы и акцент на управление большим количеством устройств.",
risk: "Полная переработка оболочки",
audience: "Для MSP и больших парков",
},
};
const errorStates = {
timeout: {
code: "504 · GATEWAY TIMEOUT",
symbol: "!",
title: "LuCI не отвечает",
description: "Роутер на связи, но веб-интерфейс не ответил за 15 секунд. Настройки роутера не изменялись.",
session: "Ещё 14:32",
primary: "Повторить подключение",
secondary: "Открыть диагностику",
},
expired: {
code: "401 · SESSION EXPIRED",
symbol: "⌛",
title: "Доступ к LuCI истёк",
description: "Временная сессия завершилась. Создайте новый безопасный доступ, когда он снова понадобится.",
session: "Завершена",
primary: "Открыть новый доступ",
secondary: "Вернуться к роутеру",
},
offline: {
code: "503 · ROUTER OFFLINE",
symbol: "×",
title: "Роутер не на связи",
description: "RMM-агент давно не выходил на связь. LuCI станет доступен после восстановления подключения роутера.",
session: "Не создана",
primary: "Открыть диагностику",
secondary: "Посмотреть события",
},
forbidden: {
code: "403 · ACCESS DENIED",
symbol: "⊘",
title: "Нет доступа к роутеру",
description: "Этот роутер принадлежит другому аккаунту или ваши права были изменены. Обратитесь к администратору.",
session: "Недоступна",
primary: "Вернуться к объектам",
secondary: "Связаться с администратором",
},
starting: {
code: "409 · TUNNEL STARTING",
symbol: "…",
title: "Туннель запускается",
description: "Агент получил команду и поднимает защищённое соединение. Обычно это занимает до 20 секунд.",
session: "Подключение…",
primary: "Проверить снова",
secondary: "Отменить запуск",
},
};
function setConcept(name) {
const concept = concepts[name] || concepts.evolution;
document.body.dataset.concept = name in concepts ? name : "evolution";
document.querySelector("#conceptNumber").textContent = concept.number;
document.querySelector("#conceptTitle").textContent = concept.title;
document.querySelector("#conceptDescription").textContent = concept.description;
document.querySelector("#conceptRisk").textContent = concept.risk;
document.querySelector("#conceptAudience").textContent = concept.audience;
for (const button of document.querySelectorAll(".concept-button")) {
button.classList.toggle("is-active", button.dataset.concept === document.body.dataset.concept);
}
}
function setErrorState(name) {
const state = errorStates[name] || errorStates.timeout;
document.querySelector("#errorCode").textContent = state.code;
document.querySelector("#errorSymbol").textContent = state.symbol;
document.querySelector("#errorTitle").textContent = state.title;
document.querySelector("#errorDescription").textContent = state.description;
document.querySelector("#errorSession").textContent = state.session;
document.querySelector("#errorPrimaryAction").textContent = state.primary;
document.querySelector("#errorSecondaryAction").textContent = state.secondary;
for (const button of document.querySelectorAll(".error-demo")) {
button.classList.toggle("is-active", button.dataset.error === name);
}
}
for (const button of document.querySelectorAll(".concept-button")) {
button.addEventListener("click", () => setConcept(button.dataset.concept));
}
for (const button of document.querySelectorAll(".error-demo")) {
button.addEventListener("click", () => setErrorState(button.dataset.error));
}
const initialConcept = new URLSearchParams(window.location.search).get("concept") || "evolution";
setConcept(initialConcept);
setErrorState("timeout");