diff --git a/server/Flask/main.py b/server/Flask/main.py index 349cf99..9fb35a1 100644 --- a/server/Flask/main.py +++ b/server/Flask/main.py @@ -49,9 +49,9 @@ def loginDB(): ) return mydb -def getData(node, dataType, MAC, dateStart, dateEnd): +def getData(node, dataTypes, MAC, dateStart, dateEnd): mydb = loginDB() - query = get_query(node, dataType, MAC, False, False, dateStart, dateEnd) + query = get_query(node, dataTypes, MAC, False, False, dateStart, dateEnd) cursor = mydb.cursor(dictionary=True) # Enable dictionary output cursor.execute(query) result = cursor.fetchall() # Fetch the results @@ -62,7 +62,7 @@ def getData(node, dataType, MAC, dateStart, dateEnd): def getNodeInfo(macAdress): mydb = loginDB() - query = get_query(False, False, macAdress, False, False) + query = get_query(False, False, macAdress, False, False, False, False) cursor = mydb.cursor(dictionary=True) # Enable dictionary output cursor.execute(query) result = cursor.fetchall() # Fetch the results diff --git a/server/Flask/queries.py b/server/Flask/queries.py index 2257b79..0211c8d 100644 --- a/server/Flask/queries.py +++ b/server/Flask/queries.py @@ -1,5 +1,9 @@ def get_query(node, dataType, MAC, questionID, replies, dateStart, dateEnd): - if dateStart and dateEnd and node: + if dateStart and dateEnd and node and dataType: + query = f'''SELECT * + FROM Measurement + WHERE TimeStamp BETWEEN '{dateStart}' AND '{dateEnd}' AND NodeID = {node} AND Type IN ('{dataType}');''' + elif dateStart and dateEnd and node: query = f'''SELECT * FROM Measurement WHERE TimeStamp BETWEEN '{dateStart}' AND '{dateEnd}' AND NodeID = {node};''' @@ -21,10 +25,7 @@ def get_query(node, dataType, MAC, questionID, replies, dateStart, dateEnd): query = f"SELECT * FROM Question" elif replies: query = f"SELECT * FROM Reply" - elif dateStart and dateEnd and node: - query = f'''SELECT * - FROM Measurement - WHERE TimeStamp BETWEEN '{dateStart}' AND '{dateEnd}';''' + else: query = "SELECT * FROM `Measurement`" return query diff --git a/web/newWebsite/graph-classes.js b/web/newWebsite/graph-classes.js index 3e6e359..9700ab0 100644 --- a/web/newWebsite/graph-classes.js +++ b/web/newWebsite/graph-classes.js @@ -42,8 +42,7 @@ class Graph { } updateData(type, value, timestamp) { - this.timeArray.push(timestamp); - + // this.timeArray.push(timestamp); switch (type) { case "Temp": this.tempArray.push(value); @@ -67,7 +66,7 @@ class Graph { x: [this.timeArray], y: [this.tempArray, this.humiArray, this.eco2Array, this.tvocArray], }; - + console.log(update); Plotly.update(this.id, update); } } @@ -140,10 +139,19 @@ class DataProcessor { } 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(); } - } + this.graph.updateGraph(); + } } diff --git a/web/newWebsite/graph-main.js b/web/newWebsite/graph-main.js index e07f628..cd9760a 100644 --- a/web/newWebsite/graph-main.js +++ b/web/newWebsite/graph-main.js @@ -24,10 +24,10 @@ container.setAttribute("class", "container"); const dataTypesContainer = document.createElement("div"); dataTypesContainer.setAttribute("class", "data-types"); -const temperatureCheckbox = createCheckBox("temperature", "Temperature"); -const humidityCheckbox = createCheckBox("humidity", "Humidity"); -const eco2Checkbox = createCheckBox("eco2", "eCO2"); -const tvocCheckbox = createCheckBox("tvoc", "TVOC"); +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); @@ -55,24 +55,30 @@ filterButton.addEventListener("click", () => { temperatureCheckbox, humidityCheckbox, eco2Checkbox, - tvocCheckbox, + tvocCheckbox ]; + checkboxes.forEach((checkbox) => { if (checkbox.checkbox.checked) { - selectedFields.push(checkbox.checkbox.id); + selectedFields.push(String(checkbox.checkbox.id)); } }); + let selectedFieldsString = selectedFields.map(String); + + let formattedString = '(' + selectedFieldsString.map(item => `'${item}'`).join(', ') + ')'; + const filteredData = [ startDate, endDate, selectedNodes, - selectedFields + formattedString ]; + console.log(filteredData); console.log(startDate, endDate, selectedNodes); - generateLink(startDate, endDate, selectedNodes); + generateLink(startDate, endDate, selectedNodes, formattedString); fetchData(); }); @@ -98,7 +104,7 @@ nodeFilter.setAttribute("class", "node-filter"); const nodeInput = document.createElement("input"); nodeInput.setAttribute("type", "text"); -nodeInput.setAttribute("placeholder", "Enter node (A, B, etc.)"); +nodeInput.setAttribute("placeholder", "Enter Node Name (* for all)"); nodeInput.setAttribute("id", "node-input"); nodeInput.setAttribute("class", "input-field"); @@ -110,12 +116,12 @@ container.appendChild(filterButton); document.body.appendChild(container); // Function to get the link for the get request -function generateLink(dateStart, dateEnd, node) { +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}`; + link = `${baseUrl}?dateStart=${formattedDateStart}&dateEnd=${formattedDateEnd}&node=${node}&dataType=${dataTypes}`; console.log(link); } diff --git a/web/newWebsite/questions-chart-class.js b/web/newWebsite/questions-chart-class.js new file mode 100644 index 0000000..42467d9 --- /dev/null +++ b/web/newWebsite/questions-chart-class.js @@ -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 + } + } + } + } +} \ No newline at end of file diff --git a/web/newWebsite/questions-main-class.js b/web/newWebsite/questions-creation-class.js similarity index 100% rename from web/newWebsite/questions-main-class.js rename to web/newWebsite/questions-creation-class.js diff --git a/web/newWebsite/questions-dashboard.html b/web/newWebsite/questions-dashboard.html index 46dad55..5ce5f66 100644 --- a/web/newWebsite/questions-dashboard.html +++ b/web/newWebsite/questions-dashboard.html @@ -30,24 +30,30 @@
+

Question 1: How clean are the toilets?

- +
+

Question 2: How clean is the study area?

- +
+

Question 3: What do you think of the temperature in the study area?

- +
+

Question 4: How crowded would you say the study area is?

- +
+

Question 5: Is there enough help available on the 5th floor?

- +
- + + \ No newline at end of file diff --git a/web/newWebsite/questions-main.js b/web/newWebsite/questions-main.js index 8bdaafc..06bf47e 100644 --- a/web/newWebsite/questions-main.js +++ b/web/newWebsite/questions-main.js @@ -1,3 +1,4 @@ +//For now create dummy data to show on the website. let dummydata1 = [40, 30, 20]; let questionOptionsDummy1 = ['disgusting','clean', 'fine']; @@ -13,119 +14,41 @@ let questionOptionsDummy4 = ['really crowded','not at all', 'its fine', ]; let dummydata5 = [30, 20, 20]; let questionOptionsDummy5 = ['no','yes', 'decently']; -const question1Data = new QuestionCreationClass(dummydata1,questionOptionsDummy1) -const question2Data = new QuestionCreationClass(dummydata2,questionOptionsDummy2) -const question3Data = new QuestionCreationClass(dummydata3, questionOptionsDummy3); -const question4Data = new QuestionCreationClass(dummydata4, questionOptionsDummy4); -const question5Data = new QuestionCreationClass(dummydata5, questionOptionsDummy5); +//make arrays to store data. +let chartConfigArray = []; +let textArray = []; -const chartConfig1 = { - type: 'pie', - data: question1Data.questionData, - options: { - responsive: true, - legend: { - position: 'top', - }, - title: { - display: true, - text: 'Question 1 Responses' - }, - animation: { - animateScale: true, - animateRotate: true - } - } -}; +let questionArray = []; +let questionOptionsDummy = []; +let dummydata = []; -const chartConfig2 = { - type: 'pie', - data: question2Data.questionData, - options: { - responsive: true, - legend: { - position: 'top', - }, - title: { - display: true, - text: 'Question 2 Responses' - }, - animation: { - animateScale: true, - animateRotate: true - } - } -}; +//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); -const chartConfig3 = { - type: 'pie', - data: question3Data.questionData, - options: { - responsive: true, - legend: { - position: 'top', - }, - title: { - display: true, - text: 'Question 3 Responses' - }, - animation: { - animateScale: true, - animateRotate: true - } - } -}; + questionArray.push(new QuestionCreationClass(dummydata[i], questionOptionsDummy[i])); +} -const chartConfig4 = { - type: 'pie', - data: question4Data.questionData, - options: { - responsive: true, - legend: { - position: 'top', - }, - title: { - display: true, - text: 'Question 4 Responses' - }, - animation: { - animateScale: true, - animateRotate: true - } - } -}; +//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'); -const chartConfig5 = { - type: 'pie', - data: question5Data.questionData, - options: { - responsive: true, - legend: { - position: 'top', - }, - title: { - display: true, - text: 'Question 5 Responses' - }, - animation: { - animateScale: true, - animateRotate: true - } - } -}; + chartConfigArray.push(new ChartConfigClass(questionArray[i].questionData, textArray[i])); +} // Create the charts const ctx1 = document.getElementById('chart1').getContext('2d'); -const myChart1 = new Chart(ctx1, chartConfig1); +const myChart1 = new Chart(ctx1, chartConfigArray[0].chartConfig); const ctx2 = document.getElementById('chart2').getContext('2d'); -const myChart2 = new Chart(ctx2, chartConfig2); +const myChart2 = new Chart(ctx2, chartConfigArray[1].chartConfig); const ctx3 = document.getElementById('chart3').getContext('2d'); -const myChart3 = new Chart(ctx3, chartConfig3); +const myChart3 = new Chart(ctx3, chartConfigArray[2].chartConfig); const ctx4 = document.getElementById('chart4').getContext('2d'); -const myChart4 = new Chart(ctx4, chartConfig4); +const myChart4 = new Chart(ctx4, chartConfigArray[3].chartConfig); const ctx5 = document.getElementById('chart5').getContext('2d'); -const myChart5 = new Chart(ctx5, chartConfig5); +const myChart5 = new Chart(ctx5, chartConfigArray[4].chartConfig); diff --git a/web/newWebsite/styles/graph-styles.css b/web/newWebsite/styles/graph-styles.css index 70e4a11..370617f 100644 --- a/web/newWebsite/styles/graph-styles.css +++ b/web/newWebsite/styles/graph-styles.css @@ -50,7 +50,7 @@ body { border-radius: 10px; margin: 20px; padding: 20px; - width: 100%; + width: 90; box-sizing: border-box; } @@ -98,8 +98,7 @@ body { } .filter-button { - flex: 1; - width: 20%; + width: 10%; background-color: #007bff; color: white; padding: 10px; @@ -108,4 +107,10 @@ body { cursor: pointer; } +.js-plotly-plot { + align-self: center; + width: 95%; + height: 100%; + margin: 10px; +} /* Additional styling as needed */ diff --git a/web/newWebsite/styles/questions-dashboard-styles.css b/web/newWebsite/styles/questions-dashboard-styles.css index eba538a..b336bc0 100644 --- a/web/newWebsite/styles/questions-dashboard-styles.css +++ b/web/newWebsite/styles/questions-dashboard-styles.css @@ -4,6 +4,7 @@ } body { + flex-direction: row; padding-top: 5vw; display: flex; background-color: #dbd7d7; @@ -42,16 +43,27 @@ } #data-container { - width: 80%; - margin: 0 auto; padding: 20px; background-color: #f5f5f5; border: 1px solid #ccc; } .chart-container { - width: 80%; - margin: 20px auto; + 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; diff --git a/web/newWebsite/styles/settings-styles.css b/web/newWebsite/styles/settings-styles.css index e69de29..f00eca5 100644 --- a/web/newWebsite/styles/settings-styles.css +++ b/web/newWebsite/styles/settings-styles.css @@ -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; + +} \ No newline at end of file