This commit is contained in:
107
www/topbar.js
107
www/topbar.js
@@ -1,63 +1,14 @@
|
||||
(() => {
|
||||
const el = (id) => document.getElementById(id);
|
||||
|
||||
const I18N = {
|
||||
vi: {
|
||||
"topbar.allOk": "ỔN ĐỊNH",
|
||||
"topbar.error": "LỖI",
|
||||
"topbar.paused": "TẠM DỪNG",
|
||||
"topbar.running": "ĐANG CHẠY",
|
||||
"topbar.waiting": "Đang chờ mission mới…",
|
||||
"topbar.noMissionsQueue": "Không có mission trong queue…",
|
||||
"topbar.reset": "RESET",
|
||||
"topbar.changeUserData": "Lưu thông tin",
|
||||
"topbar.changePassword": "Đổi mật khẩu",
|
||||
"topbar.logout": "Đăng xuất",
|
||||
"topbar.displayName": "Tên hiển thị",
|
||||
"topbar.reload": "Tải lại",
|
||||
"topbar.saveLayout": "Lưu layout",
|
||||
"topbar.joystickTitle": "Điều khiển tay (Joystick)",
|
||||
"topbar.joystickSpeed": "Tốc độ",
|
||||
"topbar.joystickOff": "Tắt joystick",
|
||||
"topbar.localeVi": "TIẾNG VIỆT",
|
||||
"topbar.localeEn": "ENGLISH",
|
||||
"topbar.startHint": "Bấm để START robot",
|
||||
"topbar.pauseHint": "Bấm để PAUSE robot",
|
||||
"topbar.code": "Mã",
|
||||
"topbar.module": "Module",
|
||||
},
|
||||
en: {
|
||||
"topbar.allOk": "ALL OK",
|
||||
"topbar.error": "ERROR",
|
||||
"topbar.paused": "PAUSED",
|
||||
"topbar.running": "RUNNING",
|
||||
"topbar.waiting": "Waiting for new missions…",
|
||||
"topbar.noMissionsQueue": "No missions in queue…",
|
||||
"topbar.reset": "RESET",
|
||||
"topbar.changeUserData": "Change user data",
|
||||
"topbar.changePassword": "Change password",
|
||||
"topbar.logout": "Log out",
|
||||
"topbar.displayName": "Display name",
|
||||
"topbar.reload": "Reload",
|
||||
"topbar.saveLayout": "Save layout",
|
||||
"topbar.joystickTitle": "Manual control (Joystick)",
|
||||
"topbar.joystickSpeed": "Speed",
|
||||
"topbar.joystickOff": "Disengage joystick",
|
||||
"topbar.localeVi": "TIẾNG VIỆT",
|
||||
"topbar.localeEn": "ENGLISH",
|
||||
"topbar.startHint": "Click to START the robot",
|
||||
"topbar.pauseHint": "Click to PAUSE the robot",
|
||||
"topbar.code": "Code",
|
||||
"topbar.module": "Module",
|
||||
},
|
||||
};
|
||||
|
||||
const LOCALE_META = {
|
||||
vi: { flag: "🇻🇳", labelKey: "topbar.localeVi" },
|
||||
en: { flag: "🇺🇸", labelKey: "topbar.localeEn" },
|
||||
};
|
||||
|
||||
let locale = "vi";
|
||||
const t = (key, vars) => window.I18n?.t(key, vars) ?? key;
|
||||
const getLocale = () => window.I18n?.getLocale?.() ?? "vi";
|
||||
|
||||
let robotStatus = null;
|
||||
let pollTimer = null;
|
||||
let eventsBound = false;
|
||||
@@ -67,8 +18,13 @@
|
||||
let joystickRaf = null;
|
||||
let lastCmd = { linear: 0, angular: 0 };
|
||||
|
||||
function t(key) {
|
||||
return I18N[locale]?.[key] ?? I18N.en[key] ?? key;
|
||||
function applyLocale(next) {
|
||||
if (window.I18n) window.I18n.setLocale(next);
|
||||
if (robotStatus) renderAll(robotStatus);
|
||||
}
|
||||
|
||||
function loadLocale() {
|
||||
/* locale owned by I18n */
|
||||
}
|
||||
|
||||
function canSeeMissions() {
|
||||
@@ -96,35 +52,6 @@
|
||||
return data;
|
||||
}
|
||||
|
||||
function applyLocale(next) {
|
||||
locale = LOCALE_META[next] ? next : "vi";
|
||||
try {
|
||||
localStorage.setItem("lm_locale", locale);
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
document.documentElement.lang = locale;
|
||||
document.querySelectorAll("[data-i18n]").forEach((node) => {
|
||||
const key = node.dataset.i18n;
|
||||
if (key) node.textContent = t(key);
|
||||
});
|
||||
const meta = LOCALE_META[locale];
|
||||
if (el("mirLocaleFlag")) el("mirLocaleFlag").textContent = meta.flag;
|
||||
if (el("mirLocaleLabel")) el("mirLocaleLabel").textContent = t(meta.labelKey);
|
||||
window.dispatchEvent(new CustomEvent("lm:locale-change", { detail: { locale } }));
|
||||
if (robotStatus) renderAll(robotStatus);
|
||||
}
|
||||
|
||||
function loadLocale() {
|
||||
try {
|
||||
const saved = localStorage.getItem("lm_locale");
|
||||
if (saved && LOCALE_META[saved]) locale = saved;
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
applyLocale(locale);
|
||||
}
|
||||
|
||||
function closePanels() {
|
||||
document.querySelectorAll(".mirPanel").forEach((p) => {
|
||||
p.hidden = true;
|
||||
@@ -226,7 +153,7 @@
|
||||
bodyEl.innerHTML = `
|
||||
<div class="mirStatusOkTitle">${t("topbar.allOk")}</div>
|
||||
<div class="mirStatusDesc">${message}</div>
|
||||
${status.queue_pending > 0 ? `<div class="mirStatusMeta">${status.queue_pending} mission(s) in queue</div>` : ""}`;
|
||||
${status.queue_pending > 0 ? `<div class="mirStatusMeta">${t("topbar.queueCount", { n: status.queue_pending })}</div>` : ""}`;
|
||||
if (footerEl) footerEl.hidden = true;
|
||||
}
|
||||
}
|
||||
@@ -267,7 +194,10 @@
|
||||
joystickActive = engaged;
|
||||
const speedSel = el("joystickSpeedSelect");
|
||||
if (speedSel && status.joystick_speed) speedSel.value = status.joystick_speed;
|
||||
if (el("joystickSpeedLabel")) el("joystickSpeedLabel").textContent = status.joystick_speed || "fast";
|
||||
if (el("joystickSpeedLabel")) {
|
||||
const speed = status.joystick_speed || "fast";
|
||||
el("joystickSpeedLabel").textContent = t(`topbar.joystickSpeed.${speed}`);
|
||||
}
|
||||
}
|
||||
|
||||
function renderAll(status) {
|
||||
@@ -438,7 +368,7 @@
|
||||
|
||||
el("mirSegJoystick")?.addEventListener("click", async () => {
|
||||
if (!canControl()) {
|
||||
alert(locale === "vi" ? "Không có quyền điều khiển" : "No control permission");
|
||||
alert(t("topbar.noControlPermission"));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -472,6 +402,9 @@
|
||||
});
|
||||
|
||||
bindJoystickPad();
|
||||
window.addEventListener("lm:locale-change", () => {
|
||||
if (robotStatus) renderAll(robotStatus);
|
||||
});
|
||||
}
|
||||
|
||||
function start() {
|
||||
@@ -502,7 +435,7 @@
|
||||
|
||||
window.TopbarApp = {
|
||||
t,
|
||||
getLocale: () => locale,
|
||||
getLocale,
|
||||
applyLocale,
|
||||
refresh: fetchStatus,
|
||||
getRobotStatus: () => robotStatus,
|
||||
|
||||
Reference in New Issue
Block a user