-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: RESTful endpoint for device module readings (#10)
- Loading branch information
Showing
15 changed files
with
401 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import pytest | ||
from rest_framework.test import APIClient | ||
|
||
|
||
@pytest.fixture | ||
def client(): | ||
return APIClient() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
from rest_framework import serializers | ||
|
||
from .models import DeviceModule, DeviceModuleReading | ||
|
||
|
||
class DeviceModuleSerializer(serializers.ModelSerializer): | ||
class Meta: | ||
model = DeviceModule | ||
fields = "__all__" | ||
|
||
|
||
class DeviceModuleReadingSerializer(serializers.ModelSerializer): | ||
class Meta: | ||
model = DeviceModuleReading | ||
fields = "__all__" | ||
# extra_kwargs = {"device_module": {"required": True}} |
10 changes: 0 additions & 10 deletions
10
shedpi_hub_dashboard/static/shedpi_hub_dashboard/dummy_data.json
This file was deleted.
Oops, something went wrong.
185 changes: 157 additions & 28 deletions
185
shedpi_hub_dashboard/static/shedpi_hub_dashboard/js/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,178 @@ | ||
const contents = document.getElementsByClassName("contents")[0]; | ||
let section = contents | ||
|
||
const contents = document.getElementsByClassName("contents"); | ||
let section = contents[0] | ||
let deviceModuleEndpoint = "" | ||
|
||
const url = section.getAttribute("data-json-feed") | ||
const myRequest = new Request(url); | ||
// Global store for the device modules, with schema | ||
let storeDeviceModules = [] | ||
let deviceModuleSchemaMap = {} | ||
|
||
/* Drop down selection */ | ||
// Create dropdown container | ||
const deviceModuleSelectorContainer = document.createElement("div"); | ||
section.append(deviceModuleSelectorContainer); | ||
|
||
const urlDeviceModule = "/api/v1/device-module/" | ||
let endpointDeviceModule = new Request(urlDeviceModule); | ||
response = fetch(endpointDeviceModule) | ||
.then((response) => { | ||
if (!response.ok) { | ||
throw new Error(`HTTP error! Status: ${response.status}`); | ||
} | ||
|
||
return response.json(); | ||
}) | ||
.then((response) => { | ||
storeDeviceModules = response | ||
drawDropdown() | ||
|
||
// Build schema map | ||
|
||
}); | ||
|
||
let drawDropdown = function () { | ||
let data = storeDeviceModules | ||
let dropdown = document.createElement("select"); | ||
|
||
// Table Header | ||
let emptySelector = document.createElement("option"); | ||
emptySelector.textContent = "Please Select" | ||
dropdown.append(emptySelector) | ||
|
||
dropdown.addEventListener('change', function (e) { | ||
optionId = this.selectedOptions[0].id | ||
|
||
if (optionId) { | ||
loadTableData(optionId) | ||
} | ||
}); | ||
|
||
for (let deviceModuleIndex in data) { | ||
const deviceModule = data[deviceModuleIndex] | ||
|
||
let optionElement = document.createElement("option"); | ||
optionElement.textContent = deviceModule.device + " - " + deviceModule.name | ||
optionElement.id = deviceModule.id | ||
|
||
// Build schema map | ||
deviceModuleSchemaMap[deviceModule.id] = deviceModule.schema | ||
|
||
dropdown.append(optionElement); | ||
} | ||
|
||
// Add the drpdown to the page | ||
deviceModuleSelectorContainer.append(dropdown); | ||
}; | ||
|
||
/* Table visual */ | ||
|
||
// Create table container | ||
const tableContainer = document.createElement("div"); | ||
section.append(tableContainer); | ||
|
||
let loadTableData = function (deviceModuleId) { | ||
|
||
// const url = section.getAttribute("data-json-feed") | ||
const url = "http://localhost:8000//api/v1/device-module-readings/" | ||
const endpoint = new URL(url); | ||
endpoint.searchParams.append("device_module", deviceModuleId); | ||
|
||
// FIXME: Need data output and need headings from Schema | ||
|
||
// const urlDeviceModuleReading = | ||
let endpointDeviceModuleReading = new Request(endpoint); | ||
|
||
response = fetch(endpointDeviceModuleReading) | ||
.then((response) => { | ||
if (!response.ok) { | ||
throw new Error(`HTTP error! Status: ${response.status}`); | ||
} | ||
|
||
return response.json(); | ||
}) | ||
.then((response) => { | ||
drawTable(response, deviceModuleId) | ||
}); | ||
} | ||
|
||
|
||
let drawTable = function (dataset, deviceModuleId) { | ||
// First empty the table container | ||
tableContainer.textContent = "" | ||
|
||
let drawTable = function (data) { | ||
let table = document.createElement("table"); | ||
|
||
// Table Header | ||
let headerRow = document.createElement("tr"); | ||
|
||
for(let heading in data.headings) { | ||
// TODO: Build the header rows from the schema, or build a full list in th | ||
// Could use the schema, what about historic data that may violate it, | ||
// Built as a ist because the pagination would hammer the device modiule | ||
const headingFields = dataset[0]; | ||
|
||
// TODO: Build the header rows from the schema, or build a full list in the backend and supply in the response | ||
// Could use the schema, what about historic data that may violate it, | ||
// Built as a ist because the pagination would hammer the device modiule | ||
|
||
schema = deviceModuleSchemaMap[deviceModuleId] | ||
|
||
let dataFields = [] | ||
if (schema) { | ||
extra_fields = Object.keys(schema.properties) | ||
dataFields = [...dataFields, ...extra_fields]; | ||
dataFields = [...new Set(dataFields)] | ||
} | ||
|
||
// FIXME: Need human readable headings, probably needs to come from the BE to be | ||
for (let heading in headingFields) { | ||
|
||
if (heading == "data") { | ||
|
||
let headerItem = document.createElement("th"); | ||
headerItem.textContent = data.headings[heading] | ||
headerRow.append(headerItem); | ||
for (let headingIndex in dataFields) { | ||
const heading = dataFields[headingIndex] | ||
let headerItem = document.createElement("th"); | ||
headerItem.textContent = heading | ||
headerRow.append(headerItem); | ||
} | ||
} else { | ||
let headerItem = document.createElement("th"); | ||
headerItem.textContent = heading | ||
headerRow.append(headerItem); | ||
} | ||
} | ||
|
||
table.append(headerRow); | ||
|
||
// Table Contents | ||
for(let row in data.readings) { | ||
for (let rowIndex in dataset) { | ||
const row = dataset[rowIndex] | ||
let contentRow = document.createElement("tr"); | ||
for(let reading in data.readings[row]) { | ||
let contentItem = document.createElement("td"); | ||
contentItem.textContent = data.readings[row][reading] | ||
contentRow.append(contentItem); | ||
for (let reading in row) { | ||
const fieldValue = row[reading] | ||
if (typeof fieldValue == "object") { | ||
for (let dataFieldIndex in dataFields) { | ||
let contentItem = document.createElement("td"); | ||
const dataField = dataFields[dataFieldIndex] | ||
|
||
// FIXME: Need to change the null value in the project to be an empty object | ||
let mydict = {} | ||
if (fieldValue != null) { | ||
if (fieldValue.hasOwnProperty(dataField)) { | ||
contentItem.textContent = fieldValue[dataField] | ||
} | ||
} | ||
|
||
contentRow.append(contentItem); | ||
} | ||
} else { | ||
let contentItem = document.createElement("td"); | ||
contentItem.textContent = row[reading] | ||
contentRow.append(contentItem); | ||
} | ||
} | ||
table.append(contentRow); | ||
} | ||
|
||
// Add the table to the page | ||
section.append(table); | ||
tableContainer.append(table); | ||
} | ||
|
||
|
||
response = fetch(myRequest) | ||
.then((response) => { | ||
if (!response.ok) { | ||
throw new Error(`HTTP error! Status: ${response.status}`); | ||
} | ||
|
||
return response.json(); | ||
}) | ||
.then((response) => { | ||
drawTable(response) | ||
}); |
36 changes: 18 additions & 18 deletions
36
shedpi_hub_dashboard/templates/shedpi_hub_dashboard/index.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,23 @@ | ||
|
||
{% load static %} | ||
|
||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<meta http-equiv="X-UA-Compatible" content="ie=edge"> | ||
<title>ShedPi</title> | ||
<link rel="stylesheet" href="{% static 'shedpi_hub_dashboard/css/landing.css' %}"> | ||
</head> | ||
<body> | ||
<header> | ||
<h1>Shed Pi data</h1> | ||
</header> | ||
<div class="contents" data-json-feed="{% static 'shedpi_hub_dashboard/dummy_data.json' %}"> | ||
</div> | ||
<footer> | ||
</footer> | ||
<script src="{% static 'shedpi_hub_dashboard/js/index.js' %}"></script> | ||
</body> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<meta http-equiv="X-UA-Compatible" content="ie=edge"> | ||
<title>ShedPi</title> | ||
<link rel="stylesheet" href="{% static 'shedpi_hub_dashboard/css/landing.css' %}"> | ||
</head> | ||
<body> | ||
<header> | ||
<h1>Shed Pi data</h1> | ||
</header> | ||
<div class="contents" data-endpoint-url=""> | ||
|
||
</div> | ||
<footer> | ||
</footer> | ||
<script src="{% static 'shedpi_hub_dashboard/js/index.js' %}"></script> | ||
</body> | ||
</html> |
Oops, something went wrong.