mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2026-10-25 22:30:05 -05:00
changes
This commit is contained in:
1 parent
6ef3abe393
commit
ab7c9531ae
2 files changed
+204
-2
No files matched your search
@@ -1580,6 +1580,38 @@ let topAsnSortColumn = 'rate';
|
||||
let topAsnSortDirection = 'desc';
|
||||
let trafficCurrentPage = 1;
|
||||
let trafficPageSize = DEFAULT_TRAFFIC_PAGE_SIZE;
|
||||
const TOP_ASN_TABLE_COLUMNS = [
|
||||
{ group: "attribution" },
|
||||
{ group: "attribution" },
|
||||
{ group: "rates", numeric: true },
|
||||
{ group: "rates", numeric: true },
|
||||
{ group: "quality", numeric: true },
|
||||
{ group: "quality", numeric: true },
|
||||
{ group: "quality", numeric: true },
|
||||
{ group: "quality", numeric: true },
|
||||
{ group: "quality", numeric: true },
|
||||
{ group: "quality", numeric: true },
|
||||
{ group: "flows", numeric: true },
|
||||
];
|
||||
const TRAFFIC_TABLE_COLUMNS = [
|
||||
{ group: "identity" },
|
||||
{ group: "rates", numeric: true },
|
||||
{ group: "rates", numeric: true },
|
||||
{ group: "volume", numeric: true },
|
||||
{ group: "volume", numeric: true },
|
||||
{ group: "volume", numeric: true },
|
||||
{ group: "volume", numeric: true },
|
||||
{ group: "quality", numeric: true },
|
||||
{ group: "quality", numeric: true },
|
||||
{ group: "quality", numeric: true },
|
||||
{ group: "quality", numeric: true },
|
||||
{ group: "quality", numeric: true },
|
||||
{ group: "quality", numeric: true },
|
||||
{ group: "attribution" },
|
||||
{ group: "attribution" },
|
||||
{ group: "attribution" },
|
||||
{ group: "actions", action: true },
|
||||
];
|
||||
|
||||
function formatQooScore(score0to100, fallback = "-") {
|
||||
if (score0to100 === null || score0to100 === undefined) {
|
||||
@@ -1630,6 +1662,106 @@ function truncatedTrafficCell(text, cellClass) {
|
||||
return td;
|
||||
}
|
||||
|
||||
function applyCircuitTableCellChrome(cell, columns, startIndex, endIndex) {
|
||||
const descriptor = columns[startIndex];
|
||||
if (!descriptor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const group = String(descriptor.group || "default");
|
||||
cell.classList.add("lqos-circuit-table-cell", `lqos-circuit-colgroup-${group}`);
|
||||
if (descriptor.numeric) {
|
||||
cell.classList.add("lqos-circuit-cell-numeric");
|
||||
}
|
||||
if (descriptor.action) {
|
||||
cell.classList.add("lqos-circuit-cell-action");
|
||||
}
|
||||
|
||||
if (startIndex > 0 && columns[startIndex - 1]?.group !== group) {
|
||||
cell.classList.add("lqos-circuit-col-start");
|
||||
}
|
||||
if (endIndex < columns.length - 1 && columns[endIndex + 1]?.group !== group) {
|
||||
cell.classList.add("lqos-circuit-col-end");
|
||||
}
|
||||
|
||||
cell.dataset.columnStart = String(startIndex);
|
||||
cell.dataset.columnEnd = String(endIndex);
|
||||
}
|
||||
|
||||
function annotateCircuitDataTable(table, columns) {
|
||||
const headRow = table.tHead?.rows?.[0];
|
||||
if (headRow) {
|
||||
let columnIndex = 0;
|
||||
Array.from(headRow.cells).forEach((cell) => {
|
||||
const span = Math.max(1, Number(cell.colSpan) || 1);
|
||||
const startIndex = columnIndex;
|
||||
const endIndex = Math.min(columns.length - 1, startIndex + span - 1);
|
||||
applyCircuitTableCellChrome(cell, columns, startIndex, endIndex);
|
||||
columnIndex += span;
|
||||
});
|
||||
}
|
||||
|
||||
Array.from(table.tBodies).forEach((tbody) => {
|
||||
Array.from(tbody.rows).forEach((row) => {
|
||||
if (row.cells.length !== columns.length) {
|
||||
return;
|
||||
}
|
||||
Array.from(row.cells).forEach((cell, index) => {
|
||||
applyCircuitTableCellChrome(cell, columns, index, index);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
wireCircuitDataTableHover(table);
|
||||
}
|
||||
|
||||
function wireCircuitDataTableHover(table) {
|
||||
let activeStart = null;
|
||||
let activeEnd = null;
|
||||
|
||||
const paintRange = (start, end) => {
|
||||
Array.from(table.querySelectorAll("[data-column-start][data-column-end]")).forEach((cell) => {
|
||||
const cellStart = Number.parseInt(cell.dataset.columnStart || "", 10);
|
||||
const cellEnd = Number.parseInt(cell.dataset.columnEnd || "", 10);
|
||||
const shouldHighlight = Number.isFinite(cellStart)
|
||||
&& Number.isFinite(cellEnd)
|
||||
&& cellStart <= end
|
||||
&& cellEnd >= start;
|
||||
cell.classList.toggle("is-column-hover", shouldHighlight);
|
||||
});
|
||||
};
|
||||
|
||||
const clearRange = () => {
|
||||
activeStart = null;
|
||||
activeEnd = null;
|
||||
Array.from(table.querySelectorAll(".is-column-hover")).forEach((cell) => {
|
||||
cell.classList.remove("is-column-hover");
|
||||
});
|
||||
};
|
||||
|
||||
table.addEventListener("pointerover", (event) => {
|
||||
const cell = event.target.closest("th, td");
|
||||
if (!cell || !table.contains(cell)) {
|
||||
return;
|
||||
}
|
||||
const start = Number.parseInt(cell.dataset.columnStart || "", 10);
|
||||
const end = Number.parseInt(cell.dataset.columnEnd || "", 10);
|
||||
if (!Number.isFinite(start) || !Number.isFinite(end)) {
|
||||
return;
|
||||
}
|
||||
if (activeStart === start && activeEnd === end) {
|
||||
return;
|
||||
}
|
||||
activeStart = start;
|
||||
activeEnd = end;
|
||||
paintRange(start, end);
|
||||
});
|
||||
|
||||
table.addEventListener("pointerleave", () => {
|
||||
clearRange();
|
||||
});
|
||||
}
|
||||
|
||||
function visibleTrafficRows() {
|
||||
return Array.isArray(latestTrafficPage?.rows) ? latestTrafficPage.rows : [];
|
||||
}
|
||||
@@ -1735,7 +1867,7 @@ function renderTopAsnTab() {
|
||||
tableWrap.classList.add("lqos-table-wrap");
|
||||
|
||||
const table = document.createElement("table");
|
||||
table.classList.add("lqos-table", "lqos-table-tight", "lqos-circuit-traffic-table");
|
||||
table.classList.add("lqos-table", "lqos-table-tight", "lqos-circuit-traffic-table", "lqos-circuit-data-table");
|
||||
const thead = document.createElement("thead", "small");
|
||||
thead.style.fontSize = "0.8em";
|
||||
|
||||
@@ -1797,6 +1929,7 @@ function renderTopAsnTab() {
|
||||
}
|
||||
|
||||
table.appendChild(tbody);
|
||||
annotateCircuitDataTable(table, TOP_ASN_TABLE_COLUMNS);
|
||||
tableWrap.appendChild(table);
|
||||
clearDiv(target);
|
||||
target.appendChild(tableWrap);
|
||||
@@ -1818,7 +1951,7 @@ function renderTrafficTab() {
|
||||
tableWrap.classList.add("lqos-table-wrap");
|
||||
|
||||
let table = document.createElement("table");
|
||||
table.classList.add("lqos-table", "lqos-table-tight", "lqos-circuit-traffic-table");
|
||||
table.classList.add("lqos-table", "lqos-table-tight", "lqos-circuit-traffic-table", "lqos-circuit-data-table");
|
||||
let thead = document.createElement("thead", "small");
|
||||
thead.style.fontSize = "0.8em";
|
||||
|
||||
@@ -1903,6 +2036,7 @@ function renderTrafficTab() {
|
||||
}
|
||||
|
||||
table.appendChild(tbody);
|
||||
annotateCircuitDataTable(table, TRAFFIC_TABLE_COLUMNS);
|
||||
tableWrap.appendChild(table);
|
||||
clearDiv(target);
|
||||
target.appendChild(tableWrap);
|
||||
|
||||
@@ -1567,6 +1567,74 @@ h5 {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.lqos-circuit-data-table th,
|
||||
.lqos-circuit-data-table td {
|
||||
--lqos-circuit-group-tint: transparent;
|
||||
--lqos-circuit-hover-tint: transparent;
|
||||
background-image:
|
||||
linear-gradient(var(--lqos-circuit-hover-tint), var(--lqos-circuit-hover-tint)),
|
||||
linear-gradient(var(--lqos-circuit-group-tint), var(--lqos-circuit-group-tint));
|
||||
background-clip: padding-box;
|
||||
transition:
|
||||
background-color 140ms ease,
|
||||
border-color 140ms ease,
|
||||
box-shadow 140ms ease;
|
||||
}
|
||||
|
||||
.lqos-circuit-data-table thead th + th,
|
||||
.lqos-circuit-data-table tbody td + td {
|
||||
border-left: 1px solid color-mix(in srgb, var(--lqos-border) 42%, transparent);
|
||||
}
|
||||
|
||||
.lqos-circuit-data-table .lqos-circuit-col-start {
|
||||
border-left-color: color-mix(in srgb, var(--lqos-border) 92%, transparent);
|
||||
}
|
||||
|
||||
.lqos-circuit-data-table .lqos-circuit-colgroup-identity,
|
||||
.lqos-circuit-data-table .lqos-circuit-colgroup-actions {
|
||||
--lqos-circuit-group-tint: color-mix(in srgb, var(--lqos-surface) 14%, transparent);
|
||||
}
|
||||
|
||||
.lqos-circuit-data-table .lqos-circuit-colgroup-rates {
|
||||
--lqos-circuit-group-tint: color-mix(in srgb, var(--bs-info) 7%, transparent);
|
||||
}
|
||||
|
||||
.lqos-circuit-data-table .lqos-circuit-colgroup-volume {
|
||||
--lqos-circuit-group-tint: color-mix(in srgb, #d39f37 7%, transparent);
|
||||
}
|
||||
|
||||
.lqos-circuit-data-table .lqos-circuit-colgroup-quality {
|
||||
--lqos-circuit-group-tint: color-mix(in srgb, #2b8a57 7%, transparent);
|
||||
}
|
||||
|
||||
.lqos-circuit-data-table .lqos-circuit-colgroup-attribution,
|
||||
.lqos-circuit-data-table .lqos-circuit-colgroup-flows {
|
||||
--lqos-circuit-group-tint: color-mix(in srgb, var(--bs-secondary-color) 8%, transparent);
|
||||
}
|
||||
|
||||
.lqos-circuit-data-table .lqos-circuit-cell-numeric {
|
||||
text-align: right;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.lqos-circuit-data-table .lqos-circuit-cell-action {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.lqos-circuit-data-table .is-column-hover {
|
||||
--lqos-circuit-hover-tint: rgba(255, 255, 255, 0.035);
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.05),
|
||||
inset 0 0 0 1px color-mix(in srgb, var(--lqos-border) 70%, transparent);
|
||||
}
|
||||
|
||||
[data-bs-theme="light"] .lqos-circuit-data-table .is-column-hover {
|
||||
--lqos-circuit-hover-tint: rgba(17, 29, 45, 0.045);
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.28),
|
||||
inset 0 0 0 1px color-mix(in srgb, var(--lqos-border) 74%, transparent);
|
||||
}
|
||||
|
||||
.lqos-tree-stack {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
Reference in new issue
Block a user