import { withStatus } from "./api.js"; import { openChart, renderChart } from "./chart.js"; import { dom } from "./dom.js"; import { closeApiDocDrawer, openApiDocDrawer } from "./docs.js"; import { loadEvents } from "./events.js"; import { applyBatchEquipmentUnit, clearEquipmentFilter, clearPointBinding, clearSelectedEquipments, closeEquipmentModal, loadEquipments, openCreateEquipmentModal, resetEquipmentForm, saveEquipment, } from "./equipment.js"; import { startPointSocket, startLogs, stopLogs } from "./logs.js"; import { startOps, renderOpsUnits, loadAllEquipmentCards } from "./ops.js"; import { clearBatchBinding, browseAndLoadTree, clearSelectedPoints, createPoints, loadPoints, loadTree, openBatchBinding, openPointCreateModal, renderSelectedNodes, saveBatchBinding, savePointBinding, updatePointFilterSummary, updateSelectedPointSummary, } from "./points.js"; import { state } from "./state.js"; import { loadSources, saveSource } from "./sources.js"; import { closeUnitModal, loadUnits, openCreateUnitModal, resetUnitForm, renderUnits, saveUnit } from "./units.js"; function switchView(view) { state.activeView = view; const main = document.querySelector("main"); main.className = view === "ops" ? "grid-ops" : "grid-config"; dom.tabOps.classList.toggle("active", view === "ops"); dom.tabConfig.classList.toggle("active", view === "config"); // config-only panels ["top-left", "top-right", "bottom-left", "bottom-right"].forEach((cls) => { const el = main.querySelector(`.panel.${cls}`); if (el) el.classList.toggle("hidden", view === "ops"); }); // bottom-mid is log-stream in config, hidden in ops const logStreamPanel = main.querySelector(".panel.bottom-mid"); if (logStreamPanel) logStreamPanel.classList.toggle("hidden", view === "ops"); // ops-only panels const opsMain = main.querySelector(".panel.ops-main"); const opsBottom = main.querySelector(".panel.ops-bottom"); if (opsMain) opsMain.classList.toggle("hidden", view === "config"); if (opsBottom) opsBottom.classList.toggle("hidden", view === "config"); if (view === "config") { startLogs(); } else { stopLogs(); } } function bindEvents() { dom.unitForm.addEventListener("submit", (event) => withStatus(saveUnit(event))); dom.sourceForm.addEventListener("submit", (event) => withStatus(saveSource(event))); dom.equipmentForm.addEventListener("submit", (event) => withStatus(saveEquipment(event))); dom.pointBindingForm.addEventListener("submit", (event) => withStatus(savePointBinding(event))); dom.batchBindingForm.addEventListener("submit", (event) => withStatus(saveBatchBinding(event))); dom.unitResetBtn.addEventListener("click", resetUnitForm); dom.refreshUnitBtn.addEventListener("click", () => withStatus(loadUnits().then(loadEvents))); dom.newUnitBtn.addEventListener("click", openCreateUnitModal); dom.closeUnitModalBtn.addEventListener("click", closeUnitModal); dom.sourceResetBtn.addEventListener("click", () => dom.sourceForm.reset()); dom.equipmentResetBtn.addEventListener("click", resetEquipmentForm); dom.refreshEquipmentBtn.addEventListener("click", () => withStatus(loadEquipments())); dom.newEquipmentBtn.addEventListener("click", openCreateEquipmentModal); dom.closeEquipmentModalBtn.addEventListener("click", closeEquipmentModal); dom.clearEquipmentFilterBtn.addEventListener("click", () => withStatus(clearEquipmentFilter())); dom.applyEquipmentUnitBtn.addEventListener("click", () => withStatus(applyBatchEquipmentUnit())); dom.clearEquipmentSelectionBtn.addEventListener("click", clearSelectedEquipments); dom.openPointModalBtn.addEventListener("click", openPointCreateModal); dom.pointSourceSelect.addEventListener("change", () => { dom.nodeTree.innerHTML = '
Click "Load Nodes" to fetch node tree
'; dom.pointSourceNodeCount.textContent = "Nodes: 0"; }); dom.browseNodesBtn.addEventListener("click", () => withStatus(browseAndLoadTree())); dom.refreshTreeBtn.addEventListener("click", () => withStatus(loadTree())); dom.createPointsBtn.addEventListener("click", () => withStatus(createPoints())); dom.closeModalBtn.addEventListener("click", () => dom.pointModal.classList.add("hidden")); dom.openSourceFormBtn.addEventListener("click", () => { dom.sourceForm.reset(); dom.sourceId.value = ""; dom.sourceModal.classList.remove("hidden"); }); dom.closeSourceModalBtn.addEventListener("click", () => dom.sourceModal.classList.add("hidden")); dom.clearPointBindingBtn.addEventListener("click", () => withStatus(clearPointBinding())); dom.closePointBindingModalBtn.addEventListener("click", () => { dom.pointBindingModal.classList.add("hidden"); }); dom.openBatchBindingBtn.addEventListener("click", openBatchBinding); dom.clearSelectedPointsBtn.addEventListener("click", clearSelectedPoints); dom.closeBatchBindingModalBtn.addEventListener("click", () => { dom.batchBindingModal.classList.add("hidden"); }); dom.clearBatchBindingBtn.addEventListener("click", () => withStatus(clearBatchBinding())); dom.toggleAllPoints.addEventListener("change", () => { const checked = dom.toggleAllPoints.checked; dom.pointList.querySelectorAll('input[data-point-select="true"]').forEach((input) => { input.checked = checked; input.dispatchEvent(new Event("change")); }); }); dom.openApiDocBtn.addEventListener("click", () => withStatus(openApiDocDrawer())); dom.closeApiDocBtn.addEventListener("click", closeApiDocDrawer); dom.refreshEventBtn.addEventListener("click", () => withStatus(loadEvents())); dom.refreshChartBtn.addEventListener("click", () => { if (!state.chartPointId) { return; } withStatus(openChart(state.chartPointId, state.chartPointName)); }); dom.prevPointsBtn.addEventListener("click", () => { if (state.pointsPage > 1) { state.pointsPage -= 1; withStatus(loadPoints()); } }); dom.nextPointsBtn.addEventListener("click", () => { const totalPages = Math.max(1, Math.ceil(state.pointsTotal / state.pointsPageSize)); if (state.pointsPage < totalPages) { state.pointsPage += 1; withStatus(loadPoints()); } }); dom.equipmentKeyword.addEventListener("keydown", (event) => { if (event.key === "Enter") { event.preventDefault(); withStatus(loadEquipments()); } }); dom.tabOps.addEventListener("click", () => switchView("ops")); dom.tabConfig.addEventListener("click", () => switchView("config")); document.addEventListener("equipments-updated", () => { renderUnits(); renderOpsUnits(); if (!state.selectedOpsUnitId) loadAllEquipmentCards(); }); document.addEventListener("units-loaded", () => { renderOpsUnits(); if (state.equipments.length > 0 && !state.selectedOpsUnitId) loadAllEquipmentCards(); }); } async function bootstrap() { bindEvents(); switchView("ops"); renderSelectedNodes(); updateSelectedPointSummary(); updatePointFilterSummary(); renderChart(); startPointSocket(); await withStatus(loadUnits()); startOps(); await withStatus(loadSources()); await withStatus(loadEquipments()); await withStatus(loadEvents()); await withStatus(loadPoints()); } bootstrap();