Merge branch 'main' of gitlab.fdmci.hva.nl:propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-3/qaajeeqiinii59

This commit is contained in:
Dano van den Bosch
2024-04-02 13:09:16 +02:00
34 changed files with 1361 additions and 283 deletions

View File

@@ -13,6 +13,7 @@ class GaugeGroup {
this.element.innerHTML = `
<h2 class="groupTitle">${this.nodeId} - ${this.location}</h2>
<div class="Node">
<img src="arrow.png" class="arrowimg" onclick="toggleGraph('${this.nodeId}')">
${Array(this.gaugesCount).fill().map((_, i) => `
<div class="Sensorvalues">
<div id="gaugeContainer${this.nodeId}_${i+1}" class="gaugeContainer">
@@ -25,6 +26,9 @@ class GaugeGroup {
</div>
`).join('')}
</div>
<div class="plotly-container">
<div id="liveGraph${this.nodeId}" class="disabled" ></div>
</div>
`;
// Append the new div to the body

View File

@@ -0,0 +1,157 @@
class Graph {
constructor(id) {
this.id = "graph" + id;
this.timeArray = [];
this.tempArray = [];
this.humiArray = [];
this.eco2Array = [];
this.tvocArray = [];
}
// Function to create a graph
makeGraph(line, lineColor, name) {
let div = document.createElement("div");
div.setAttribute("id", this.id);
document.body.appendChild(div);
let lineArray;
switch (line) {
case "temp":
lineArray = this.tempArray;
break;
case "humi":
lineArray = this.humiArray;
break;
case "eco2":
lineArray = this.eco2Array;
break;
case "tvoc":
lineArray = this.tvocArray;
break;
default:
console.error("Invalid line");
}
Plotly.plot(this.id, [
{
x: this.timeArray,
y: lineArray,
mode: "lines",
line: { color: lineColor },
name: name,
},
]);
}
updateData(type, value, timestamp) {
// this.timeArray.push(timestamp);
switch (type) {
case "Temp":
this.tempArray.push(value);
break;
case "Humi":
this.humiArray.push(value);
break;
case "eCO2":
this.eco2Array.push(value / 10);
break;
case "TVOC":
this.tvocArray.push(value / 10);
break;
default:
console.error("Invalid type");
}
}
updateGraph() {
let update = {
x: [this.timeArray],
y: [this.tempArray, this.humiArray, this.eco2Array, this.tvocArray],
};
console.log(update);
Plotly.update(this.id, update);
}
}
class LiveGraph extends Graph {
// Constructor to initialize the graph
constructor(id) {
super(id);
this.tempArray = [];
this.humiArray = [];
this.eco2Array = [];
this.tvocArray = [];
this.cnt = 0;
}
// Function to update the graph with new values got from updateData function
updateGraph() {
let time = new Date();
this.timeArray.push(new Date());
let update = {
x: [[this.timeArray]],
y: [
[this.tempArray],
[this.humiArray],
[this.eco2Array],
[this.tvocArray],
],
};
let olderTime = time.setMinutes(time.getMinutes() - 1);
let futureTime = time.setMinutes(time.getMinutes() + 1);
let minuteView = {
xaxis: {
type: "date",
range: [olderTime, futureTime],
},
};
Plotly.relayout(this.id, minuteView);
if (this.cnt === 10) clearInterval(interval);
}
// function to get the new data for graph
updateData(temperature, humidity, eCO2, TVOC) {
// Update the graph
this.tempArray.push(temperature);
this.humiArray.push(humidity);
this.eco2Array.push(eCO2 / 10);
this.tvocArray.push(TVOC / 10);
}
}
class DataProcessor {
constructor(data) {
this.data = data;
this.graph;
}
// You can add more filtering methods based on different criteria if needed
update(data) {
this.data = data;
console.log("Data updated");
console.log(data);
}
makeGraph() {
this.graph = new Graph(1);
this.graph.makeGraph("temp", "red", "Temperature");
this.graph.makeGraph("humi", "blue", "Humidity");
this.graph.makeGraph("eco2", "green", "eCO2");
this.graph.makeGraph("tvoc", "#F5G644", "TVOC");
}
updateGraph() {
this.graph.timeArray = [];
this.graph.tempArray = [];
this.graph.humiArray = [];
this.graph.eco2Array = [];
this.graph.tvocArray = [];
for (let i = 0; i < this.data.length; i++) {
if (i % 4 == 0){
this.graph.timeArray.push(this.data[i].TimeStamp);
}
this.graph.updateData(this.data[i].Type, this.data[i].Value, this.data[i].TimeStamp);
console.log(this.data[i].Type, this.data[i].Value, this.data[i].TimeStamp);
}
this.graph.updateGraph();
}
}

View File

@@ -0,0 +1,145 @@
// Sample data - you can replace this with your actual dataset
const data = [];
processor = new DataProcessor();
let link;
// Function to create checkbox with label
function createCheckBox(id, label) {
const checkbox = document.createElement("input");
checkbox.setAttribute("type", "checkbox");
checkbox.setAttribute("id", id);
checkbox.setAttribute("class", "checkbox");
const checkboxLabel = document.createElement("label");
checkboxLabel.setAttribute("for", id);
checkboxLabel.textContent = label;
return { checkbox, checkboxLabel };
}
// Create HTML input elements for user input
const container = document.createElement("div");
container.setAttribute("class", "container");
const dataTypesContainer = document.createElement("div");
dataTypesContainer.setAttribute("class", "data-types");
const temperatureCheckbox = createCheckBox("Temp", "Temperature");
const humidityCheckbox = createCheckBox("Humi", "Humidity");
const eco2Checkbox = createCheckBox("eCO2", "eCO2");
const tvocCheckbox = createCheckBox("TVOC", "TVOC");
dataTypesContainer.appendChild(temperatureCheckbox.checkbox);
dataTypesContainer.appendChild(temperatureCheckbox.checkboxLabel);
dataTypesContainer.appendChild(humidityCheckbox.checkbox);
dataTypesContainer.appendChild(humidityCheckbox.checkboxLabel);
dataTypesContainer.appendChild(eco2Checkbox.checkbox);
dataTypesContainer.appendChild(eco2Checkbox.checkboxLabel);
dataTypesContainer.appendChild(tvocCheckbox.checkbox);
dataTypesContainer.appendChild(tvocCheckbox.checkboxLabel);
container.appendChild(dataTypesContainer);
const filterButton = document.createElement("button");
filterButton.textContent = "Filter Data";
filterButton.setAttribute("class", "filter-button");
filterButton.addEventListener("click", () => {
const startDate = document.getElementById("start-date").value
const endDate = document.getElementById("end-date").value
const selectedNodes = document
.getElementById("node-input")
.value.split(",")
.map((node) => node.trim());
const selectedFields = [];
const checkboxes = [
temperatureCheckbox,
humidityCheckbox,
eco2Checkbox,
tvocCheckbox
];
checkboxes.forEach((checkbox) => {
if (checkbox.checkbox.checked) {
selectedFields.push(String(checkbox.checkbox.id));
}
});
let selectedFieldsString = selectedFields.map(String);
let formattedString = '(' + selectedFieldsString.map(item => `'${item}'`).join(', ') + ')';
const filteredData = [
startDate,
endDate,
selectedNodes,
formattedString
];
console.log(filteredData);
console.log(startDate, endDate, selectedNodes);
generateLink(startDate, endDate, selectedNodes, formattedString);
fetchData();
});
const dateFilter = document.createElement("div");
dateFilter.setAttribute("class", "date-filter");
const startDateInput = document.createElement("input");
startDateInput.setAttribute("type", "datetime-local");
startDateInput.setAttribute("id", "start-date");
startDateInput.setAttribute("class", "input-field");
const endDateInput = document.createElement("input");
endDateInput.setAttribute("type", "datetime-local");
endDateInput.setAttribute("id", "end-date");
endDateInput.setAttribute("class", "input-field");
dateFilter.appendChild(startDateInput);
dateFilter.appendChild(endDateInput);
container.appendChild(dateFilter);
const nodeFilter = document.createElement("div");
nodeFilter.setAttribute("class", "node-filter");
const nodeInput = document.createElement("input");
nodeInput.setAttribute("type", "text");
nodeInput.setAttribute("placeholder", "Enter Node Name (* for all)");
nodeInput.setAttribute("id", "node-input");
nodeInput.setAttribute("class", "input-field");
nodeFilter.appendChild(nodeInput);
container.appendChild(nodeFilter);
container.appendChild(filterButton);
document.body.appendChild(container);
// Function to get the link for the get request
function generateLink(dateStart, dateEnd, node, dataTypes) {
const baseUrl = 'http://145.92.8.114/getMeasurements';
const formattedDateStart = new Date(dateStart).toISOString().replace('T', '%20');
const formattedDateEnd = new Date(dateEnd).toISOString().replace('T', '%20');
link = `${baseUrl}?dateStart=${formattedDateStart}&dateEnd=${formattedDateEnd}&node=${node}&dataType=${dataTypes}`;
console.log(link);
}
processor.makeGraph();
// Get request to fetch data from the server
function fetchData() {
fetch(link)
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then((data) => {
processor.update(data);
processor.updateGraph();
})
.catch((error) => {
console.error("Error fetching data:", error);
});
}

View File

@@ -6,6 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles/graph-styles.css">
<title>Graphs</title>
<script src="https://cdn.plot.ly/plotly-latest.min.js" charset="utf-8"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
@@ -22,12 +23,13 @@
<li class="nav-item">
<a href="settings.html" class="nav-link">Settings</a>
</li>
<li class="nav-item">
<a href="questions-dashboard.html" class="nav-link">Questions</a>
</ul>
</nav>
<body>
<script src="graph-main.js"></script>
<script src="graph-classes.js"></script>
<script src="graph-main.js"></script>
</body>
</html>

View File

@@ -6,6 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles/dashboard-styles.css">
<title>Gauges</title>
<script src="https://cdn.plot.ly/plotly-latest.min.js" charset="utf-8"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
@@ -24,22 +25,13 @@
<li class="nav-item">
<a href="settings.html" class="nav-link">Settings</a>
</li>
<div id="editNodeInformation">
<button id="settings" onclick="settings()">Settings</button>
</div>
<div id="editNode">
<textarea id="inputName"></textarea>
<textarea id="inputLocation"></textarea>
<select id="mySelect"></select>
<button id="button" onclick="changeText()">Change Information</button>
<p id="text">Status updating</p>
</div>
</ul>
</nav>
<body>
<body>
<script src="GaugGroup.js"></script>
<script src="graph-classes.js"></script>
<script src="main.js"></script>
<script src="text.js"></script>
<script src="liveGraph.js"></script>

View File

@@ -54,15 +54,16 @@ class liveGraph {
}
// Function to update the graph with new values got from updateData function
updateGraph() {
updateGraph(temperature, humidity, eCO2, TVOC) {
// Update the graph
this.tempArray.push(temperature);
this.humiArray.push(humidity);
this.eco2Array.push(eCO2 / 10);
this.tvocArray.push(TVOC / 10);
let time = new Date();
this.timeArray.push(new Date());
let update = {
x: [[this.timeArray]],
y: [[this.tempArray], [this.humiArray], [this.eco2Array], [this.tvocArray]]
};
let olderTime = time.setMinutes(time.getMinutes() - 1);
let futureTime = time.setMinutes(time.getMinutes() + 1);
let minuteView = {
@@ -75,11 +76,4 @@ class liveGraph {
if (this.cnt === 10) clearInterval(interval);
}
// function to get the new data for graph
updateData(temperature, humidity, eCO2, TVOC) {
// Update the graph
this.tempArray.push(temperature);
this.humiArray.push(humidity);
this.eco2Array.push(eCO2 / 10);
this.tvocArray.push(TVOC / 10);
}
}

View File

@@ -4,7 +4,7 @@ const sensorData = {};
let liveGraphs = [];
let nodeArray = [];
let nodeDict = {};
let graphArray = [];
// letiables
let intervalDelay = 5000;
let amountOfNodes = 3;
@@ -66,6 +66,7 @@ async function handleIncomingData(data) {
sensorData[data.node].updateGauge(2, humidity);
sensorData[data.node].updateGauge(3, CO2);
sensorData[data.node].updateGauge(4, TVOC);
sensorData[data.node].graph.updateGraph(temperature, humidity, CO2, TVOC);
} else {
console.error('No sensor data for node:', nodeName);
}
@@ -98,31 +99,14 @@ async function nodeAdressHandler(node, dataTypes) {
let gaugeGroup = new GaugeGroup(nodeName, nodeLocation, dataTypes.length, maxGaugeValues, dataTypes);
sensorData[node] = gaugeGroup;
gaugeGroup.graph = new liveGraph(nodeName);
sensorData[node] = gaugeGroup;
gaugeGroup.graph.makeGraph();
sensorData[node] = gaugeGroup;
}
}
function createGauge(node, dataType) {
// Create a new gauge here
let gauge = new GaugeGroup(node, dataType); // Assuming Gauge is the name of the class
sensorData[node][dataType] = gauge; // Store the gauge in the sensorData object for later use
}
//function for making the html elements for the following html code
function nodeData(data) {
let nodeData = document.createElement("div");
nodeData.innerHTML = data;
// nodeData.setAttribute("id", "node" + node);
document.body.appendChild(nodeData);
// console.log("Hello World");
}
function updateGauge(nodeNumber, dataType, value) {
// Update the gauge here
let gauge = sensorData[nodeNumber][dataType]; // Get the gauge from the sensorData object
gauge.update(value); // Assuming the Gauge class has an update method
}
function getNodeInfo(node){
return fetch("http://145.92.8.114/getNodeInfo?macAdress=" + node)
@@ -142,4 +126,19 @@ function getNodeInfo(node){
};
})
}
// create a function to enable and disable the graph using .disabled using the id of the graph
function toggleGraph(nodeId) {
let graph = document.querySelector('#liveGraph' + nodeId);
if (graph) {
if (graph.classList.contains('disabled')) {
graph.classList.remove('disabled');
} else {
graph.classList.add('disabled');
}
} else {
console.error('No element found with id: liveGraph' + nodeId);
}
}

View File

@@ -0,0 +1,27 @@
class ChartConfigClass{
constructor(data, text){
this.data = data
this.text = text
}
get chartConfig() {
return{
type: 'pie',
data: this.data,
options: {
responsive: true,
legend: {
position: 'top',
},
title: {
display: true,
text: this.text
},
animation: {
animateScale: true,
animateRotate: true
}
}
}
}
}

View File

@@ -0,0 +1,27 @@
class QuestionCreationClass {
constructor(data, label) {
this.data = data;
this.label = label;
}
get questionData() {
return {
labels: this.label,
datasets: [{
label: 'Responses',
data: this.data,
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)'
],
borderWidth: 1
}]
};
}
}

View File

@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles/questions-dashboard-styles.css">
<title>Graphs</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<nav class="navbar">
<ul class="navbar-nav">
<li class="nav-item">
<a href="index.html" class="nav-link">Dashboard</a>
</li>
<li class="nav-item">
<a href="graphs.html" class="nav-link">Graphs</a>
</li>
<li class="nav-item">
<a href="settings.html" class="nav-link">Settings</a>
</li>
<li class="nav-item">
<a href="questions-dashboard.html" class="nav-link">Questions</a>
</ul>
</nav>
<body>
<div class="chart-container">
<div class="chart">
<h2>Question 1: How clean are the toilets?</h2>
<canvas id="chart1"></canvas>
</div>
<div class="chart">
<h2>Question 2: How clean is the study area?</h2>
<canvas id="chart2"></canvas>
</div>
<div class="chart">
<h2>Question 3: What do you think of the temperature in the study area?</h2>
<canvas id="chart3"></canvas>
</div>
<div class="chart">
<h2>Question 4: How crowded would you say the study area is?</h2>
<canvas id="chart4"></canvas>
</div>
<div class="chart">
<h2>Question 5: Is there enough help available on the 5th floor?</h2>
<canvas id="chart5"></canvas>
</div>
<!-- Add more questions and canvas elements as needed -->
</div>
<script src="questions-chart-class.js"></script>
<script src="questions-creation-class.js"></script>
<script src="questions-main.js"></script>
</body>
</html>

View File

@@ -0,0 +1,54 @@
//For now create dummy data to show on the website.
let dummydata1 = [40, 30, 20];
let questionOptionsDummy1 = ['disgusting','clean', 'fine'];
let dummydata2 = [25, 35, 40];
let questionOptionsDummy2 = ['disgusting', 'clean', 'normal'];
let dummydata3 = [30, 20, 20];
let questionOptionsDummy3 = ['cold', 'perfect', 'hot'];
let dummydata4 = [30, 20, 20];
let questionOptionsDummy4 = ['really crowded','not at all', 'its fine', ];
let dummydata5 = [30, 20, 20];
let questionOptionsDummy5 = ['no','yes', 'decently'];
//make arrays to store data.
let chartConfigArray = [];
let textArray = [];
let questionArray = [];
let questionOptionsDummy = [];
let dummydata = [];
//Go along the array's to fetch data, and push this in a class.
for (let i = 0; i < 5; i++) {
dummydata.push(dummydata1, dummydata2, dummydata3, dummydata4, dummydata5);
questionOptionsDummy.push(questionOptionsDummy1, questionOptionsDummy2, questionOptionsDummy3, questionOptionsDummy4, questionOptionsDummy5);
questionArray.push(new QuestionCreationClass(dummydata[i], questionOptionsDummy[i]));
}
//Go allong another array to also give the class that creates the charts the data collected by the previous array.
for (let i = 0; i < 5; i++){
textArray.push('Question 1 Responses', 'Question 2 Responses', 'Question 3 Responses', 'Question 4 Responses', 'Question 5 Responses');
chartConfigArray.push(new ChartConfigClass(questionArray[i].questionData, textArray[i]));
}
// Create the charts
const ctx1 = document.getElementById('chart1').getContext('2d');
const myChart1 = new Chart(ctx1, chartConfigArray[0].chartConfig);
const ctx2 = document.getElementById('chart2').getContext('2d');
const myChart2 = new Chart(ctx2, chartConfigArray[1].chartConfig);
const ctx3 = document.getElementById('chart3').getContext('2d');
const myChart3 = new Chart(ctx3, chartConfigArray[2].chartConfig);
const ctx4 = document.getElementById('chart4').getContext('2d');
const myChart4 = new Chart(ctx4, chartConfigArray[3].chartConfig);
const ctx5 = document.getElementById('chart5').getContext('2d');
const myChart5 = new Chart(ctx5, chartConfigArray[4].chartConfig);

View File

@@ -22,6 +22,8 @@
<li class="nav-item">
<a href="settings.html" class="nav-link">Settings</a>
</li>
<li class="nav-item">
<a href="questions-dashboard.html" class="nav-link">Questions</a>
</ul>
</nav>

View File

@@ -42,21 +42,20 @@
} */
body {
padding-top: 5vw;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
margin-top: 8vh;
background-color: #f0f0f0;
flex-direction: column;
background-color: #afafaf;
align-items: center;
}
.gaugeGroup {
width: 98vw;
height: 20vh;
height: auto;
display: flex;
flex-direction: column; /* Keep as column */
justify-content: flex-start;
@@ -68,8 +67,8 @@ body {
clear: both;
margin-bottom: 10px;
position: relative;
float: top;
}
.groupTitle {
width: 100%;
text-align: center;
@@ -112,7 +111,9 @@ body {
height: 80%; /* Increase the height from 70% to 80% */
position: relative;
overflow: visible;
height: 5vh;
margin-bottom: 1vh;
}
.gaugeImage {
@@ -125,7 +126,6 @@ body {
left: 0;
z-index: 1; /* Make the image display below the needle */
bottom: 0;
margin-bottom: 10px;
}
.gaugeValue, .gaugeText {
@@ -215,4 +215,24 @@ body {
color: #fff;
text-decoration: none;
font-size: 18px;
}
.plotly-container {
width: 100%;
float: bottom;
padding: 1vw;
align-items: center;
justify-content: center;
display: flex;
}
.js-plotly-plot {
width: 90%;
height: 100%;
}
.disabled {
opacity: 0;
height: 0;
}

View File

@@ -1,168 +1,116 @@
* {
box-sizing: border-box;
font-family: "Roboto", sans-serif;
box-sizing: border-box;
font-family: "Roboto", sans-serif;
}
body {
padding-top: 5vw;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
flex-direction: column;
background-color: #afafaf;
}
.gaugeGroup {
width: 98vw;
height: 20vh;
display: flex;
flex-direction: column; /* Keep as column */
justify-content: flex-start;
background-color: #333;
color: #fff;
padding: 10px;
border-radius: 50px;
border: 2px solid #333;
clear: both;
margin-bottom: 10px;
position: relative;
float: top;
}
.groupTitle {
width: 100%;
text-align: center;
font-size: 24px;
}
.Node {
display: flex;
justify-content: space-around;
align-items: center;
width: 100%;
height: 100%;
}
.Sensorvalues {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
flex-wrap: wrap;
width: 15%;
height: 110%;
background-color: #ddd;
color: #333;
padding: 10px;
margin: 10px;
border-radius: 10px;
text-align: center;
position: relative;
padding-bottom: 6vh; /* Increase bottom padding */
}
.gaugeContainer {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 80%; /* Increase the height from 70% to 80% */
position: relative;
overflow: visible;
}
.gaugeImage {
width: 100%;
height: auto;
max-height: 200%;
object-fit: contain;
position: absolute; /* Make the image position absolute */
top: 0;
left: 0;
z-index: 1; /* Make the image display below the needle */
bottom: 0;
margin-bottom: 10px;
}
.gaugeValue, .gaugeText {
width: 100%;
text-align: center;
font-size: 24px;
z-index: 2;
}
.gaugeText {
width: 100%;
text-align: center;
font-size: 1.4vw;
z-index: 2;
position: absolute;
bottom: -3.2vw; /* Adjust this value to move the text further down */
}
.valueContainer {
display: flex;
justify-content: center;
margin-top: 10px;
}
#valueText {
font-size: 20px;
}
.needle {
position: absolute;
bottom: -40%; /* Lower the needle to the bottom */
left: 50%;
width: 2px;
height: 110%;
background-color: black;
transform-origin: bottom;
z-index: 3; /* Make the needle display above the image */
}
.contentContainer {
display: flex;
flex-direction: row; /* Layout children side by side */
width: 100%;
height: 100%;
padding-top: 5vw;
display: flex;
flex-direction: column;
background-color: #afafaf;
margin: 0;
}
.navbar {
background-color: #333;
height: 60px;
display: flex;
align-items: center;
padding: 0 20px;
position: fixed; /* Fix the navbar at the top of the page */
top: 0; /* Position it at the very top */
width: 100%; /* Make it span the full width of the page */
z-index: 1000; /* Make sure it's above all other elements */
background-color: #333;
height: 60px;
display: flex;
align-items: center;
padding: 0 20px;
position: fixed; /* Fix the navbar at the top of the page */
top: 0; /* Position it at the very top */
width: 100%; /* Make it span the full width of the page */
z-index: 1000; /* Make sure it's above all other elements */
}
.navbar-nav {
list-style: none;
display: flex;
align-items: center;
justify-content: center; /* Center the links horizontally */
height: 100%;
width: 100%; /* Make it span the full width of the navbar */
list-style: none;
display: flex;
align-items: center;
justify-content: center; /* Center the links horizontally */
height: 100%;
width: 100%; /* Make it span the full width of the navbar */
}
.nav-item {
margin-right: 20px;
margin-right: 20px;
}
.nav-link {
color: #fff;
text-decoration: none;
font-size: 18px;
}
color: #fff;
text-decoration: none;
font-size: 18px;
}
.container {
display: flex;
flex-direction: row;
align-items: center;
border: 2px solid #ccc;
border-radius: 10px;
margin: 20px;
padding: 20px;
width: 90;
box-sizing: border-box;
}
.data-types {
flex: 1;
display: flex;
flex-direction: column;
align-items: flex-start;
margin-right: 60px;
margin-bottom: 10px;
font-size: 0.8em;
padding: 8px;
border-radius: 5px;
background-color: #f0f0f0;
}
.filters {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin-bottom: 10px;
}
.date-filter {
flex: 1;
text-align: center;
margin-right: 60px;
font-size: 1.2em; /* Increase font size for a bigger appearance */
padding: 8px;
border-radius: 5px; /* Add border radius for a rounded look */
background-color: #f0f0f0; /* Light background color for contrast */
}
.node-filter {
flex: 1;
margin: auto;
text-align: center;
margin-right: 60px;
align-content: center;
font-size: 1.2em; /* Increase font size for a bigger appearance */
padding: 8px;
border-radius: 5px; /* Add border radius for a rounded look */
background-color: #f0f0f0; /* Light background color for contrast */
}
.filter-button {
width: 10%;
background-color: #007bff;
color: white;
padding: 10px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.js-plotly-plot {
align-self: center;
width: 95%;
height: 100%;
margin: 10px;
}
/* Additional styling as needed */

View File

@@ -0,0 +1,70 @@
* {
box-sizing: border-box;
font-family: "Roboto", sans-serif;
}
body {
flex-direction: row;
padding-top: 5vw;
display: flex;
background-color: #dbd7d7;
margin: 0;
}
.navbar {
background-color: #3d898c;
height: 60px;
display: flex;
align-items: center ;
padding: 0 20px;
position: fixed; /* Fix the navbar at the top of the page */
top: 0; /* Position it at the very top */
width: 100%; /* Make it span the full width of the page */
z-index: 1000; /* Make sure it's above all other elements */
}
.navbar-nav {
list-style: none;
display: flex;
align-items: center;
justify-content: center; /* Center the links horizontally */
height: 100%;
width: 100%; /* Make it span the full width of the navbar */
}
.nav-item {
margin-right: 20px;
}
.nav-link {
color: #fff;
text-decoration: none;
font-size: 18px;
}
#data-container {
padding: 20px;
background-color: #f5f5f5;
border: 1px solid #ccc;
}
.chart-container {
justify-content: center;
align-self: start;
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 100%;
}
.chart {
width: 30%;
margin: 20px;
padding: 20px;
background-color: #dbd7d7;
border: 3px solid #000;
border-radius: 30px;
}
canvas {
margin-bottom: 20px;
}

View File

@@ -0,0 +1,202 @@
* {
box-sizing: border-box;
font-family: "Roboto", sans-serif;
}
body {
display: flex;
justify-content: center;
margin: 0;
margin-top: 8vh;
background-color: #f0f0f0;
flex-direction: column;
background-color: #afafaf;
align-items: center;
}
.gaugeGroup {
width: 98vw;
height: auto;
display: flex;
flex-direction: column; /* Keep as column */
justify-content: flex-start;
background-color: #333;
color: #fff;
padding: 10px;
border-radius: 50px;
border: 2px solid #333;
clear: both;
margin-bottom: 10px;
position: relative;
}
.groupTitle {
width: 100%;
text-align: center;
font-size: 24px;
}
.Node {
display: flex;
justify-content: space-around;
align-items: center;
width: 100%;
height: 100%;
}
.Sensorvalues {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
flex-wrap: wrap;
width: 15%;
height: 110%;
background-color: #ddd;
color: #333;
padding: 10px;
margin: 10px;
border-radius: 10px;
text-align: center;
position: relative;
padding-top: 3vh; /* Increase bottom padding */
}
.gaugeContainer {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 80%; /* Increase the height from 70% to 80% */
position: relative;
overflow: visible;
height: 5vh;
margin-bottom: 1vh;
}
.gaugeImage {
width: 100%;
height: auto;
max-height: 120%;
object-fit: contain;
position: absolute; /* Make the image position absolute */
top: 0;
left: 0;
z-index: 1; /* Make the image display below the needle */
bottom: 0;
}
.gaugeValue, .gaugeText {
width: 100%;
text-align: center;
font-size: 24px;
z-index: 2;
}
.gaugeText {
width: 100%;
text-align: center;
font-size: 1.4vw;
z-index: 2;
position: absolute;
top: -1.4vw; /* Adjust this value to move the text further down */
}
.arrowimg {
width: 3vh;
height: auto;
max-height: 100%;
object-fit: contain;
position: absolute;
top: 0.5vw;
right: 1.2vw;
z-index: 2;
}
.valueContainer {
display: flex;
justify-content: center;
margin-top: 10px;
}
#valueText {
font-size: 20px;
}
.needle {
position: absolute;
bottom: -10%; /* Lower the needle to the bottom */
left: 50%;
width: 2px;
height: 100%;
background-color: black;
transform-origin: bottom;
z-index: 3; /* Make the needle display above the image */
transition: transform 0.1s ease-out;
}
.contentContainer {
display: flex;
flex-direction: row; /* Layout children side by side */
width: 100%;
height: 100%;
}
.navbar {
background-color: #333;
height: 60px;
display: flex;
align-items: center;
padding: 0 20px;
position: fixed; /* Fix the navbar at the top of the page */
top: 0; /* Position it at the very top */
width: 100%; /* Make it span the full width of the page */
z-index: 1000; /* Make sure it's above all other elements */
}
.navbar-nav {
list-style: none;
display: flex;
align-items: center;
justify-content: center; /* Center the links horizontally */
height: 100%;
width: 100%; /* Make it span the full width of the navbar */
}
.nav-item {
margin-right: 20px;
}
.nav-link {
color: #fff;
text-decoration: none;
font-size: 18px;
}
.plotly-container {
width: 100%;
float: bottom;
padding: 1vw;
align-items: center;
justify-content: center;
display: flex;
}
.js-plotly-plot {
width: 90%;
height: 100%;
}
.disabled {
opacity: 0;
height: 0;
}