@@ -894,6 +910,34 @@ function switchTab(name) {
document.querySelectorAll('.tab').forEach(b =>
b.addEventListener('click', () => switchTab(b.dataset.tab)));
+// ── Tickets dataset sub-tabs (INC | CRQ) ────────────────────────────────────
+// Same dashboard machinery, different source dataset: flips DS, which repoints the
+// /webhook/${DS}-dashboard|search|filter-options calls, then resets the per-dataset
+// dropdowns + explorer and reloads. The map/legend/popups are dataset-agnostic.
+function resetSelect(id) { // keep only the first (placeholder) option
+ const el = $(id); if (!el) return;
+ while (el.options.length > 1) el.remove(1);
+ el.selectedIndex = 0;
+}
+function setDataset(ds) {
+ if (ds === DS) return;
+ DS = ds;
+ document.querySelectorAll('.subtab').forEach(b => b.classList.toggle('active', b.dataset.ds === ds));
+ const U = ds.toUpperCase();
+ $('tk-ds-ov').textContent = U;
+ $('tk-ds-map').textContent = U;
+ // per-dataset dropdowns + explorer results are stale → clear and re-init
+ incDropdownsInit = false; incFilterOptionsInit = false;
+ ['tk-cluster', 'tk-status', 'tk-x-eng', 'tk-x-cluster'].forEach(resetSelect);
+ $('tk-x-id').value = ''; $('tk-x-id-list').innerHTML = '';
+ $('tk-x-count').textContent = '';
+ $('tk-x-wrap').innerHTML = '
Search by ticket id, engineer, cluster, state and time.
';
+ loadInc(); // reload metrics + map for the new dataset
+ loadIncFilterOptions(); // refill explorer pulldowns for the new dataset
+}
+document.querySelectorAll('.subtab').forEach(b =>
+ b.addEventListener('click', () => setDataset(b.dataset.ds)));
+
// ============================================================================
// TICKETS — INC operations dashboard (open layer + windowed closed overlay)
// ============================================================================
@@ -963,6 +1007,7 @@ const tkMarkers = new Map(); // imei → maplibregl.M
const tkLayerState = { open: true, closed: true, vehicles: true };
let tkOwnerFilter = null; // when set, the closed layer is filtered to this engineer (drill-down)
let incData = null, incDropdownsInit = false, vehCount = 0;
+let DS = 'inc'; // active Tickets dataset (inc | crq) — drives /webhook/${DS}-* endpoints + labels
let tkLoadedDay = null; // EAT calendar day of the last INC load — drives the midnight auto-rollover
const eatDay = () => new Date().toLocaleDateString('en-CA', { timeZone: 'Africa/Nairobi' });
@@ -1224,7 +1269,7 @@ let incFilterOptionsInit = false;
async function loadIncFilterOptions() {
if (incFilterOptionsInit) return;
try {
- const o = await api('/webhook/inc-filter-options');
+ const o = await api(`/webhook/${DS}-filter-options`);
incFilterOptionsInit = true;
const eng = $('tk-x-eng'); (o.owners || []).forEach((n) => eng.add(new Option(n, n)));
const cl = $('tk-x-cluster'); (o.clusters || []).forEach((c) => cl.add(new Option(c, c)));
@@ -1235,7 +1280,7 @@ async function loadIncSearch() {
const wrap = $('tk-x-wrap');
wrap.innerHTML = '
Searching…
';
try {
- const j = await api(`/webhook/inc-search?${incSearchQs()}`);
+ const j = await api(`/webhook/${DS}-search?${incSearchQs()}`);
tkSearchRows = (j && j.rows) || [];
const count = (j && j.count) || 0;
$('tk-x-count').textContent = j ? (j.truncated ? `(first ${tkSearchRows.length} of ${intg(count)})` : `(${intg(count)})`) : '';
@@ -1287,7 +1332,7 @@ function initIncDropdowns(m) {
async function loadInc() {
$('tk-main').classList.add('loading');
try {
- const j = await api(`/webhook/inc-dashboard?${incQs()}`);
+ const j = await api(`/webhook/${DS}-dashboard?${incQs()}`);
incData = j;
tkLoadedDay = eatDay();
if (!incDropdownsInit && j.metrics) { initIncDropdowns(j.metrics); incDropdownsInit = true; }
@@ -1296,7 +1341,7 @@ async function loadInc() {
buildIncLayers();
} catch (e) {
console.error(e);
- $('tk-metrics').innerHTML = `
${e.message || 'Failed to load the INC dashboard. Is the API reachable?'}
`;
+ $('tk-metrics').innerHTML = `
${e.message || `Failed to load the ${DS.toUpperCase()} dashboard. Is the API reachable?`}
`;
} finally {
$('tk-main').classList.remove('loading');
}
@@ -1389,8 +1434,8 @@ function showIncPopup(f, closed) {
function buildIncLayers() {
const m = (incData && incData.metrics) || {};
const rows = [
- { id: 'open', label: 'Open INC', color: SLA_COLORS.breached, n: m.open_now ?? 0 },
- { id: 'closed', label: 'Closed INC', color: pastel(CLOSED_COLOR), n: m.closed_in_window ?? 0 },
+ { id: 'open', label: `Open ${DS.toUpperCase()}`, color: SLA_COLORS.breached, n: m.open_now ?? 0 },
+ { id: 'closed', label: `Closed ${DS.toUpperCase()}`, color: pastel(CLOSED_COLOR), n: m.closed_in_window ?? 0 },
{ id: 'vehicles', label: 'ISP vehicles', color: '#E8954A', n: vehCount },
];
let html = rows.map((r) =>