html front end component for resource monitor
This commit is contained in:
parent
8921ac8d3d
commit
7722d2c305
|
|
@ -54,4 +54,3 @@ user_path_config-deprecated.txt
|
|||
/auth.json
|
||||
.DS_Store
|
||||
/.venv
|
||||
web/
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,23 @@
|
|||
/* fallback */
|
||||
@font-face {
|
||||
font-family: 'Material Icons';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url('material.woff2') format('woff2');
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
font-family: 'Material Icons';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
-webkit-font-feature-settings: 'liga';
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
Binary file not shown.
|
|
@ -0,0 +1,250 @@
|
|||
#chart-button {
|
||||
position: fixed !important;
|
||||
transition: bottom 0.6s ease-in-out, bottom 0.6s ease-in-out,
|
||||
right 0.6s ease-in-out;
|
||||
background-color: #00000096 !important;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2) !important;
|
||||
color: white !important;
|
||||
border-radius: 10px !important;
|
||||
width: 225px !important;
|
||||
height: 0px !important;
|
||||
z-index: 9998;
|
||||
}
|
||||
|
||||
#chart-button.show {
|
||||
height: 185px !important;
|
||||
}
|
||||
|
||||
#chart-button.bottom-right {
|
||||
bottom: 10px !important;
|
||||
right: -450px !important;
|
||||
}
|
||||
|
||||
#chart-button.bottom-left {
|
||||
bottom: 10px !important;
|
||||
right: calc(100vw + 30px + 225px) !important;
|
||||
}
|
||||
|
||||
#chart-button.bottom-center {
|
||||
bottom: -450px !important;
|
||||
right: calc(50vw - 85px) !important;
|
||||
}
|
||||
|
||||
#chart-button.top-right {
|
||||
bottom: calc(100vh - 10px - 185px) !important;
|
||||
right: -450px !important;
|
||||
}
|
||||
|
||||
#chart-button.top-left {
|
||||
bottom: calc(100vh - 10px - 185px) !important;
|
||||
right: calc(100vw + 30px + 225px) !important;
|
||||
}
|
||||
|
||||
#chart-button.top-center {
|
||||
bottom: calc(100vh + 10px + 185px) !important;
|
||||
right: calc(50vw - 85px) !important;
|
||||
}
|
||||
|
||||
#chart-button.left-center {
|
||||
right: calc(100vw + 30px + 225px) !important;
|
||||
bottom: calc(50vh - 85px) !important;
|
||||
}
|
||||
|
||||
#chart-button.right-center {
|
||||
right: -450px !important;
|
||||
bottom: calc(50vh - 85px) !important;
|
||||
}
|
||||
|
||||
#chart-button.bottom-right.active {
|
||||
right: 10px !important;
|
||||
}
|
||||
|
||||
#chart-button.bottom-left.active {
|
||||
right: calc(100vw - 30px - 225px) !important;
|
||||
}
|
||||
|
||||
#chart-button.bottom-center.active {
|
||||
bottom: calc(0vh + 10px) !important;
|
||||
}
|
||||
|
||||
#chart-button.top-right.active {
|
||||
right: 10px !important;
|
||||
}
|
||||
|
||||
#chart-button.top-left.active {
|
||||
right: calc(100vw - 30px - 225px) !important;
|
||||
}
|
||||
|
||||
#chart-button.top-center.active {
|
||||
bottom: calc(100vh - 10px - 185px) !important;
|
||||
}
|
||||
|
||||
#chart-button.left-center.active {
|
||||
right: calc(100vw - 30px - 225px) !important;
|
||||
}
|
||||
|
||||
#chart-button.right-center.active {
|
||||
right: 10px !important;
|
||||
}
|
||||
|
||||
.chart-row {
|
||||
padding: 5px 5px 0px 5px !important;
|
||||
text-align: right !important;
|
||||
margin-bottom: -10px !important;
|
||||
display: flex !important;
|
||||
justify-content: space-evenly !important;
|
||||
z-index: 9999 !important;
|
||||
position: relative !important;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.chart-col {
|
||||
flex: auto !important;
|
||||
}
|
||||
|
||||
.left-col a {
|
||||
width: 15px !important;
|
||||
cursor: pointer !important;
|
||||
border-radius: 4px !important;
|
||||
display: inline-block !important;
|
||||
text-align: center !important;
|
||||
color: #fff !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.left-col a:hover {
|
||||
background-color: #fff !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
|
||||
#chart-container {
|
||||
width: 225px;
|
||||
height: 145px;
|
||||
padding: 5px !important;
|
||||
}
|
||||
|
||||
#chart-container.line {
|
||||
width: 225px;
|
||||
padding: 5px !important;
|
||||
}
|
||||
|
||||
canvas.bar {
|
||||
height: 160px !important;
|
||||
min-width: 200px !important;
|
||||
}
|
||||
canvas.line {
|
||||
height: 145px !important;
|
||||
min-width: 200px !important;
|
||||
}
|
||||
|
||||
i {
|
||||
color: #fff !important; /* Adjust color */
|
||||
cursor: pointer !important; /* Change cursor to pointer on hover */
|
||||
}
|
||||
|
||||
.toggle-resources-button:hover {
|
||||
color: rgb(101, 101, 101) !important; /* Change color on hover */
|
||||
}
|
||||
|
||||
#settingsMenu {
|
||||
display: none; /* Hidden by default */
|
||||
position: absolute !important;
|
||||
transform: translateX(-50%) !important; /* Center alignment */
|
||||
background: #000000 !important;
|
||||
border: 0px solid #ddd !important;
|
||||
padding: 0px !important;
|
||||
border-radius: 6px !important;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1) !important;
|
||||
z-index: 1000 !important;
|
||||
opacity: 0 !important;
|
||||
transform: scale(0.8) translateY(-20px) !important; /* Initial hidden state */
|
||||
transition: opacity 1s ease, transform 0.3s ease !important;
|
||||
}
|
||||
|
||||
#settingsMenu.show {
|
||||
display: block !important; /* Show the menu */
|
||||
opacity: 1 !important;
|
||||
transform: scale(1) translateY(0) !important; /* Animate to visible state */
|
||||
}
|
||||
|
||||
.position-menu {
|
||||
display: grid !important;
|
||||
grid-template-columns: repeat(3, 1fr) !important;
|
||||
grid-template-rows: repeat(3, 1fr) !important;
|
||||
grid-gap: 0px !important;
|
||||
}
|
||||
|
||||
.position-btn > i {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.position-btn {
|
||||
color: #fff !important;
|
||||
padding: 6px !important;
|
||||
margin: 0px !important;
|
||||
font-size: 12px !important;
|
||||
cursor: pointer !important;
|
||||
border: 0px solid #ccc !important;
|
||||
background-color: transparent !important;
|
||||
border-radius: 4px !important;
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.position-btn:hover {
|
||||
background-color: #fff !important;
|
||||
}
|
||||
.position-btn:hover > i {
|
||||
color: #000 !important;
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
.left-col {
|
||||
text-align: left !important;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.left-col.text {
|
||||
margin-bottom: 5px !important;
|
||||
}
|
||||
|
||||
.settings-hr {
|
||||
width: 0px;
|
||||
margin-top: 0px !important;
|
||||
margin-bottom: 0px !important;
|
||||
transition: width 1s ease;
|
||||
}
|
||||
|
||||
.settings-hr.show {
|
||||
width: 100%;
|
||||
}
|
||||
#custom-legend {
|
||||
display: flex !important;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.custom-legend-item {
|
||||
margin-bottom: 5px !important;
|
||||
font-size: 14px !important;
|
||||
flex: auto !important;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.custom-legend-color {
|
||||
display: inline-block !important;
|
||||
width: 15px !important;
|
||||
height: 15px !important;
|
||||
margin-right: 10px !important;
|
||||
vertical-align: middle !important;
|
||||
}
|
||||
|
||||
.custom-legend-text {
|
||||
display: inline !important;
|
||||
vertical-align: middle !important;
|
||||
}
|
||||
|
||||
#show_resource_monitor {
|
||||
cursor: pointer !important;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 99 B |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 9.0 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,577 @@
|
|||
const { hostname } = window.location; // Gets the host without port
|
||||
const baseUrl = `http://${hostname}:5000`; // Append the port 5000
|
||||
const apiUrl = `${baseUrl}/gpu_usage/`;
|
||||
|
||||
const perfMonitorContainer = $("#perf-monitor-container");
|
||||
const chartButton = $("#chart-button");
|
||||
const closeButton = $("#close-button");
|
||||
|
||||
let intervalId; // Variable to store the interval ID
|
||||
// Function to start the interval
|
||||
function startInterval() {
|
||||
intervalId = setInterval(updateUsage, 500);
|
||||
}
|
||||
// Function to stop the interval
|
||||
function stopInterval() {
|
||||
if (intervalId) {
|
||||
clearInterval(intervalId);
|
||||
intervalId = null; // Optional: Reset intervalId to indicate no active interval
|
||||
}
|
||||
}
|
||||
shouldShowPerfMonitor = false;
|
||||
|
||||
function showPerfMonitor() {
|
||||
shouldShowPerfMonitor = !shouldShowPerfMonitor;
|
||||
if (shouldShowPerfMonitor === true) {
|
||||
startInterval();
|
||||
} else {
|
||||
stopInterval();
|
||||
}
|
||||
localStorage.setItem("shouldShowPerfMonitor", shouldShowPerfMonitor);
|
||||
chartButton.toggleClass("active");
|
||||
setTimeout(() => {
|
||||
chartButton.toggleClass("show");
|
||||
}, 300);
|
||||
}
|
||||
|
||||
// Define your color palette
|
||||
const colorPalette = [
|
||||
"rgb(240, 193, 90, 0.2)",
|
||||
"rgb(240, 142, 219, 0.2)",
|
||||
"rgb(24, 90, 219, 0.2)",
|
||||
"rgb(127, 161, 195, 0.2)",
|
||||
"rgb(128, 239, 145, 0.2)",
|
||||
"rgb(245, 245, 245, 0.2)",
|
||||
"rgb(240, 142, 219, 0.2)",
|
||||
];
|
||||
|
||||
const borderColors = [
|
||||
"rgb(240, 193, 90)",
|
||||
"rgb(240, 142, 219)",
|
||||
"rgb(24, 90, 219)",
|
||||
"rgb(127, 161, 195)",
|
||||
"rgb(128, 239, 145)",
|
||||
"rgb(245, 245, 245)",
|
||||
"rgb(240, 142, 219)",
|
||||
];
|
||||
|
||||
// Custom plugin to draw fixed labels in the middle of the chart area
|
||||
const fixedLabelPlugin = {
|
||||
id: "fixedLabelPlugin",
|
||||
afterDatasetsDraw(chart) {
|
||||
const { ctx, scales, data } = chart;
|
||||
ctx.save();
|
||||
|
||||
const centerX = scales.x.left + scales.x.width / 2;
|
||||
const labelPositions = [];
|
||||
|
||||
data.datasets[0].data.forEach((value, index) => {
|
||||
const yPos = chart.getDatasetMeta(0).data[index].y;
|
||||
|
||||
// Store yPos for positioning labels
|
||||
labelPositions.push({
|
||||
x: centerX,
|
||||
y: yPos,
|
||||
value: `${value.toFixed(2)}%`,
|
||||
});
|
||||
});
|
||||
|
||||
ctx.font = "12px Arial";
|
||||
ctx.fillStyle = "#FFFFFF";
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
|
||||
labelPositions.forEach((label) => {
|
||||
ctx.fillText(label.value, label.x, label.y);
|
||||
});
|
||||
|
||||
ctx.restore();
|
||||
},
|
||||
};
|
||||
const chartContainer = document.getElementById("chart-container");
|
||||
|
||||
let currentChart = null; // Track the current chart instance
|
||||
const MAX_DATA_POINTS = 50; // Number of data points to keep
|
||||
// Initialize the bar chart
|
||||
function initializeBarChart() {
|
||||
localStorage.setItem("active-chart", "bar");
|
||||
const existingCanvas = document.getElementById("usage-chart");
|
||||
if (existingCanvas) {
|
||||
chartContainer.removeChild(existingCanvas);
|
||||
}
|
||||
|
||||
// Create a new canvas element
|
||||
const newCanvas = document.createElement("canvas");
|
||||
newCanvas.id = "usage-chart";
|
||||
newCanvas.classList.add("bar"); // Add the class directly to the canvas element
|
||||
chartContainer.appendChild(newCanvas);
|
||||
|
||||
const ctx = newCanvas.getContext("2d");
|
||||
|
||||
currentChart = new Chart(ctx, {
|
||||
type: "bar",
|
||||
data: {
|
||||
labels: ["CPU", "RAM", "GPU", "VRAM", "HDD"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Usage",
|
||||
data: [0, 0, 0, 0, 0],
|
||||
barPercentage: 0.8, // Adjust space occupied by bars
|
||||
categoryPercentage: 1, // Adjust space between bars
|
||||
backgroundColor: function (context) {
|
||||
const value = context.dataset.data[context.dataIndex];
|
||||
return value > 90 ? "#D9534F" : colorPalette[context.dataIndex];
|
||||
},
|
||||
borderColor: function (context) {
|
||||
const value = context.dataset.data[context.dataIndex];
|
||||
return value > 90 ? "#D9534F" : borderColors[context.dataIndex];
|
||||
},
|
||||
borderWidth: 1.5,
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
indexAxis: "y", // Horizontal bars
|
||||
scales: {
|
||||
x: {
|
||||
grid: {
|
||||
display: false, // Hide all grid lines
|
||||
},
|
||||
border: {
|
||||
display: false, // Hide all grid lines
|
||||
},
|
||||
beginAtZero: true,
|
||||
max: 100,
|
||||
ticks: {
|
||||
color: "#ffffff",
|
||||
font: {
|
||||
weight: 600,
|
||||
},
|
||||
align: "center",
|
||||
callback: function (value, index, ticks) {
|
||||
return value + "%";
|
||||
},
|
||||
},
|
||||
},
|
||||
y: {
|
||||
grid: {
|
||||
display: false,
|
||||
},
|
||||
border: {
|
||||
color: "#ffffff30",
|
||||
width: 1, // Width of the axis border
|
||||
},
|
||||
ticks: {
|
||||
color: "#FFFFFF",
|
||||
crossAlign: "far",
|
||||
font: {
|
||||
weight: 600,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
tooltip: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
},
|
||||
plugins: [fixedLabelPlugin], // Register the custom plugins
|
||||
});
|
||||
|
||||
currentChart.options.animation = true;
|
||||
const legendContainer = document.getElementById("custom-legend");
|
||||
legendContainer.innerHTML = "";
|
||||
|
||||
document.getElementById("settingsMenu").classList.remove("show"); // Hide the menu
|
||||
window.addEventListener("resize", () => {
|
||||
currentChart.resize();
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize the line chart
|
||||
function initializeLineChart() {
|
||||
localStorage.setItem("active-chart", "line");
|
||||
const existingCanvas = document.getElementById("usage-chart");
|
||||
if (existingCanvas) {
|
||||
chartContainer.removeChild(existingCanvas);
|
||||
}
|
||||
|
||||
// Create a new canvas element
|
||||
const newCanvas = document.createElement("canvas");
|
||||
newCanvas.id = "usage-chart";
|
||||
newCanvas.classList.add("line"); // Add the class directly to the canvas element
|
||||
chartContainer.appendChild(newCanvas);
|
||||
|
||||
const ctx = newCanvas.getContext("2d");
|
||||
|
||||
// ctx.width = "225px";
|
||||
// ctx.height = "125px";
|
||||
currentChart = new Chart(ctx, {
|
||||
type: "line",
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [
|
||||
{
|
||||
label: "CPU",
|
||||
data: [],
|
||||
borderColor: function (context) {
|
||||
const dataset = context.dataset;
|
||||
const datasetIndex = context.datasetIndex;
|
||||
const shouldUseRed = dataset.data.some((value) => value > 90);
|
||||
|
||||
if (shouldUseRed) {
|
||||
generateCustomLegend();
|
||||
|
||||
return "#D9534F"; // Return red color if any value exceeds 90
|
||||
}
|
||||
return borderColors[datasetIndex % borderColors.length];
|
||||
},
|
||||
borderWidth: 1.5,
|
||||
backgroundColor: function (context) {
|
||||
const dataset = context.dataset;
|
||||
const datasetIndex = context.datasetIndex;
|
||||
const shouldUseRed = dataset.data.some((value) => value > 90);
|
||||
|
||||
if (shouldUseRed) {
|
||||
return "#D9534F"; // Return red color if any value exceeds 90
|
||||
}
|
||||
return colorPalette[datasetIndex % borderColors.length];
|
||||
},
|
||||
fill: false,
|
||||
tension: 0.1,
|
||||
},
|
||||
{
|
||||
label: "RAM",
|
||||
data: [],
|
||||
borderColor: function (context) {
|
||||
const dataset = context.dataset;
|
||||
const datasetIndex = context.datasetIndex;
|
||||
const shouldUseRed = dataset.data.some((value) => value > 90);
|
||||
|
||||
if (shouldUseRed) {
|
||||
generateCustomLegend();
|
||||
|
||||
return "#D9534F"; // Return red color if any value exceeds 90
|
||||
}
|
||||
return borderColors[datasetIndex % borderColors.length];
|
||||
},
|
||||
borderWidth: 1.5,
|
||||
backgroundColor: function (context) {
|
||||
const dataset = context.dataset;
|
||||
const datasetIndex = context.datasetIndex;
|
||||
const shouldUseRed = dataset.data.some((value) => value > 90);
|
||||
|
||||
if (shouldUseRed) {
|
||||
return "#D9534F"; // Return red color if any value exceeds 90
|
||||
}
|
||||
return colorPalette[datasetIndex % borderColors.length];
|
||||
},
|
||||
fill: false,
|
||||
tension: 0.1,
|
||||
},
|
||||
{
|
||||
label: "GPU",
|
||||
data: [],
|
||||
borderColor: function (context) {
|
||||
const dataset = context.dataset;
|
||||
const datasetIndex = context.datasetIndex;
|
||||
const shouldUseRed = dataset.data.some((value) => value > 90);
|
||||
|
||||
if (shouldUseRed) {
|
||||
generateCustomLegend();
|
||||
|
||||
return "#D9534F"; // Return red color if any value exceeds 90
|
||||
}
|
||||
return borderColors[datasetIndex % borderColors.length];
|
||||
},
|
||||
borderWidth: 1.5,
|
||||
backgroundColor: function (context) {
|
||||
const dataset = context.dataset;
|
||||
const datasetIndex = context.datasetIndex;
|
||||
const shouldUseRed = dataset.data.some((value) => value > 90);
|
||||
|
||||
if (shouldUseRed) {
|
||||
return "#D9534F"; // Return red color if any value exceeds 90
|
||||
}
|
||||
return colorPalette[datasetIndex % borderColors.length];
|
||||
},
|
||||
fill: false,
|
||||
tension: 0.1,
|
||||
},
|
||||
{
|
||||
label: "VRAM",
|
||||
data: [],
|
||||
borderColor: function (context) {
|
||||
const dataset = context.dataset;
|
||||
const datasetIndex = context.datasetIndex;
|
||||
const shouldUseRed = dataset.data.some((value) => value > 90);
|
||||
|
||||
if (shouldUseRed) {
|
||||
generateCustomLegend();
|
||||
|
||||
return "#D9534F"; // Return red color if any value exceeds 90
|
||||
}
|
||||
return borderColors[datasetIndex % borderColors.length];
|
||||
},
|
||||
borderWidth: 1.5,
|
||||
backgroundColor: function (context) {
|
||||
const dataset = context.dataset;
|
||||
const datasetIndex = context.datasetIndex;
|
||||
const shouldUseRed = dataset.data.some((value) => value > 90);
|
||||
|
||||
if (shouldUseRed) {
|
||||
return "#D9534F"; // Return red color if any value exceeds 90
|
||||
}
|
||||
return colorPalette[datasetIndex % borderColors.length];
|
||||
},
|
||||
fill: false,
|
||||
tension: 0.1,
|
||||
},
|
||||
{
|
||||
label: "HDD",
|
||||
data: [],
|
||||
borderColor: function (context) {
|
||||
const dataset = context.dataset;
|
||||
const datasetIndex = context.datasetIndex;
|
||||
const shouldUseRed = dataset.data.some((value) => value > 90);
|
||||
|
||||
if (shouldUseRed) {
|
||||
generateCustomLegend();
|
||||
return "#D9534F"; // Return red color if any value exceeds 90
|
||||
}
|
||||
return borderColors[datasetIndex % borderColors.length];
|
||||
},
|
||||
borderWidth: 1.5,
|
||||
backgroundColor: function (context) {
|
||||
const dataset = context.dataset;
|
||||
const datasetIndex = context.datasetIndex;
|
||||
const shouldUseRed = dataset.data.some((value) => value > 90);
|
||||
|
||||
if (shouldUseRed) {
|
||||
return "#D9534F"; // Return red color if any value exceeds 90
|
||||
}
|
||||
return colorPalette[datasetIndex % borderColors.length];
|
||||
},
|
||||
fill: false,
|
||||
tension: 0.1,
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
animation: {
|
||||
enabled: false,
|
||||
tension: {
|
||||
duration: 1000,
|
||||
easing: "linear",
|
||||
from: 1,
|
||||
to: 0,
|
||||
loop: true,
|
||||
},
|
||||
},
|
||||
elements: {
|
||||
point: {
|
||||
radius: 0,
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
ticks: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
max: 100,
|
||||
ticks: {
|
||||
callback: function (value, index, ticks) {
|
||||
return value + "%";
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: true,
|
||||
labels: {
|
||||
generateLabels: false,
|
||||
},
|
||||
},
|
||||
title: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
function generateCustomLegend() {
|
||||
const legendContainer = document.getElementById("custom-legend");
|
||||
legendContainer.innerHTML = "";
|
||||
|
||||
currentChart.data.datasets.forEach((dataset, index) => {
|
||||
const legendItem = document.createElement("div");
|
||||
legendItem.className = "custom-legend-item";
|
||||
|
||||
// Create text element
|
||||
const legendText = document.createElement("span");
|
||||
legendText.className = "custom-legend-text";
|
||||
legendText.textContent = dataset.label;
|
||||
const shouldUseRed = dataset.data.some((value) => value > 90);
|
||||
legendText.style.color = shouldUseRed
|
||||
? "#D9534F"
|
||||
: `${borderColors[index]}`;
|
||||
|
||||
legendText.style.fontWeight = shouldUseRed ? "700" : `400`;
|
||||
|
||||
legendItem.appendChild(legendText);
|
||||
legendContainer.appendChild(legendItem);
|
||||
});
|
||||
}
|
||||
currentChart.options.animation = false;
|
||||
generateCustomLegend();
|
||||
document.getElementById("settingsMenu").classList.remove("show"); // Hide the menu
|
||||
|
||||
window.addEventListener("resize", () => {
|
||||
currentChart.resize();
|
||||
});
|
||||
}
|
||||
|
||||
async function updateUsage() {
|
||||
try {
|
||||
const response = await fetch(apiUrl);
|
||||
const data = await response.json();
|
||||
const timestamp = new Date();
|
||||
|
||||
if (currentChart) {
|
||||
if (currentChart.config.type === "bar") {
|
||||
// Update data for bar chart
|
||||
currentChart.data.datasets[0].data = [
|
||||
data.cpu,
|
||||
data.memory,
|
||||
data.gpu,
|
||||
data.vram,
|
||||
data.hdd,
|
||||
];
|
||||
} else if (currentChart.config.type === "line") {
|
||||
// Update data for line chart
|
||||
currentChart.data.labels.push(timestamp);
|
||||
currentChart.data.datasets[0].data.push(data.cpu);
|
||||
currentChart.data.datasets[1].data.push(data.memory);
|
||||
currentChart.data.datasets[2].data.push(data.gpu);
|
||||
currentChart.data.datasets[3].data.push(data.vram);
|
||||
currentChart.data.datasets[4].data.push(data.hdd);
|
||||
|
||||
// Prune old data if the number of points exceeds the limit
|
||||
if (currentChart.data.labels.length > MAX_DATA_POINTS) {
|
||||
currentChart.data.labels.shift(); // Remove the oldest label
|
||||
currentChart.data.datasets.forEach((dataset) => dataset.data.shift()); // Remove the oldest data points
|
||||
}
|
||||
}
|
||||
|
||||
// Update the chart with new data
|
||||
currentChart.update();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch usage data.", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Show or hide the settings menu when the settings icon is clicked
|
||||
document
|
||||
.getElementById("popupTrigger")
|
||||
.addEventListener("click", function (event) {
|
||||
const settingsMenu = document.getElementById("settingsMenu");
|
||||
settingsMenu.classList.toggle("show"); // Toggle the 'show' class for animation
|
||||
|
||||
setTimeout(() => {
|
||||
const settingsMenuHr = document.getElementById("settings-hr");
|
||||
settingsMenuHr.classList.add("show"); // Toggle the 'show' class for animation
|
||||
}, 300);
|
||||
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
// Hide the settings menu when the close button is clicked
|
||||
document.getElementById("close-button").addEventListener("click", function () {
|
||||
document.getElementById("settingsMenu").classList.remove("show"); // Hide the menu
|
||||
});
|
||||
|
||||
// Hide the settings menu when clicking outside
|
||||
window.addEventListener("click", function (e) {
|
||||
const settingsMenu = document.getElementById("settingsMenu");
|
||||
const trigger = document.getElementById("popupTrigger");
|
||||
if (!settingsMenu.contains(e.target) && e.target !== trigger) {
|
||||
settingsMenu.classList.remove("show"); // Hide the menu if clicking outside
|
||||
}
|
||||
});
|
||||
|
||||
document.querySelectorAll(".position-btn").forEach((button) => {
|
||||
button.addEventListener("click", function () {
|
||||
const position = this.id;
|
||||
// Remove all possible position classes
|
||||
const chartButton = document.getElementById("chart-button");
|
||||
chartButton.classList.remove(
|
||||
"bottom-right",
|
||||
"bottom-left",
|
||||
"top-right",
|
||||
"top-left",
|
||||
"top-center",
|
||||
"bottom-center",
|
||||
"left-center",
|
||||
"right-center"
|
||||
);
|
||||
setMonitorPosition(position);
|
||||
|
||||
// Save the position to localStorage
|
||||
localStorage.setItem("perf-monitor-position", position);
|
||||
});
|
||||
});
|
||||
|
||||
// Set the initial position based on localStorage
|
||||
const perfMonitordisplayed = JSON.parse(
|
||||
localStorage.getItem("shouldShowPerfMonitor")
|
||||
);
|
||||
|
||||
const savedPosition =
|
||||
localStorage.getItem("perf-monitor-position") ?? "bottom-right";
|
||||
|
||||
setMonitorPosition(savedPosition);
|
||||
|
||||
const savedChart = localStorage.getItem("active-chart") ?? "bar";
|
||||
|
||||
if (perfMonitordisplayed == true) {
|
||||
// Remove previous position classes
|
||||
const chartButton = document.getElementById("chart-button");
|
||||
chartButton.classList.remove(
|
||||
"bottom-right",
|
||||
"bottom-left",
|
||||
"top-right",
|
||||
"top-left",
|
||||
"top-center",
|
||||
"bottom-center",
|
||||
"left-center",
|
||||
"right-center"
|
||||
);
|
||||
setMonitorPosition(savedPosition);
|
||||
setTimeout(() => {
|
||||
showPerfMonitor();
|
||||
if (savedChart == "bar") {
|
||||
initializeBarChart();
|
||||
} else {
|
||||
initializeLineChart();
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function setMonitorPosition(position) {
|
||||
chartButton.addClass(position);
|
||||
const settingsMenu = document.getElementById("settingsMenu");
|
||||
settingsMenu.classList.remove("show"); // Hide the menu if visible
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<div id="perf-monitor-container"></div>
|
||||
<img
|
||||
src="/file=web/assets/img/clearfix.png"
|
||||
onload="{
|
||||
var footer = document.querySelector('footer');
|
||||
var link = document.createElement('a');
|
||||
|
||||
// Add multiple classes correctly using the spread operator
|
||||
link.classList.add('built-with', 'svelte-1ax1toq');
|
||||
link.id = 'show_resource_monitor';
|
||||
link.text = 'Resource Monitor';
|
||||
link.onclick = function() { showPerfMonitor(); }; // Use function reference instead of string
|
||||
|
||||
var linkImg = document.createElement('img')
|
||||
linkImg.src = '/file=web/assets/img/monitor.svg';
|
||||
linkImg.classList.add('svelte-1ax1toq')
|
||||
link.appendChild(linkImg);
|
||||
footer.appendChild(link);
|
||||
|
||||
var script = document.createElement('script');
|
||||
script.src = '/file=web/assets/js/jquery-3.7.1.min.js';
|
||||
document.body.appendChild(script);
|
||||
|
||||
var script = document.createElement('script');
|
||||
script.src = '/file=web/assets/js/chart.js';
|
||||
document.body.appendChild(script);
|
||||
|
||||
async function loadHtmlContent() {
|
||||
const response = await fetch('/file=web/templates/perf-monitor/perf-monitor.html');
|
||||
document.getElementById('perf-monitor-container').innerHTML = await response.text();
|
||||
|
||||
var styles = document.createElement('link');
|
||||
styles.href = '/file=web/assets/css/styles.css';
|
||||
styles.property = 'stylesheet'
|
||||
styles.rel = 'stylesheet'
|
||||
document.body.appendChild(styles);
|
||||
|
||||
var fa = document.createElement('link');
|
||||
fa.href = '/file=web/assets/css/material-icon.css';
|
||||
fa.property = 'stylesheet'
|
||||
fa.rel = 'stylesheet'
|
||||
document.body.appendChild(fa);
|
||||
|
||||
|
||||
|
||||
var script = document.createElement('script');
|
||||
script.src = '/file=web/assets/js/chartjs-plugin-datalabels.js';
|
||||
document.body.appendChild(script);
|
||||
|
||||
var script = document.createElement('script');
|
||||
script.src = '/file=web/assets/js/perf-monitor.js';
|
||||
document.body.appendChild(script);
|
||||
}
|
||||
loadHtmlContent();
|
||||
}"
|
||||
/>
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<div id="chart-button">
|
||||
<div class="chart-row">
|
||||
<div class="left-col">
|
||||
<i class="material-icons" id="popupTrigger">settings</i>
|
||||
<div id="settingsMenu" class="settings-menu">
|
||||
<div class="left-col text">
|
||||
Layout : <a onclick="initializeBarChart()"> 1</a> |
|
||||
<a onclick="initializeLineChart()"> 2</a>
|
||||
</div>
|
||||
<hr id="settings-hr" class="settings-hr" />
|
||||
<span>Position:</span>
|
||||
<div id="positionMenu" class="position-menu">
|
||||
<button class="position-btn" id="top-left">
|
||||
<i class="material-icons">north_west</i>
|
||||
</button>
|
||||
<button class="position-btn" id="top-center">
|
||||
<i class="material-icons">north</i>
|
||||
</button>
|
||||
<button class="position-btn" id="top-right">
|
||||
<i class="material-icons">north_east</i>
|
||||
</button>
|
||||
<button class="position-btn" id="left-center">
|
||||
<i class="material-icons">west</i>
|
||||
</button>
|
||||
<button class="position-btn" id="center">
|
||||
<i class="material-icons">radio_button_checked</i>
|
||||
</button>
|
||||
<button class="position-btn" id="right-center">
|
||||
<i class="material-icons">east</i>
|
||||
</button>
|
||||
<button class="position-btn" id="bottom-left">
|
||||
<i class="material-icons">south_west</i>
|
||||
</button>
|
||||
<button class="position-btn" id="bottom-center">
|
||||
<i class="material-icons">south</i>
|
||||
</button>
|
||||
<button class="position-btn" id="bottom-right">
|
||||
<i class="material-icons">south_east</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="chart-col">
|
||||
<i class="material-icons" id="close-button" onclick="showPerfMonitor()"
|
||||
>close</i
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div id="chart-container">
|
||||
<canvas id="usage-chart" style="width: 100%; height: 100%"></canvas>
|
||||
</div>
|
||||
<div id="custom-legend"></div>
|
||||
</div>
|
||||
</div>
|
||||
Loading…
Reference in New Issue