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:
@@ -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
|
||||
|
157
web/newWebsite/graph-classes.js
Normal file
157
web/newWebsite/graph-classes.js
Normal 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();
|
||||
}
|
||||
}
|
145
web/newWebsite/graph-main.js
Normal file
145
web/newWebsite/graph-main.js
Normal 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);
|
||||
});
|
||||
}
|
@@ -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>
|
@@ -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>
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
27
web/newWebsite/questions-chart-class.js
Normal file
27
web/newWebsite/questions-chart-class.js
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
27
web/newWebsite/questions-creation-class.js
Normal file
27
web/newWebsite/questions-creation-class.js
Normal 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
|
||||
}]
|
||||
};
|
||||
}
|
||||
}
|
59
web/newWebsite/questions-dashboard.html
Normal file
59
web/newWebsite/questions-dashboard.html
Normal 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>
|
54
web/newWebsite/questions-main.js
Normal file
54
web/newWebsite/questions-main.js
Normal 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);
|
@@ -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>
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
}
|
@@ -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 */
|
||||
|
70
web/newWebsite/styles/questions-dashboard-styles.css
Normal file
70
web/newWebsite/styles/questions-dashboard-styles.css
Normal 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;
|
||||
}
|
@@ -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;
|
||||
|
||||
}
|
Reference in New Issue
Block a user