This commit is contained in:
@@ -1,14 +1,12 @@
|
||||
(() => {
|
||||
const STORAGE_KEY = "phenikaax_dashboard_v1";
|
||||
|
||||
const WIDGET_LABELS = {
|
||||
mission_button: "Mission button",
|
||||
mission_group: "Mission group",
|
||||
mission_queue: "Mission queue",
|
||||
pause_continue: "Pause / Continue",
|
||||
};
|
||||
function widgetTypeLabel(type) {
|
||||
return t(`dashboard.widget.${type}`) || type;
|
||||
}
|
||||
|
||||
const el = (id) => document.getElementById(id);
|
||||
const t = (key, vars) => window.I18n?.t(key, vars) ?? key;
|
||||
const gridEl = el("dashboardGrid");
|
||||
const emptyEl = el("dashboardEmpty");
|
||||
const addDialogEl = el("dashboardAddWidgetDialog");
|
||||
@@ -60,7 +58,7 @@
|
||||
store.widgets = [
|
||||
{ id: newId(), type: "mission_button", mission_id: firstId, title: "" },
|
||||
{ id: newId(), type: "mission_group", group: "Missions", title: "" },
|
||||
{ id: newId(), type: "mission_queue", title: "Mission queue" },
|
||||
{ id: newId(), type: "mission_queue", title: "" },
|
||||
{ id: newId(), type: "pause_continue", title: "" },
|
||||
];
|
||||
persistStore();
|
||||
@@ -76,7 +74,7 @@
|
||||
|
||||
function widgetTitle(widget) {
|
||||
if (widget.title) return widget.title;
|
||||
return WIDGET_LABELS[widget.type] || widget.type;
|
||||
return widgetTypeLabel(widget.type);
|
||||
}
|
||||
|
||||
function missionOptions(selected) {
|
||||
@@ -102,33 +100,33 @@
|
||||
if (type === "mission_button") {
|
||||
container.innerHTML = `
|
||||
<div class="row rowWide">
|
||||
<label>Mission</label>
|
||||
<label>${t("dashboard.widget.field.mission")}</label>
|
||||
<select data-field="mission_id">${missionOptions(widget.mission_id || "")}</select>
|
||||
</div>
|
||||
<div class="row rowWide">
|
||||
<label>Tiêu đề widget (tùy chọn)</label>
|
||||
<input data-field="title" type="text" value="${escapeHtml(widget.title || "")}" placeholder="VD: Go to charging" />
|
||||
<label>${t("dashboard.widget.field.title")}</label>
|
||||
<input data-field="title" type="text" value="${escapeHtml(widget.title || "")}" placeholder="${t(\"dashboard.widget.titlePlaceholder\")}" />
|
||||
</div>`;
|
||||
} else if (type === "mission_group") {
|
||||
container.innerHTML = `
|
||||
<div class="row rowWide">
|
||||
<label>Nhóm mission</label>
|
||||
<label>${t("dashboard.widget.field.group")}</label>
|
||||
<select data-field="group">${groupOptions(widget.group || "Missions")}</select>
|
||||
</div>
|
||||
<div class="row rowWide">
|
||||
<label>Tiêu đề widget (tùy chọn)</label>
|
||||
<label>${t("dashboard.widget.field.title")}</label>
|
||||
<input data-field="title" type="text" value="${escapeHtml(widget.title || "")}" />
|
||||
</div>`;
|
||||
} else if (type === "mission_queue") {
|
||||
container.innerHTML = `
|
||||
<div class="row rowWide">
|
||||
<label>Tiêu đề widget (tùy chọn)</label>
|
||||
<label>${t("dashboard.widget.field.title")}</label>
|
||||
<input data-field="title" type="text" value="${escapeHtml(widget.title || "Mission queue")}" />
|
||||
</div>`;
|
||||
} else if (type === "pause_continue") {
|
||||
container.innerHTML = `
|
||||
<div class="row rowWide">
|
||||
<label>Tiêu đề widget (tùy chọn)</label>
|
||||
<label>${t("dashboard.widget.field.title")}</label>
|
||||
<input data-field="title" type="text" value="${escapeHtml(widget.title || "")}" />
|
||||
</div>
|
||||
<p class="mutedNote">Tạm dừng / tiếp tục / hủy mission đang chạy trên robot.</p>`;
|
||||
@@ -145,13 +143,13 @@
|
||||
|
||||
function renderMissionButtonWidget(widget, bodyEl) {
|
||||
const m = missions()?.getMissionById?.(widget.mission_id);
|
||||
const label = m?.name || "Chọn mission…";
|
||||
const label = m?.name || t("dashboard.widget.selectMission");
|
||||
bodyEl.innerHTML = `
|
||||
<button type="button" class="dashboardMissionBtn" data-run-mission="${escapeHtml(widget.mission_id || "")}">
|
||||
<span class="dashboardMissionBtnIcon">▶</span>
|
||||
<span>${escapeHtml(label)}</span>
|
||||
</button>
|
||||
${!m ? `<p class="mutedNote dashboardWidgetHint">Cấu hình widget và chọn mission.</p>` : ""}`;
|
||||
${!m ? `<p class="mutedNote dashboardWidgetHint">${t("dashboard.widget.configHint")}</p>` : ""}`;
|
||||
bodyEl.querySelector("[data-run-mission]")?.addEventListener("click", () => {
|
||||
if (!widget.mission_id) return;
|
||||
missions()?.queueMission?.(widget.mission_id);
|
||||
@@ -162,7 +160,7 @@
|
||||
const group = widget.group || "Missions";
|
||||
const list = (missions()?.getMissions?.() || []).filter((m) => m.group === group);
|
||||
if (!list.length) {
|
||||
bodyEl.innerHTML = `<p class="mutedNote">Không có mission trong nhóm «${escapeHtml(group)}».</p>`;
|
||||
bodyEl.innerHTML = `<p class="mutedNote">${t("dashboard.widget.emptyGroup", { group })}</p>`;
|
||||
return;
|
||||
}
|
||||
bodyEl.innerHTML = `<div class="dashboardMissionGroupList"></div>`;
|
||||
@@ -181,8 +179,8 @@
|
||||
bodyEl.innerHTML = `
|
||||
<div class="dashboardQueueRunner mutedNote" data-role="runner">—</div>
|
||||
<div class="dashboardQueueList" data-role="list"></div>
|
||||
<p class="mutedNote dashboardQueueEmpty" data-role="empty">Queue trống</p>
|
||||
<button type="button" class="btn subtle btnBlock dashboardQueueClear">Xóa queue chờ</button>`;
|
||||
<p class="mutedNote dashboardQueueEmpty" data-role="empty">${t("dashboard.widget.queueEmpty")}</p>
|
||||
<button type="button" class="btn subtle btnBlock dashboardQueueClear">${t("dashboard.widget.clearQueue")}</button>`;
|
||||
bodyEl.querySelector(".dashboardQueueClear")?.addEventListener("click", () => missions()?.clearQueue?.());
|
||||
refreshQueueWidget(bodyEl);
|
||||
}
|
||||
@@ -208,13 +206,13 @@
|
||||
bodyEl.innerHTML = `
|
||||
<div class="dashboardRunnerControls">
|
||||
<button type="button" class="dashboardPauseBtn ${paused ? "is-paused" : ""}" data-pause-action="${paused ? "continue" : "pause"}" ${running ? "" : "disabled"}>
|
||||
${paused ? "Continue" : "Pause"}
|
||||
${paused ? t("dashboard.widget.continue") : t("dashboard.widget.pause")}
|
||||
</button>
|
||||
<button type="button" class="dashboardCancelBtn" data-cancel-mission ${running ? "" : "disabled"}>
|
||||
Hủy mission
|
||||
${t("dashboard.widget.cancelMission")}
|
||||
</button>
|
||||
</div>
|
||||
<p class="mutedNote dashboardWidgetHint">${running ? (paused ? "Mission đang tạm dừng" : "Mission đang chạy") : "Không có mission đang chạy"}</p>`;
|
||||
<p class="mutedNote dashboardWidgetHint">${running ? (paused ? t("dashboard.widget.runner.paused") : t("dashboard.widget.runner.running")) : t("dashboard.widget.runner.idle")}</p>`;
|
||||
bodyEl.querySelector("[data-pause-action]")?.addEventListener("click", async (evt) => {
|
||||
const action = evt.currentTarget.dataset.pauseAction;
|
||||
try {
|
||||
@@ -242,8 +240,8 @@
|
||||
<div class="dashboardWidgetHeader">
|
||||
<div class="dashboardWidgetTitle">${escapeHtml(widgetTitle(widget))}</div>
|
||||
<div class="dashboardWidgetChrome" hidden>
|
||||
<button type="button" class="iconBtn" data-widget-config title="Cấu hình">⚙</button>
|
||||
<button type="button" class="iconBtn danger" data-widget-delete title="Xóa">×</button>
|
||||
<button type="button" class="iconBtn" data-widget-config title="${t(\"common.configure\")}">⚙</button>
|
||||
<button type="button" class="iconBtn danger" data-widget-delete title="${t(\"common.delete\")}">×</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dashboardWidgetBody"></div>`;
|
||||
@@ -301,13 +299,13 @@
|
||||
const widget = store.widgets.find((w) => w.id === widgetId);
|
||||
if (!widget) return;
|
||||
editWidgetIdEl.value = widget.id;
|
||||
editWidgetTypeEl.value = WIDGET_LABELS[widget.type] || widget.type;
|
||||
editWidgetTypeEl.value = widgetTypeLabel(widget.type);
|
||||
fillTypeFields(editFieldsEl, widget.type, widget);
|
||||
editDialogEl.showModal();
|
||||
}
|
||||
|
||||
function deleteWidget(widgetId) {
|
||||
if (!confirm("Xóa widget này?")) return;
|
||||
if (!confirm(t("dashboard.widget.deleteConfirm"))) return;
|
||||
store.widgets = store.widgets.filter((w) => w.id !== widgetId);
|
||||
persistStore();
|
||||
renderDashboard();
|
||||
@@ -318,7 +316,7 @@
|
||||
el("dashboardAddWidgetBtn")?.addEventListener("click", openAddDialog);
|
||||
el("dashboardEditBtn")?.addEventListener("click", () => {
|
||||
store.editMode = !store.editMode;
|
||||
el("dashboardEditBtn").textContent = store.editMode ? "Xong" : "Sửa layout";
|
||||
el("dashboardEditBtn").textContent = store.editMode ? t("dashboard.editDone") : t("dashboard.editLayout");
|
||||
renderDashboard();
|
||||
});
|
||||
|
||||
@@ -391,6 +389,12 @@
|
||||
function boot() {
|
||||
init();
|
||||
}
|
||||
window.addEventListener("lm:locale-change", () => {
|
||||
renderDashboard();
|
||||
const editBtn = el("dashboardEditBtn");
|
||||
if (editBtn) editBtn.textContent = store.editMode ? t("dashboard.editDone") : t("dashboard.editLayout");
|
||||
});
|
||||
|
||||
if (window.AuthApp?.isReady()) boot();
|
||||
else window.addEventListener("lm:auth-ready", boot, { once: true });
|
||||
window.addEventListener("lm:auth-logout", stopDashboardPoll);
|
||||
|
||||
Reference in New Issue
Block a user