From 364bc7cd6f52ccd2b0a5eab9e75df385d10eea73 Mon Sep 17 00:00:00 2001 From: ray310 <60367095+Ray310@users.noreply.github.com> Date: Wed, 18 Mar 2020 19:52:35 -0400 Subject: [PATCH 01/21] 1) Updated views/sensor.py to refelct new database schema 2) Modified appearance and functioning of sensor.html page and associated javascript (sensor.js) 2a) Included deleted row from add sensor view --- mercury/static/mercury/js/sensor.js | 73 +++++--------- mercury/static/mercury/style.css | 38 ++++++- mercury/templates/sensor.html | 147 ++++++++++++---------------- mercury/views/sensor.py | 62 ++++-------- 4 files changed, 138 insertions(+), 182 deletions(-) diff --git a/mercury/static/mercury/js/sensor.js b/mercury/static/mercury/js/sensor.js index b19b8260..a99d50f3 100644 --- a/mercury/static/mercury/js/sensor.js +++ b/mercury/static/mercury/js/sensor.js @@ -1,51 +1,22 @@ function addRow(){ - var sensorList, field_name_li, field_type_li, field_name_input, field_type_select, - float_option, string_option, bool_option; - - fields = document.getElementById("field-list"); - // Make field name input - field_name_input = document.createElement("input"); - field_name_input.setAttribute("type","text"); - field_name_input.setAttribute("name","field-name"); - field_name_input.setAttribute("class","inline-block-child"); - fields.appendChild(field_name_input); - - //Make field type - field_type_select = document.createElement("select"); - field_type_select.setAttribute("name", "field-type"); - field_type_select.setAttribute("class", "inline-block-child"); - - float_option = document.createElement("option"); - float_option.setAttribute("value", "float"); - float_option.appendChild(document.createTextNode("Float")); - field_type_select.appendChild(float_option); - - string_option = document.createElement("option"); - string_option.setAttribute("value", "string"); - string_option.appendChild(document.createTextNode("String")); - field_type_select.appendChild(string_option); - - bool_option = document.createElement("option"); - bool_option.setAttribute("value", "bool"); - bool_option.appendChild(document.createTextNode("Boolean")); - field_type_select.appendChild(bool_option); - - fields.appendChild(field_type_select); - - // Make unit input - unit_input = document.createElement("input"); - unit_input.setAttribute("type","text"); - unit_input.setAttribute("name","field-unit") - unit_input.setAttribute("class", "inline-block-child"); - fields.appendChild(unit_input); - - var hr = document.createElement('hr'); - fields.appendChild(hr); + var table = document.getElementById("new-sensor-table"); + var rowCount = table.rows.length; + var colCount = table.rows[0].cells.length; + var newRow = table.insertRow(rowCount); + for(var i=0; i 2){ + table.deleteRow(rowCount-1) + } } /* @@ -54,10 +25,10 @@ selectView displays the correct view of the "Add or Modify Sensors" page -if a user submits a new sensor which posts and reloads page, then the add new sensor view should remain */ function selectView() { - var newSensorDiv = document.getElementById("add-new-sensor"); - var existingSensorDiv = document.getElementById("existing-sensors"); - var modifyButton = document.getElementById("current-sensor-btn"); - var newButton = document.getElementById("add-sensor-btn"); + var newSensorDiv = document.getElementById("add-new-sensor"); + var existingSensorDiv = document.getElementById("existing-sensors"); + var modifyButton = document.getElementById("current-sensor-btn"); + var newButton = document.getElementById("add-sensor-btn"); if (sessionStorage.getItem('viewing') == 'addingNew'){ newSensorDiv.style.display = "block"; existingSensorDiv.style.display = 'none'; @@ -75,8 +46,8 @@ function selectView() { } function displayCurrentSensors() { - sessionStorage.setItem('viewing', 'existing'); - selectView() + sessionStorage.setItem('viewing', 'existing'); + selectView() } function displayAddNewSensor() { diff --git a/mercury/static/mercury/style.css b/mercury/static/mercury/style.css index 5eb3fb41..d8dcfa2b 100644 --- a/mercury/static/mercury/style.css +++ b/mercury/static/mercury/style.css @@ -11,10 +11,41 @@ body { tr:nth-child(even) {background-color: #f2f2f2;} -li{ +nav ul{ + display:flex; + justify-content: space-around; +} + +nav li{ + display: inline-block; list-style-type: none; /* removes bulleting */ +} + +#sensor-container{ + background-color:lightgray; +} + +.inline-box{ display: inline-block; - margin: 0% 5%; +} + +.inline-box label{ + text-align:right; + width: auto; + min-width:150px; +} + +.sensor-field-row{ + display: inline-block; + vertical-align: middle; + border: 1px solid black; +} + +.sensor-field-row-item{ + display: inline-block; + vertical-align: middle; + margin: 5px; + min-height: 30px; } .topbar-container { @@ -407,7 +438,7 @@ input#id_can_msg{ -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } - article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { + article, aside, figcaption, figure, footer, header, hgroup, main, section { display: block; } @@ -424,6 +455,7 @@ input#id_can_msg{ h1, h2, h3, h4, h5, h6 { margin-top: 0; margin-bottom: 0.5rem; + text-align: center; } p { diff --git a/mercury/templates/sensor.html b/mercury/templates/sensor.html index d1b9f291..1c581e5c 100644 --- a/mercury/templates/sensor.html +++ b/mercury/templates/sensor.html @@ -1,3 +1,5 @@ + + {% load static %} @@ -13,23 +15,17 @@ {% include 'sidebar.html' %}
-
-

Add or Modify Sensors

-

- This page is used to add new sensors to the database as well as edit currently existing sensors within the database. -

-
+

Add or Modify Sensors

-
- -
+ -
+

Existing sensors

{% if sensors %} @@ -78,83 +74,66 @@

Field Unit

{% endif%}
-
-

Add a New Sensor

-
- -
- {% csrf_token %} -
- - -
- -

Field Name

-

Field Type

-

Field Unit

- -
- - {% if sensor_format %} - - {% for key, value in sensor_format.items %} - - - - -
- - {% endfor %} - - {% endif %} - - - - +
+

Configure a New Sensor

+
+ + {% csrf_token %} +
+
+ + + + + +

+ + + + + + + + + + + + + + + + + + + + + + +
Field Number Field Name Field Data Type Unit (optional)
1 + +

+ +
+ +

+
-
+

-
-
- -

-
- -
-

+ +
+
{% for message in messages %}

{{ message }}

{% endfor %} +
diff --git a/mercury/views/sensor.py b/mercury/views/sensor.py index 72be4ad1..fe49a065 100644 --- a/mercury/views/sensor.py +++ b/mercury/views/sensor.py @@ -3,6 +3,7 @@ from django.views.generic import TemplateView from ..event_check import require_event_code from mercury.models import AGSensor +from mercury.models import FuelLevelSensor from django.contrib import messages log = logging.getLogger(__name__) @@ -30,61 +31,34 @@ def get(self, request, *args, **kwargs): @require_event_code def post(self, request, *args, **kwargs): - post_sensor_name = request.POST.get("sensor-name") - post_field_names = request.POST.getlist("field-name") - post_field_types = request.POST.getlist("field-type") - post_field_units = request.POST.getlist("field-unit") - - field_names = list() - field_types = list() - field_units = list() - for i in range(len(post_field_names)): - if post_field_names[i]: - field_names.append(post_field_names[i]) - field_types.append(post_field_types[i]) - field_units.append(post_field_units[i]) + id_num = request.POST.get("sensor-id-num") + sensor_name = request.POST.get("sensor-name") + field_names = request.POST.getlist("field-names") + field_types = request.POST.getlist("data-types") + field_units = request.POST.getlist("units") + # error checking. Note that sensor name, field name and id number are required by the HTML form. See sensor.HTML form_valid = True - - if not post_sensor_name: - messages.error( - request, ("Sensor name is missing."), - ) - form_valid = False - - sensor = AGSensor.objects.filter(sensor_name=post_sensor_name) - if sensor.count() > 0: - messages.error( - request, ("Sensor name already taken."), - ) + if len(AGSensor.objects.filter(sensor_name=sensor_name)) > 0: + messages.error(request, "Sensor name is already taken.") form_valid = False - - if len(field_names) == 0: - messages.error( - request, ("Sensor must have at least 1 field."), - ) - form_valid = False - if check_if_duplicates(field_names): - messages.error( - request, ("Field names must be unique."), - ) + messages.error(request, "Field names must be unique.") form_valid = False + # create sensor format which is dictionary of dictionaries sensor_format = {} - for i in range(len(field_names)): - if post_field_names[i]: - sensor_format[field_names[i]] = { - "unit": field_units[i], - "format": field_types[i], - } + fields = zip(field_names, field_types, field_units) + for field in fields: + sensor_format[field[0]] = {"data_type": field[1], "unit": field[2]} if form_valid: sensor = AGSensor.objects.create( - sensor_name=post_sensor_name, + sensor_id=id_num, + sensor_name=sensor_name, sensor_processing_formula=0, sensor_format=sensor_format, - ) + ) # processing formula needs to be adapted sensor.save() sensors = AGSensor.objects.all() context = {"sensors": sensors} @@ -92,7 +66,7 @@ def post(self, request, *args, **kwargs): sensors = AGSensor.objects.all() context = { "sensors": sensors, - "sensor_name": post_sensor_name, + "sensor_name": sensor_name, "sensor_format": sensor_format, } From ca69ea83f62465b57b7b8728da6ee29511b44310 Mon Sep 17 00:00:00 2001 From: ray310 <60367095+Ray310@users.noreply.github.com> Date: Wed, 18 Mar 2020 20:10:42 -0400 Subject: [PATCH 02/21] Updated formatting --- mercury/views/sensor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mercury/views/sensor.py b/mercury/views/sensor.py index fe49a065..3d1e9be0 100644 --- a/mercury/views/sensor.py +++ b/mercury/views/sensor.py @@ -3,7 +3,6 @@ from django.views.generic import TemplateView from ..event_check import require_event_code from mercury.models import AGSensor -from mercury.models import FuelLevelSensor from django.contrib import messages log = logging.getLogger(__name__) @@ -37,7 +36,8 @@ def post(self, request, *args, **kwargs): field_types = request.POST.getlist("data-types") field_units = request.POST.getlist("units") - # error checking. Note that sensor name, field name and id number are required by the HTML form. See sensor.HTML + # error checking. Note that sensor name, field name and id number + # are required by the HTML form. See sensor.HTMLgit form_valid = True if len(AGSensor.objects.filter(sensor_name=sensor_name)) > 0: messages.error(request, "Sensor name is already taken.") From 55b893b389bc46d654bab5576046e0df6287a72b Mon Sep 17 00:00:00 2001 From: ray310 <60367095+Ray310@users.noreply.github.com> Date: Thu, 19 Mar 2020 15:26:28 -0400 Subject: [PATCH 03/21] Fixed input validation for "Add Sensor" --- mercury/views/sensor.py | 46 +++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/mercury/views/sensor.py b/mercury/views/sensor.py index 3d1e9be0..002d2519 100644 --- a/mercury/views/sensor.py +++ b/mercury/views/sensor.py @@ -9,12 +9,31 @@ log.setLevel(logging.ERROR) -def check_if_duplicates(elements): - """Check if given list contains any duplicates""" - if len(elements) == len(set(elements)): - return False - else: - return True +def validate_add_sensor_inputs(sensor_name, field_name_list, request): + form_valid = True + + # no sensor name + if not sensor_name: + messages.error(request, "Sensor name is missing or invalid.") + form_valid = False + + # missing field names + for name in field_name_list: + if not name: + messages.error(request, "Sensor has missing field name(s).") + form_valid = False + + # duplicated sensor name + if AGSensor.objects.filter(sensor_name=sensor_name).count() > 0: + messages.error(request, "Sensor name is already taken.") + form_valid = False + + # duplicated field names + if len(field_name_list) > len(set(field_name_list)): + messages.error(request, "Field names must be unique.") + form_valid = False + + return form_valid, request class CreateSensorView(TemplateView): @@ -36,15 +55,10 @@ def post(self, request, *args, **kwargs): field_types = request.POST.getlist("data-types") field_units = request.POST.getlist("units") - # error checking. Note that sensor name, field name and id number - # are required by the HTML form. See sensor.HTMLgit - form_valid = True - if len(AGSensor.objects.filter(sensor_name=sensor_name)) > 0: - messages.error(request, "Sensor name is already taken.") - form_valid = False - if check_if_duplicates(field_names): - messages.error(request, "Field names must be unique.") - form_valid = False + # reformat then validate inputs to avoid duplicated names or bad inputs like " " + sensor_name = sensor_name.strip().lower() # remove excess whitespace and CAPS + field_names = [string.strip().lower() for string in field_names] + valid, request = validate_add_sensor_inputs(sensor_name, field_names, request) # create sensor format which is dictionary of dictionaries sensor_format = {} @@ -52,7 +66,7 @@ def post(self, request, *args, **kwargs): for field in fields: sensor_format[field[0]] = {"data_type": field[1], "unit": field[2]} - if form_valid: + if valid: sensor = AGSensor.objects.create( sensor_id=id_num, sensor_name=sensor_name, From a04f25377f14a20067bddb18b4dd14a88e9c74dc Mon Sep 17 00:00:00 2001 From: ray310 <60367095+Ray310@users.noreply.github.com> Date: Thu, 19 Mar 2020 17:00:37 -0400 Subject: [PATCH 04/21] Updated sensor models in mercury/models.py --- mercury/models.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/mercury/models.py b/mercury/models.py index ce62e0aa..61fc1fc7 100644 --- a/mercury/models.py +++ b/mercury/models.py @@ -16,11 +16,24 @@ class AGEvent(models.Model): event_location = models.CharField(max_length=100, null=False, blank=True) +class AGSensorType(models.Model): + """Stores the information about sensor types which is used to provide a sensor template + and related formula for different types of sensors. + """ + + id = models.AutoField(primary_key=True) + name = models.CharField(max_length=1024, blank=True) + processing_formula = models.IntegerField(default=0, null=False) + format = JSONField() + + class AGSensor(models.Model): - sensor_id = models.AutoField(primary_key=True) - sensor_name = models.CharField(max_length=1024, blank=True) - sensor_processing_formula = models.IntegerField(default=0, null=False) - sensor_format = JSONField() + """Stores the information about sensors including name and type id. + """ + + id = models.AutoField(primary_key=True) + name = models.CharField(max_length=1024, blank=True) + type_id = models.ForeignKey(AGSensorType, null=False, on_delete=models.PROTECT) class AGMeasurement(models.Model): From 299c66867489430e1b749167b7c381a2f3de6210 Mon Sep 17 00:00:00 2001 From: ray310 <60367095+Ray310@users.noreply.github.com> Date: Thu, 19 Mar 2020 17:40:05 -0400 Subject: [PATCH 05/21] Modified how sensor is being created. Code needs to be tested. --- mercury/views/sensor.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/mercury/views/sensor.py b/mercury/views/sensor.py index 002d2519..5cb6071b 100644 --- a/mercury/views/sensor.py +++ b/mercury/views/sensor.py @@ -3,6 +3,7 @@ from django.views.generic import TemplateView from ..event_check import require_event_code from mercury.models import AGSensor +from mercury.models import AGSensorType from django.contrib import messages log = logging.getLogger(__name__) @@ -24,7 +25,7 @@ def validate_add_sensor_inputs(sensor_name, field_name_list, request): form_valid = False # duplicated sensor name - if AGSensor.objects.filter(sensor_name=sensor_name).count() > 0: + if AGSensor.objects.filter(name=sensor_name).count() > 0: messages.error(request, "Sensor name is already taken.") form_valid = False @@ -66,13 +67,11 @@ def post(self, request, *args, **kwargs): for field in fields: sensor_format[field[0]] = {"data_type": field[1], "unit": field[2]} + sensor_type = AGSensorType(name='Homer_Simpson', processing_formula=0, format=sensor_format) + sensor_type.save() + if valid: - sensor = AGSensor.objects.create( - sensor_id=id_num, - sensor_name=sensor_name, - sensor_processing_formula=0, - sensor_format=sensor_format, - ) # processing formula needs to be adapted + sensor = AGSensor.objects.create(name=sensor_name, type_id=sensor_type) sensor.save() sensors = AGSensor.objects.all() context = {"sensors": sensors} From b8875edcf942d388bf045358a8d5bf9337a10a21 Mon Sep 17 00:00:00 2001 From: dandipietrantonio Date: Fri, 20 Mar 2020 17:40:46 -0400 Subject: [PATCH 06/21] Changed all imports for AG models from mercury/models.py to ag_data.models.py --- mercury/forms.py | 2 +- mercury/models.py | 47 ------------------------- mercury/tests/test_configure_sensors.py | 3 +- mercury/tests/test_event.py | 3 +- mercury/views/dashboard.py | 3 +- mercury/views/event.py | 2 +- mercury/views/events.py | 2 +- mercury/views/sensor.py | 16 ++++----- mercury/views/simulator.py | 3 +- 9 files changed, 16 insertions(+), 65 deletions(-) diff --git a/mercury/forms.py b/mercury/forms.py index 71282aad..3855e1d4 100644 --- a/mercury/forms.py +++ b/mercury/forms.py @@ -1,8 +1,8 @@ """This module defines the ModelForms (or Forms) that are used by the rendering engine to accept input for various features of the site""" from django import forms +from ag_data.models import AGEvent from mercury.models import ( - AGEvent, TemperatureSensor, AccelerationSensor, WheelSpeedSensor, diff --git a/mercury/models.py b/mercury/models.py index 61fc1fc7..9e63fea6 100644 --- a/mercury/models.py +++ b/mercury/models.py @@ -3,53 +3,6 @@ import uuid from django.utils import timezone - -class AGEvent(models.Model): - """This model stores the information about events. When a new event is created, - a UUID4-typed event_uuid will be assigned to this event and also store the current - date for this event. """ - - event_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) - event_name = models.CharField(max_length=40, blank=True) - event_date = models.DateTimeField(default=timezone.now) - event_description = models.CharField(max_length=100, null=False, blank=True) - event_location = models.CharField(max_length=100, null=False, blank=True) - - -class AGSensorType(models.Model): - """Stores the information about sensor types which is used to provide a sensor template - and related formula for different types of sensors. - """ - - id = models.AutoField(primary_key=True) - name = models.CharField(max_length=1024, blank=True) - processing_formula = models.IntegerField(default=0, null=False) - format = JSONField() - - -class AGSensor(models.Model): - """Stores the information about sensors including name and type id. - """ - - id = models.AutoField(primary_key=True) - name = models.CharField(max_length=1024, blank=True) - type_id = models.ForeignKey(AGSensorType, null=False, on_delete=models.PROTECT) - - -class AGMeasurement(models.Model): - measurement_uuid = models.UUIDField( - primary_key=True, default=uuid.uuid4, editable=False - ) - measurement_timestamp = models.DateTimeField(default=timezone.now, blank=False) - measurement_event = models.ForeignKey( - AGEvent, on_delete=models.CASCADE, blank=False, null=False - ) - measurement_sensor = models.ForeignKey( - AGSensor, on_delete=models.CASCADE, blank=False, null=False - ) - measurement_value = JSONField() - - class TemperatureSensor(models.Model): """This model represents the Temperature sensor that we expect to be potentially available in the future in the NYU Motorsports diff --git a/mercury/tests/test_configure_sensors.py b/mercury/tests/test_configure_sensors.py index b04167ff..cc02faeb 100644 --- a/mercury/tests/test_configure_sensors.py +++ b/mercury/tests/test_configure_sensors.py @@ -1,6 +1,7 @@ from django.test import TestCase from django.urls import reverse -from mercury.models import EventCodeAccess, AGSensor +from mercury.models import EventCodeAccess +from ag_data.models import AGSensor class TestConfigureSensorView(TestCase): diff --git a/mercury/tests/test_event.py b/mercury/tests/test_event.py index 398a38bb..5aa6d5aa 100644 --- a/mercury/tests/test_event.py +++ b/mercury/tests/test_event.py @@ -1,6 +1,7 @@ from django.test import TestCase from django.urls import reverse -from mercury.models import AGEvent, EventCodeAccess +from mercury.models import EventCodeAccess +from ag_data.models import AGEvent import datetime diff --git a/mercury/views/dashboard.py b/mercury/views/dashboard.py index 75024722..45857d28 100644 --- a/mercury/views/dashboard.py +++ b/mercury/views/dashboard.py @@ -1,8 +1,7 @@ from django.shortcuts import render from django.views.generic import TemplateView - +from ag_data.models import AGEvent from mercury.models import ( - AGEvent, TemperatureSensor, AccelerationSensor, WheelSpeedSensor, diff --git a/mercury/views/event.py b/mercury/views/event.py index abce1b76..9027cf31 100644 --- a/mercury/views/event.py +++ b/mercury/views/event.py @@ -4,7 +4,7 @@ from ..event_check import require_event_code from mercury.forms import EventForm -from mercury.models import AGEvent +from ag_data.models import AGEvent log = logging.getLogger(__name__) log.setLevel(logging.ERROR) diff --git a/mercury/views/events.py b/mercury/views/events.py index bc4574a1..9f60cd70 100644 --- a/mercury/views/events.py +++ b/mercury/views/events.py @@ -4,7 +4,7 @@ from django.views.generic import TemplateView from ..event_check import require_event_code from mercury.forms import EventForm -from mercury.models import AGEvent +from ag_data.models import AGEvent log = logging.getLogger(__name__) log.setLevel(logging.ERROR) diff --git a/mercury/views/sensor.py b/mercury/views/sensor.py index 002d2519..1bac603f 100644 --- a/mercury/views/sensor.py +++ b/mercury/views/sensor.py @@ -2,7 +2,7 @@ from django.shortcuts import render from django.views.generic import TemplateView from ..event_check import require_event_code -from mercury.models import AGSensor +from ag_data.models import AGSensor, AGSensorType from django.contrib import messages log = logging.getLogger(__name__) @@ -24,7 +24,7 @@ def validate_add_sensor_inputs(sensor_name, field_name_list, request): form_valid = False # duplicated sensor name - if AGSensor.objects.filter(sensor_name=sensor_name).count() > 0: + if AGSensor.objects.filter(name=sensor_name).count() > 0: messages.error(request, "Sensor name is already taken.") form_valid = False @@ -66,13 +66,11 @@ def post(self, request, *args, **kwargs): for field in fields: sensor_format[field[0]] = {"data_type": field[1], "unit": field[2]} + sensor_type = AGSensorType(name='Homer_Simpson', processing_formula=0, format=sensor_format) + sensor_type.save() + if valid: - sensor = AGSensor.objects.create( - sensor_id=id_num, - sensor_name=sensor_name, - sensor_processing_formula=0, - sensor_format=sensor_format, - ) # processing formula needs to be adapted + sensor = AGSensor.objects.create(name=sensor_name, type_id=sensor_type) sensor.save() sensors = AGSensor.objects.all() context = {"sensors": sensors} @@ -84,4 +82,4 @@ def post(self, request, *args, **kwargs): "sensor_format": sensor_format, } - return render(request, self.template_name, context) + return render(request, self.template_name, context) \ No newline at end of file diff --git a/mercury/views/simulator.py b/mercury/views/simulator.py index 8f340fbd..de892f26 100644 --- a/mercury/views/simulator.py +++ b/mercury/views/simulator.py @@ -3,9 +3,8 @@ from django.http import HttpResponse from django.shortcuts import render from django.views.generic import TemplateView - +from ag_data.models import AGEvent from mercury.models import ( - AGEvent, TemperatureSensor, AccelerationSensor, WheelSpeedSensor, From 992b73fe35780a595be0a4bdbd3d7a247326d1fb Mon Sep 17 00:00:00 2001 From: dandipietrantonio Date: Fri, 20 Mar 2020 18:36:13 -0400 Subject: [PATCH 07/21] POST for adding type is working, now working on adding sensor --- mercury/static/mercury/js/sensor.js | 61 +++++++++++++++-- mercury/static/mercury/style.css | 4 +- mercury/templates/sensor.html | 102 +++++++++++++++++++++++++--- mercury/views/sensor.py | 51 +++++++------- 4 files changed, 177 insertions(+), 41 deletions(-) diff --git a/mercury/static/mercury/js/sensor.js b/mercury/static/mercury/js/sensor.js index a99d50f3..494a651a 100644 --- a/mercury/static/mercury/js/sensor.js +++ b/mercury/static/mercury/js/sensor.js @@ -1,5 +1,5 @@ function addRow(){ - var table = document.getElementById("new-sensor-table"); + var table = document.getElementById("new-type-table"); var rowCount = table.rows.length; var colCount = table.rows[0].cells.length; var newRow = table.insertRow(rowCount); @@ -12,7 +12,7 @@ function addRow(){ } function deleteRow() { - var table = document.getElementById("new-sensor-table"); + var table = document.getElementById("new-type-table"); var rowCount = table.rows.length; if (rowCount > 2){ table.deleteRow(rowCount-1) @@ -25,28 +25,65 @@ selectView displays the correct view of the "Add or Modify Sensors" page -if a user submits a new sensor which posts and reloads page, then the add new sensor view should remain */ function selectView() { + var newSensorDiv = document.getElementById("add-new-sensor"); var existingSensorDiv = document.getElementById("existing-sensors"); + var newTypeDiv = document.getElementById("add-new-type"); + var viewTypesDiv = document.getElementById("view-existing-types"); + var modifyButton = document.getElementById("current-sensor-btn"); - var newButton = document.getElementById("add-sensor-btn"); + var newSensorButton = document.getElementById("add-sensor-btn"); + var newTypeButton = document.getElementById("add-sensor-type-btn"); + var viewTypesButton = document.getElementById("view-sensor-types-btn"); + if (sessionStorage.getItem('viewing') == 'addingNew'){ newSensorDiv.style.display = "block"; existingSensorDiv.style.display = 'none'; + newTypeDiv.style.display = "none"; + viewTypesDiv.style.display = "none"; modifyButton.style.backgroundColor = 'var(--light-accent)'; - newButton.style.backgroundColor = 'var(--green)'; + newSensorButton.style.backgroundColor = 'var(--green)'; + newTypeButton.style.backgroundColor = 'var(--light--accent)'; + viewTypesButton.style.backgroundColor = 'var(--light--accent)'; } - else { + else if (sessionStorage.getItem('viewing') == 'view-sensors'){ newSensorDiv.style.display = "none"; existingSensorDiv.style.display = 'block'; + newTypeDiv.style.display = "none"; + viewTypesDiv.style.display = "none"; modifyButton.style.backgroundColor = 'var(--green)'; - newButton.style.backgroundColor = 'var(--light-accent)'; + newSensorButton.style.backgroundColor = 'var(--light-accent)'; + newTypeButton.style.backgroundColor = 'var(--light-accent)'; + viewTypesButton.style.backgroundColor = 'var(--light--accent)'; + } + else if (sessionStorage.getItem('viewing') == 'addingNewType'){ + newSensorDiv.style.display = "none"; + existingSensorDiv.style.display = 'none'; + newTypeDiv.style.display = "block"; + viewTypesDiv.style.display = "none"; + + modifyButton.style.backgroundColor = 'var(--light-accent)'; + newSensorButton.style.backgroundColor = 'var(--light-accent)'; + newTypeButton.style.backgroundColor = 'var(--green)'; + viewTypesButton.style.backgroundColor = 'var(--light--accent)'; + } + else if (sessionStorage.getItem('viewing') == 'viewingTypes'){ + newSensorDiv.style.display = "none"; + existingSensorDiv.style.display = 'none'; + newTypeDiv.style.display = "none"; + viewTypesDiv.style.display = "block"; + + modifyButton.style.backgroundColor = 'var(--light-accent)'; + newSensorButton.style.backgroundColor = 'var(--light-accent)'; + newTypeButton.style.backgroundColor = 'var(--light--accent)'; + viewTypesButton.style.backgroundColor = 'var(--green)'; } } function displayCurrentSensors() { - sessionStorage.setItem('viewing', 'existing'); + sessionStorage.setItem('viewing', 'view-sensors'); selectView() } @@ -54,3 +91,13 @@ function displayAddNewSensor() { sessionStorage.setItem('viewing', 'addingNew'); selectView() } + +function displayAddNewSensorType() { + sessionStorage.setItem('viewing', 'addingNewType'); + selectView() +} + +function displaySensorTypes() { + sessionStorage.setItem('viewing', 'viewingTypes'); + selectView() +} diff --git a/mercury/static/mercury/style.css b/mercury/static/mercury/style.css index d8dcfa2b..1ec84382 100644 --- a/mercury/static/mercury/style.css +++ b/mercury/static/mercury/style.css @@ -21,9 +21,9 @@ nav li{ list-style-type: none; /* removes bulleting */ } -#sensor-container{ +/* #sensor-container{ background-color:lightgray; -} +} */ .inline-box{ display: inline-block; diff --git a/mercury/templates/sensor.html b/mercury/templates/sensor.html index 1c581e5c..de0c3027 100644 --- a/mercury/templates/sensor.html +++ b/mercury/templates/sensor.html @@ -22,6 +22,8 @@

Add or Modify Sensors

  • +
  • +
  • @@ -76,20 +78,52 @@

    Field Unit

    -

    Configure a New Sensor

    +

    Add a New Sensor


    {% csrf_token %}
    - + - + + + + + +

    +

    +

    Preview

    + + +
    +
    +
    + +
    +

    Add a New Sensor Type

    +
    +
    + {% csrf_token %} +
    +
    + + + +
    + + +

    - +
    @@ -123,18 +157,70 @@

    Configure a New Sensor



    -
    +
    - +
    - {% for message in messages %}

    {{ message }}

    {% endfor %} - + + +
    +

    Existing Types

    + + {% if sensor_types %} + {% for sensor_type in sensor_types %} +
    +

    + {{ sensor_type.name }}

    + +

    Field Name

    +

    Field Type

    +

    Field Unit

    + + {% for field_name, unit_and_format in sensor_type.format.items %} +
    +

    {{field_name}}

    +

    {{unit_and_format.data_type}}

    + +

    {{unit_and_format.unit}}

    +
    + {% endfor %} + +
    + {% endfor %} + {% else %} +

    There are no types to display

    + + {% endif%} + +
    + diff --git a/mercury/views/sensor.py b/mercury/views/sensor.py index 98e643ca..60a92398 100644 --- a/mercury/views/sensor.py +++ b/mercury/views/sensor.py @@ -11,23 +11,23 @@ log.setLevel(logging.ERROR) -def validate_add_sensor_inputs(sensor_name, field_name_list, request): +def validate_add_sensor_type_inputs(type_name, field_name_list, request): form_valid = True - # no sensor name - if not sensor_name: - messages.error(request, "Sensor name is missing or invalid.") + # no type name + if not type_name: + messages.error(request, "Type name is missing or invalid.") form_valid = False # missing field names for name in field_name_list: if not name: - messages.error(request, "Sensor has missing field name(s).") + messages.error(request, "Type has missing field name(s).") form_valid = False # duplicated sensor name - if AGSensor.objects.filter(name=sensor_name).count() > 0: - messages.error(request, "Sensor name is already taken.") + if AGSensor.objects.filter(name=type_name).count() > 0: + messages.error(request, "Type name is already taken.") form_valid = False # duplicated field names @@ -46,42 +46,45 @@ class CreateSensorView(TemplateView): @require_event_code def get(self, request, *args, **kwargs): sensors = AGSensor.objects.all() - context = {"sensors": sensors} + sensor_types = AGSensorType.objects.all() + context = {"sensors": sensors, "sensor_types": sensor_types} return render(request, self.template_name, context) @require_event_code def post(self, request, *args, **kwargs): - id_num = request.POST.get("sensor-id-num") - sensor_name = request.POST.get("sensor-name") + id_num = request.POST.get("type-id-num") + type_name = request.POST.get("type-name") field_names = request.POST.getlist("field-names") field_types = request.POST.getlist("data-types") field_units = request.POST.getlist("units") + print("\n\n FIELD TYPES: " + str(field_types) + "\n\n") # reformat then validate inputs to avoid duplicated names or bad inputs like " " - sensor_name = sensor_name.strip().lower() # remove excess whitespace and CAPS + type_name = type_name.strip().lower() # remove excess whitespace and CAPS field_names = [string.strip().lower() for string in field_names] - valid, request = validate_add_sensor_inputs(sensor_name, field_names, request) + valid, request = validate_add_sensor_type_inputs(type_name, field_names, request) # create sensor format which is dictionary of dictionaries - sensor_format = {} + type_format = {} fields = zip(field_names, field_types, field_units) for field in fields: - sensor_format[field[0]] = {"data_type": field[1], "unit": field[2]} + type_format[field[0]] = {"data_type": field[1], "unit": field[2]} - sensor_type = AGSensorType(name='Homer_Simpson', processing_formula=0, format=sensor_format) - sensor_type.save() + # Left over from when this was for old models, not sure if it's valuable later: + # sensor = AGSensorType(name='Homer_Simpson', processing_formula=0, format=type_format) + # sensor.save() if valid: - sensor = AGSensor.objects.create(name=sensor_name, type_id=sensor_type) - sensor.save() - sensors = AGSensor.objects.all() - context = {"sensors": sensors} + new_type = AGSensorType.objects.create(name=type_name, id=id_num, processing_formula = 0, format= type_format) + new_type.save() + sensor_types = AGSensorType.objects.all() + context = {"sensor_types": sensor_types} else: - sensors = AGSensor.objects.all() + sensor_types = AGSensorType.objects.all() context = { - "sensors": sensors, - "sensor_name": sensor_name, - "sensor_format": sensor_format, + "sensors": sensor_types, + "type_name": type_name, + "type_format": type_format, } return render(request, self.template_name, context) \ No newline at end of file From 647e05fdef53ee9bbe4377fd597cf2445252da42 Mon Sep 17 00:00:00 2001 From: dandipietrantonio Date: Fri, 20 Mar 2020 19:49:51 -0400 Subject: [PATCH 08/21] Able to add sensors but the displaying breaks, need to fix --- mercury/static/mercury/js/sensor.js | 10 +-- mercury/templates/sensor.html | 40 ++-------- mercury/views/sensor.py | 115 +++++++++++++++++++--------- 3 files changed, 89 insertions(+), 76 deletions(-) diff --git a/mercury/static/mercury/js/sensor.js b/mercury/static/mercury/js/sensor.js index 494a651a..aed94aaa 100644 --- a/mercury/static/mercury/js/sensor.js +++ b/mercury/static/mercury/js/sensor.js @@ -44,8 +44,8 @@ function selectView() { modifyButton.style.backgroundColor = 'var(--light-accent)'; newSensorButton.style.backgroundColor = 'var(--green)'; - newTypeButton.style.backgroundColor = 'var(--light--accent)'; - viewTypesButton.style.backgroundColor = 'var(--light--accent)'; + newTypeButton.style.backgroundColor = 'var(--light-accent)'; + viewTypesButton.style.backgroundColor = 'var(--light-accent)'; } else if (sessionStorage.getItem('viewing') == 'view-sensors'){ newSensorDiv.style.display = "none"; @@ -56,7 +56,7 @@ function selectView() { modifyButton.style.backgroundColor = 'var(--green)'; newSensorButton.style.backgroundColor = 'var(--light-accent)'; newTypeButton.style.backgroundColor = 'var(--light-accent)'; - viewTypesButton.style.backgroundColor = 'var(--light--accent)'; + viewTypesButton.style.backgroundColor = 'var(--light-accent)'; } else if (sessionStorage.getItem('viewing') == 'addingNewType'){ newSensorDiv.style.display = "none"; @@ -67,7 +67,7 @@ function selectView() { modifyButton.style.backgroundColor = 'var(--light-accent)'; newSensorButton.style.backgroundColor = 'var(--light-accent)'; newTypeButton.style.backgroundColor = 'var(--green)'; - viewTypesButton.style.backgroundColor = 'var(--light--accent)'; + viewTypesButton.style.backgroundColor = 'var(--light-accent)'; } else if (sessionStorage.getItem('viewing') == 'viewingTypes'){ newSensorDiv.style.display = "none"; @@ -77,7 +77,7 @@ function selectView() { modifyButton.style.backgroundColor = 'var(--light-accent)'; newSensorButton.style.backgroundColor = 'var(--light-accent)'; - newTypeButton.style.backgroundColor = 'var(--light--accent)'; + newTypeButton.style.backgroundColor = 'var(--light-accent)'; viewTypesButton.style.backgroundColor = 'var(--green)'; } } diff --git a/mercury/templates/sensor.html b/mercury/templates/sensor.html index de0c3027..c42cf8b0 100644 --- a/mercury/templates/sensor.html +++ b/mercury/templates/sensor.html @@ -87,22 +87,20 @@

    Add a New Sensor

    - - -

    Preview

    - +
    @@ -116,11 +114,6 @@

    Add a New Sensor Type

    - -
    - - -

    Field Number
    @@ -159,7 +152,7 @@

    Add a New Sensor Type


    - +
    @@ -188,25 +181,6 @@

    Field Unit

    contenteditable="true">{{field_name}}

    {{unit_and_format.data_type}}

    -

    {{unit_and_format.unit}}

    diff --git a/mercury/views/sensor.py b/mercury/views/sensor.py index 60a92398..1f73b20e 100644 --- a/mercury/views/sensor.py +++ b/mercury/views/sensor.py @@ -25,8 +25,8 @@ def validate_add_sensor_type_inputs(type_name, field_name_list, request): messages.error(request, "Type has missing field name(s).") form_valid = False - # duplicated sensor name - if AGSensor.objects.filter(name=type_name).count() > 0: + # duplicated type name + if AGSensorType.objects.filter(name=type_name).count() > 0: messages.error(request, "Type name is already taken.") form_valid = False @@ -37,6 +37,22 @@ def validate_add_sensor_type_inputs(type_name, field_name_list, request): return form_valid, request +def validate_add_sensor_inputs(sensor_name, request): + form_valid = True + print("\n\n") + print("IN VALIDATE") + print("\n") #DEBUG + # no sensor name + if not sensor_name: + messages.error(request, "Sensor name is missing or invalid.") + form_valid = False + + # duplicated sensor name + if AGSensor.objects.filter(name=sensor_name).count() > 0: + messages.error(request, "Sensor name is already taken.") + form_valid = False + + return form_valid, request class CreateSensorView(TemplateView): """This is the view for creating a new event.""" @@ -52,39 +68,62 @@ def get(self, request, *args, **kwargs): @require_event_code def post(self, request, *args, **kwargs): - id_num = request.POST.get("type-id-num") - type_name = request.POST.get("type-name") - field_names = request.POST.getlist("field-names") - field_types = request.POST.getlist("data-types") - field_units = request.POST.getlist("units") - print("\n\n FIELD TYPES: " + str(field_types) + "\n\n") - - # reformat then validate inputs to avoid duplicated names or bad inputs like " " - type_name = type_name.strip().lower() # remove excess whitespace and CAPS - field_names = [string.strip().lower() for string in field_names] - valid, request = validate_add_sensor_type_inputs(type_name, field_names, request) - - # create sensor format which is dictionary of dictionaries - type_format = {} - fields = zip(field_names, field_types, field_units) - for field in fields: - type_format[field[0]] = {"data_type": field[1], "unit": field[2]} - - # Left over from when this was for old models, not sure if it's valuable later: - # sensor = AGSensorType(name='Homer_Simpson', processing_formula=0, format=type_format) - # sensor.save() - - if valid: - new_type = AGSensorType.objects.create(name=type_name, id=id_num, processing_formula = 0, format= type_format) - new_type.save() - sensor_types = AGSensorType.objects.all() - context = {"sensor_types": sensor_types} - else: - sensor_types = AGSensorType.objects.all() - context = { - "sensors": sensor_types, - "type_name": type_name, - "type_format": type_format, - } - - return render(request, self.template_name, context) \ No newline at end of file + if ("submit_new_type" in request.POST): + print("SUBMITTING NEW TYPE") + type_name = request.POST.get("type-name") + field_names = request.POST.getlist("field-names") + field_types = request.POST.getlist("data-types") + field_units = request.POST.getlist("units") + + # reformat then validate inputs to avoid duplicated names or bad inputs like " " + type_name = type_name.strip().lower() # remove excess whitespace and CAPS + field_names = [string.strip().lower() for string in field_names] + valid, request = validate_add_sensor_type_inputs(type_name, field_names, request) + + # create sensor format which is dictionary of dictionaries + type_format = {} + fields = zip(field_names, field_types, field_units) + for field in fields: + type_format[field[0]] = {"data_type": field[1], "unit": field[2]} + + # Left over from when this was for old models, not sure if it's valuable later: + # sensor = AGSensorType(name='Homer_Simpson', processing_formula=0, format=type_format) + # sensor.save() + + if valid: + new_type = AGSensorType.objects.create(name=type_name, processing_formula=0, format=type_format) + new_type.save() + sensor_types = AGSensorType.objects.all() + context = {"sensor_types": sensor_types} + else: + sensor_types = AGSensorType.objects.all() + context = { + "sensor_types": sensor_types, + "type_name": type_name, + "type_format": type_format, + } + + return render(request, self.template_name, context) + + elif ("submit_new_sensor" in request.POST): + sensor_name = request.POST.get("sensor-name") + sensor_type = request.POST.get("select-sensor-type") + sensor_type = AGSensorType.objects.get(name=sensor_type) + + # reformat then validate name to avoid duplicated names or bad inputs like " " + sensor_name = sensor_name.strip().lower() # remove excess whitespace and CAPS + valid, request = validate_add_sensor_inputs(sensor_name, request) + + if valid: + new_sensor = AGSensor.objects.create(name=sensor_name, type_id=sensor_type) + new_sensor.save() + sensors = AGSensor.objects.all() + context = {"sensors": sensors} + else: + sensors = AGSensor.objects.all() + context = { + "sensors": sensors, + "sensor_name": sensor_name, + "sensor_type": sensor_type, + } + return render(request, self.template_name, context) \ No newline at end of file From e6f12672ee4fc2e892fdf4f33c967224258e3129 Mon Sep 17 00:00:00 2001 From: dandipietrantonio Date: Fri, 20 Mar 2020 20:19:24 -0400 Subject: [PATCH 09/21] Creating new sensor and sensor types working --- mercury/templates/sensor.html | 50 +++++++++++++---------------------- mercury/views/sensor.py | 21 ++++++++++----- 2 files changed, 32 insertions(+), 39 deletions(-) diff --git a/mercury/templates/sensor.html b/mercury/templates/sensor.html index c42cf8b0..ba8a7b5d 100644 --- a/mercury/templates/sensor.html +++ b/mercury/templates/sensor.html @@ -33,40 +33,22 @@

    Existing sensors

    {% if sensors %} {% for sensor in sensors %}
    -

    - {{ sensor.sensor_name }}

    +

    + {{ sensor.name }}

    -

    Field Name

    -

    Field Type

    -

    Field Unit

    +

    Sensor Name

    +

    Sensor ID

    +

    Sensor Type

    - {% for field_name, unit_and_format in sensor.sensor_format.items %}

    {{field_name}}

    - + contenteditable="false">{{ sensor.name }}

    {{unit_and_format.unit}}

    + contenteditable="false">{{ sensor.id }}

    +

    {{ sensor.type_id }}

    - {% endfor %} +
    {% endfor %} @@ -168,9 +150,13 @@

    Existing Types

    {% if sensor_types %} {% for sensor_type in sensor_types %}
    -

    +

    {{ sensor_type.name }}

    +
    + ID: {{ sensor_type.id }} +
    +

    Field Name

    Field Type

    Field Unit

    @@ -178,11 +164,11 @@

    Field Unit

    {% for field_name, unit_and_format in sensor_type.format.items %}

    {{field_name}}

    + contenteditable="false">{{field_name}}

    {{unit_and_format.data_type}}

    + contenteditable="false">{{unit_and_format.data_type}}

    {{unit_and_format.unit}}

    + contenteditable="false">{{unit_and_format.unit}}

    {% endfor %} diff --git a/mercury/views/sensor.py b/mercury/views/sensor.py index 1f73b20e..dc5c7a79 100644 --- a/mercury/views/sensor.py +++ b/mercury/views/sensor.py @@ -39,9 +39,7 @@ def validate_add_sensor_type_inputs(type_name, field_name_list, request): def validate_add_sensor_inputs(sensor_name, request): form_valid = True - print("\n\n") - print("IN VALIDATE") - print("\n") #DEBUG + # no sensor name if not sensor_name: messages.error(request, "Sensor name is missing or invalid.") @@ -69,7 +67,6 @@ def get(self, request, *args, **kwargs): @require_event_code def post(self, request, *args, **kwargs): if ("submit_new_type" in request.POST): - print("SUBMITTING NEW TYPE") type_name = request.POST.get("type-name") field_names = request.POST.getlist("field-names") field_types = request.POST.getlist("data-types") @@ -90,17 +87,22 @@ def post(self, request, *args, **kwargs): # sensor = AGSensorType(name='Homer_Simpson', processing_formula=0, format=type_format) # sensor.save() + sensors = AGSensor.objects.all() #for when we return context later if valid: new_type = AGSensorType.objects.create(name=type_name, processing_formula=0, format=type_format) new_type.save() sensor_types = AGSensorType.objects.all() - context = {"sensor_types": sensor_types} + context = { + "sensor_types": sensor_types, + "sensors": sensors, + } else: sensor_types = AGSensorType.objects.all() context = { "sensor_types": sensor_types, "type_name": type_name, "type_format": type_format, + "sensors": sensors, } return render(request, self.template_name, context) @@ -108,22 +110,27 @@ def post(self, request, *args, **kwargs): elif ("submit_new_sensor" in request.POST): sensor_name = request.POST.get("sensor-name") sensor_type = request.POST.get("select-sensor-type") - sensor_type = AGSensorType.objects.get(name=sensor_type) + sensor_type = AGSensorType.objects.get(name=sensor_type) #str --> AGSensorType # reformat then validate name to avoid duplicated names or bad inputs like " " sensor_name = sensor_name.strip().lower() # remove excess whitespace and CAPS valid, request = validate_add_sensor_inputs(sensor_name, request) + sensor_types = AGSensorType.objects.all() #for when we return context later if valid: new_sensor = AGSensor.objects.create(name=sensor_name, type_id=sensor_type) new_sensor.save() sensors = AGSensor.objects.all() - context = {"sensors": sensors} + context = { + "sensors": sensors, + "sensor_types": sensor_types, + } else: sensors = AGSensor.objects.all() context = { "sensors": sensors, "sensor_name": sensor_name, "sensor_type": sensor_type, + "sensor_types": sensor_types, } return render(request, self.template_name, context) \ No newline at end of file From 802a2ddea830391d4c11d47d062c859b0d4016ce Mon Sep 17 00:00:00 2001 From: dandipietrantonio Date: Sat, 21 Mar 2020 13:52:53 -0400 Subject: [PATCH 10/21] Delete sensors and delete sensor types both working, moving on to editing --- mercury/static/mercury/style.css | 7 +++ mercury/templates/sensor.html | 73 ++++++++++++++++++-------------- mercury/templates/sidebar.html | 2 +- mercury/urls.py | 2 + mercury/views/sensor.py | 20 ++++++++- 5 files changed, 71 insertions(+), 33 deletions(-) diff --git a/mercury/static/mercury/style.css b/mercury/static/mercury/style.css index 1ec84382..5f29159f 100644 --- a/mercury/static/mercury/style.css +++ b/mercury/static/mercury/style.css @@ -4405,4 +4405,11 @@ a { .rounded { border-radius: 0.35rem !important; } + +.center-image { + display: block; + margin-left: auto; + margin-right: auto; + width: 50%; +} diff --git a/mercury/templates/sensor.html b/mercury/templates/sensor.html index ba8a7b5d..22d343a5 100644 --- a/mercury/templates/sensor.html +++ b/mercury/templates/sensor.html @@ -20,41 +20,48 @@

    Add or Modify Sensors

    Existing sensors

    - +
    {% if sensors %} {% for sensor in sensors %}

    {{ sensor.name }}

    -

    Sensor Name

    -

    Sensor ID

    -

    Sensor Type

    +
    + ID: {{ sensor.id }} +
    +
    + +

    Field Name

    +

    Field Type

    +

    Field Unit

    + {% for field_name, unit_and_format in sensor.type_id.format.items %}

    {{ sensor.name }}

    + contenteditable="false">{{field_name}}

    {{ sensor.id }}

    + contenteditable="false">{{unit_and_format.data_type}}

    {{ sensor.type_id }}

    + contenteditable="false">{{unit_and_format.unit}}

    - - + {% endfor %} + Delete + Edit
    {% endfor %} {% else %} -

    There are no sensors to display

    - +

    There are no sensors to display

    + {% endif%}
    @@ -62,20 +69,18 @@

    Sensor Type

    Add a New Sensor


    -
    - {% csrf_token %} -
    -
    - - - - - + +

    @@ -84,6 +89,10 @@

    Preview

    + {% else %} +

    Add a sensor type in "Add New Sensor Type" to proceed

    + + {% endif%}
    @@ -146,7 +155,7 @@

    Add a New Sensor Type

    Existing Types

    - +
    {% if sensor_types %} {% for sensor_type in sensor_types %}
    @@ -156,6 +165,7 @@

    ID: {{ sensor_type.id }}
    +

    Field Name

    Field Type

    @@ -171,12 +181,13 @@

    Field Unit

    contenteditable="false">{{unit_and_format.unit}}

    {% endfor %} - + Delete + Edit
    {% endfor %} {% else %} -

    There are no types to display

    - +

    There are no types to display

    + {% endif%}
    diff --git a/mercury/templates/sidebar.html b/mercury/templates/sidebar.html index 897ea3fe..a4b8a7af 100644 --- a/mercury/templates/sidebar.html +++ b/mercury/templates/sidebar.html @@ -70,7 +70,7 @@ {% if request.path == "/sensor/" %} {% else %} diff --git a/mercury/urls.py b/mercury/urls.py index 9d2ee76f..f00e96fd 100644 --- a/mercury/urls.py +++ b/mercury/urls.py @@ -23,6 +23,8 @@ path("can/", can.CANUI.as_view(), name="can-ui"), # CAN Decoder UI endpoint path("event/", event.CreateEventView.as_view(), name="event"), path("sensor/", sensor.CreateSensorView.as_view(), name="sensor"), + path("sensor/delete_sensor/", sensor.delete_sensor), + path("sensor/delete_type/", sensor.delete_sensor_type), path("events/", events.CreateEventsView.as_view(), name="events"), path("events/delete/", events.delete_event), path("events/update/", events.update_event), diff --git a/mercury/views/sensor.py b/mercury/views/sensor.py index dc5c7a79..c1b041c2 100644 --- a/mercury/views/sensor.py +++ b/mercury/views/sensor.py @@ -1,5 +1,5 @@ import logging -from django.shortcuts import render +from django.shortcuts import render, redirect from django.views.generic import TemplateView from ..event_check import require_event_code @@ -12,6 +12,8 @@ def validate_add_sensor_type_inputs(type_name, field_name_list, request): + """This validates the form before a user submits a new sensor type to prevent bad inputs""" + form_valid = True # no type name @@ -38,6 +40,8 @@ def validate_add_sensor_type_inputs(type_name, field_name_list, request): return form_valid, request def validate_add_sensor_inputs(sensor_name, request): + """This validates the form before a user submits a new sensor to prevent bad inputs""" + form_valid = True # no sensor name @@ -52,6 +56,20 @@ def validate_add_sensor_inputs(sensor_name, request): return form_valid, request +def delete_sensor(request, sensor_id): + """This deletes a sensor from the database based on user button click""" + + sensor_to_delete = AGSensor.objects.get(id=sensor_id) + sensor_to_delete.delete() + return redirect("/sensor") + +def delete_sensor_type(request, type_id): + """This deletes a sensor type from the database based on user button click""" + + type_to_delete = AGSensorType.objects.get(id=type_id) + type_to_delete.delete() + return redirect("/sensor") + class CreateSensorView(TemplateView): """This is the view for creating a new event.""" From 1eba0a6b07afe7f81727dc800e945f7a6c01835e Mon Sep 17 00:00:00 2001 From: dandipietrantonio Date: Sat, 21 Mar 2020 16:11:55 -0400 Subject: [PATCH 11/21] Can now edit existing sensors, still need to fix a few bugs, add transformation preview, and add a ton of tests --- mercury/static/mercury/js/sensor.js | 60 +++++++++++++++ mercury/templates/sensor.html | 113 ++++++++++++++++++++++++++-- mercury/urls.py | 2 + mercury/views/sensor.py | 78 ++++++++++++++++++- 4 files changed, 245 insertions(+), 8 deletions(-) diff --git a/mercury/static/mercury/js/sensor.js b/mercury/static/mercury/js/sensor.js index aed94aaa..6e76d3f4 100644 --- a/mercury/static/mercury/js/sensor.js +++ b/mercury/static/mercury/js/sensor.js @@ -30,55 +30,105 @@ function selectView() { var existingSensorDiv = document.getElementById("existing-sensors"); var newTypeDiv = document.getElementById("add-new-type"); var viewTypesDiv = document.getElementById("view-existing-types"); + var editSensorsDiv = document.getElementById("edit-sensors"); + var editSensorTypesDiv = document.getElementById("edit-sensor-types"); var modifyButton = document.getElementById("current-sensor-btn"); var newSensorButton = document.getElementById("add-sensor-btn"); var newTypeButton = document.getElementById("add-sensor-type-btn"); var viewTypesButton = document.getElementById("view-sensor-types-btn"); + var editSensorsButton = document.getElementById("edit-sensors-btn"); + var editSensorTypesButton = document.getElementById("edit-sensor-types-btn"); if (sessionStorage.getItem('viewing') == 'addingNew'){ newSensorDiv.style.display = "block"; existingSensorDiv.style.display = 'none'; newTypeDiv.style.display = "none"; viewTypesDiv.style.display = "none"; + editSensorsDiv.style.display = "none"; + editSensorTypesDiv.style.display = "none"; modifyButton.style.backgroundColor = 'var(--light-accent)'; newSensorButton.style.backgroundColor = 'var(--green)'; newTypeButton.style.backgroundColor = 'var(--light-accent)'; viewTypesButton.style.backgroundColor = 'var(--light-accent)'; + editSensorsButton.style.backgroundColor = 'var(--light-accent)'; + editSensorTypesButton.style.backgroundColor = 'var(--light-accent)'; } else if (sessionStorage.getItem('viewing') == 'view-sensors'){ newSensorDiv.style.display = "none"; existingSensorDiv.style.display = 'block'; newTypeDiv.style.display = "none"; viewTypesDiv.style.display = "none"; + editSensorsDiv.style.display = "none"; + editSensorTypesDiv.style.display = "none"; modifyButton.style.backgroundColor = 'var(--green)'; newSensorButton.style.backgroundColor = 'var(--light-accent)'; newTypeButton.style.backgroundColor = 'var(--light-accent)'; viewTypesButton.style.backgroundColor = 'var(--light-accent)'; + editSensorsButton.style.backgroundColor = 'var(--light-accent)'; + editSensorTypesButton.style.backgroundColor = 'var(--light-accent)'; } else if (sessionStorage.getItem('viewing') == 'addingNewType'){ newSensorDiv.style.display = "none"; existingSensorDiv.style.display = 'none'; newTypeDiv.style.display = "block"; viewTypesDiv.style.display = "none"; + editSensorsDiv.style.display = "none"; + editSensorTypesDiv.style.display = "none"; modifyButton.style.backgroundColor = 'var(--light-accent)'; newSensorButton.style.backgroundColor = 'var(--light-accent)'; newTypeButton.style.backgroundColor = 'var(--green)'; viewTypesButton.style.backgroundColor = 'var(--light-accent)'; + editSensorsButton.style.backgroundColor = 'var(--light-accent)'; + editSensorTypesButton.style.backgroundColor = 'var(--light-accent)'; } else if (sessionStorage.getItem('viewing') == 'viewingTypes'){ newSensorDiv.style.display = "none"; existingSensorDiv.style.display = 'none'; newTypeDiv.style.display = "none"; viewTypesDiv.style.display = "block"; + editSensorsDiv.style.display = "none"; + editSensorTypesDiv.style.display = "none"; modifyButton.style.backgroundColor = 'var(--light-accent)'; newSensorButton.style.backgroundColor = 'var(--light-accent)'; newTypeButton.style.backgroundColor = 'var(--light-accent)'; viewTypesButton.style.backgroundColor = 'var(--green)'; + editSensorsButton.style.backgroundColor = 'var(--light-accent)'; + editSensorTypesButton.style.backgroundColor = 'var(--light-accent)'; + } + else if (sessionStorage.getItem('viewing') == 'editingSensors'){ + newSensorDiv.style.display = "none"; + existingSensorDiv.style.display = 'none'; + newTypeDiv.style.display = "none"; + viewTypesDiv.style.display = "none"; + editSensorsDiv.style.display = "block"; + editSensorTypesDiv.style.display = "none"; + + modifyButton.style.backgroundColor = 'var(--light-accent)'; + newSensorButton.style.backgroundColor = 'var(--light-accent)'; + newTypeButton.style.backgroundColor = 'var(--light-accent)'; + viewTypesButton.style.backgroundColor = 'var(--light-accent)'; + editSensorsButton.style.backgroundColor = 'var(--green)'; + editSensorTypesButton.style.backgroundColor = 'var(--light-accent)'; + } + else if (sessionStorage.getItem('viewing') == 'editingSensorTypes'){ + newSensorDiv.style.display = "none"; + existingSensorDiv.style.display = 'none'; + newTypeDiv.style.display = "none"; + viewTypesDiv.style.display = "none"; + editSensorsDiv.style.display = "none"; + editSensorTypesDiv.style.display = "block"; + + modifyButton.style.backgroundColor = 'var(--light-accent)'; + newSensorButton.style.backgroundColor = 'var(--light-accent)'; + newTypeButton.style.backgroundColor = 'var(--light-accent)'; + viewTypesButton.style.backgroundColor = 'var(--light-accent)'; + editSensorsButton.style.backgroundColor = 'var(--light-accent)'; + editSensorTypesButton.style.backgroundColor = 'var(--green)'; } } @@ -101,3 +151,13 @@ function displaySensorTypes() { sessionStorage.setItem('viewing', 'viewingTypes'); selectView() } + +function displayEditSensors() { + sessionStorage.setItem('viewing', 'editingSensors'); + selectView() +} + +function displayEditSensorTypes() { + sessionStorage.setItem('viewing', 'editingSensorTypes'); + selectView() +} diff --git a/mercury/templates/sensor.html b/mercury/templates/sensor.html index 22d343a5..e1e185b9 100644 --- a/mercury/templates/sensor.html +++ b/mercury/templates/sensor.html @@ -20,15 +20,17 @@

    Add or Modify Sensors

    -

    Existing sensors

    +

    Existing Sensors


    {% if sensors %} {% for sensor in sensors %} @@ -65,7 +67,6 @@

    There are no sensors to display

    {% endif%}
    -

    Add a New Sensor


    @@ -98,7 +99,6 @@

    Add a sensor type in "Add New Sensor Type" to proceed

    Add a New Sensor Type

    -
    {% csrf_token %}
    @@ -191,6 +191,109 @@

    There are no types to display

    {% endif%}
    + +
    +

    Edit Existing Sensors

    +
    + {% if sensors %} +
    +

    + + + + + + + + + + {% for sensor in sensors %} + + {% csrf_token %} + + + + + + + {% endfor %} + +
    SENSOR IDSENSOR NAMESENSOR TYPEUPDATE
    {{ sensor.id }} + +
    +
    + {% else %} +

    There are no sensors to edit

    + + {% endif%} +
    + +
    +

    Edit Existing Sensor Types

    +


    + {% for sensor_type in sensor_types %} +
    + {% csrf_token %} +
    +
    + + +

    + + + + + + + + + + + + {% for field_name, unit_and_format in sensor_type.format.items %} + + + + + + + + {% endfor %} + +
    Field Name Field Data Type Unit
    + +

    + +


    + {% endfor %} +

    +
    +
    diff --git a/mercury/urls.py b/mercury/urls.py index f00e96fd..3139ea19 100644 --- a/mercury/urls.py +++ b/mercury/urls.py @@ -25,6 +25,8 @@ path("sensor/", sensor.CreateSensorView.as_view(), name="sensor"), path("sensor/delete_sensor/", sensor.delete_sensor), path("sensor/delete_type/", sensor.delete_sensor_type), + path("sensor/update_sensor/", sensor.update_sensor), + path("sensor/update_type/", sensor.update_sensor_type), path("events/", events.CreateEventsView.as_view(), name="events"), path("events/delete/", events.delete_event), path("events/update/", events.update_event), diff --git a/mercury/views/sensor.py b/mercury/views/sensor.py index c1b041c2..49560fe7 100644 --- a/mercury/views/sensor.py +++ b/mercury/views/sensor.py @@ -70,6 +70,81 @@ def delete_sensor_type(request, type_id): type_to_delete.delete() return redirect("/sensor") +def update_sensor(request, sensor_id): + """This updates a sensor from the database based on user input""" + + sensor_to_update = AGSensor.objects.get(id=sensor_id) + + sensor_name = request.POST.get("edit-sensor-name") + # reformat then validate name to avoid duplicated names or bad inputs like " " + sensor_name = sensor_name.strip().lower() # remove excess whitespace and CAPS + valid, request = validate_add_sensor_inputs(sensor_name, request) + + sensor_types = AGSensorType.objects.all() #for when we return context later + if valid: + sensor_to_update.name = sensor_name + sensor_type = request.POST.get("edit-select-sensor-type") + sensor_to_update.type_id = AGSensorType.objects.get(name=sensor_type) + sensor_to_update.save() + sensors = AGSensor.objects.all() + context = { + "sensors": sensors, + "sensor_types": sensor_types, + } + else: + sensors = AGSensor.objects.all() + context = { + "sensors": sensors, + "sensor_name": sensor_name, + "sensor_type": sensor_type, + "sensor_types": sensor_types, + } + return render(request, "sensor.html", context) + + +def update_sensor_type(request, type_id): + type_to_update = AGSensorType.objects.get(id=type_id) + print("\n\n" + str(type_to_update.name) + "NAME BEFORE \n") + type_name = request.POST.get("edit-type-name") + field_names = request.POST.getlist("edit-field-names") + field_types = request.POST.getlist("edit-data-types") + field_units = request.POST.getlist("edit-units") + + # reformat then validate inputs to avoid duplicated names or bad inputs like " " + type_name = type_name.strip().lower() # remove excess whitespace and CAPS + field_names = [string.strip().lower() for string in field_names] + valid, request = validate_add_sensor_type_inputs(type_name, field_names, request) + + # create sensor format which is dictionary of dictionaries + type_format = {} + fields = zip(field_names, field_types, field_units) + for field in fields: + type_format[field[0]] = {"data_type": field[1], "unit": field[2]} + + sensors = AGSensor.objects.all() #for when we return context later + if valid: + type_to_update.name=type_name + print("\n\n" + str(type_to_update.name) + "NAME AFTER \n") + type_to_update.processing_formula=0 + type_to_update.format=type_format + type_to_update.save() + sensor_types = AGSensorType.objects.all() + context = { + "sensor_types": sensor_types, + "sensors": sensors, + } + else: + sensor_types = AGSensorType.objects.all() + context = { + "sensor_types": sensor_types, + "type_name": type_name, + "type_format": type_format, + "sensors": sensors, + } + + return render(request, "sensor.html", context) + + class CreateSensorView(TemplateView): """This is the view for creating a new event.""" @@ -101,9 +176,6 @@ def post(self, request, *args, **kwargs): for field in fields: type_format[field[0]] = {"data_type": field[1], "unit": field[2]} - # Left over from when this was for old models, not sure if it's valuable later: - # sensor = AGSensorType(name='Homer_Simpson', processing_formula=0, format=type_format) - # sensor.save() sensors = AGSensor.objects.all() #for when we return context later if valid: From 176709c9a20d5e41129096aec09c5a087ed3c345 Mon Sep 17 00:00:00 2001 From: dandipietrantonio Date: Sun, 22 Mar 2020 11:23:44 -0400 Subject: [PATCH 12/21] Adding, updating, deleting both sensors and sensor types completed, just needs to be tested --- mercury/templates/sensor.html | 8 ++++---- mercury/views/sensor.py | 10 ++++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/mercury/templates/sensor.html b/mercury/templates/sensor.html index e1e185b9..5e0f2981 100644 --- a/mercury/templates/sensor.html +++ b/mercury/templates/sensor.html @@ -57,8 +57,6 @@

    Field Unit

    contenteditable="false">{{unit_and_format.unit}}

    {% endfor %} -
    Delete - Edit {% endfor %} {% else %} @@ -181,8 +179,6 @@

    Field Unit

    contenteditable="false">{{unit_and_format.unit}}

    {% endfor %} - Delete - Edit {% endfor %} {% else %} @@ -204,6 +200,7 @@

    Edit Existing Sensors

    SENSOR NAME SENSOR TYPE UPDATE + DELETE @@ -225,6 +222,7 @@

    Edit Existing Sensors

    + Delete {% endfor %} @@ -239,6 +237,7 @@

    There are no sensors to edit

    Edit Existing Sensor Types

    +
    Warning: deleting sensor types will delete all sensors of that type.



    {% for sensor_type in sensor_types %}
    @@ -289,6 +288,7 @@

    Edit Existing Sensor Types


    + Delete


    {% endfor %}

    diff --git a/mercury/views/sensor.py b/mercury/views/sensor.py index 49560fe7..27fb3de4 100644 --- a/mercury/views/sensor.py +++ b/mercury/views/sensor.py @@ -65,13 +65,14 @@ def delete_sensor(request, sensor_id): def delete_sensor_type(request, type_id): """This deletes a sensor type from the database based on user button click""" - + for sensor in AGSensor.objects.all(): #delete sensors with this type first to avoid foreignkey error + sensor.delete() type_to_delete = AGSensorType.objects.get(id=type_id) type_to_delete.delete() return redirect("/sensor") def update_sensor(request, sensor_id): - """This updates a sensor from the database based on user input""" + """This updates a sensor in the database based on user input""" sensor_to_update = AGSensor.objects.get(id=sensor_id) @@ -103,8 +104,10 @@ def update_sensor(request, sensor_id): def update_sensor_type(request, type_id): + """This updates a sensor type in the database based on user input""" + #Currently causing a strange URL bug, need to debug + type_to_update = AGSensorType.objects.get(id=type_id) - print("\n\n" + str(type_to_update.name) + "NAME BEFORE \n") type_name = request.POST.get("edit-type-name") field_names = request.POST.getlist("edit-field-names") field_types = request.POST.getlist("edit-data-types") @@ -124,7 +127,6 @@ def update_sensor_type(request, type_id): sensors = AGSensor.objects.all() #for when we return context later if valid: type_to_update.name=type_name - print("\n\n" + str(type_to_update.name) + "NAME AFTER \n") type_to_update.processing_formula=0 type_to_update.format=type_format type_to_update.save() From e627e26db2718396493fee3bb334e635539ab9b4 Mon Sep 17 00:00:00 2001 From: dandipietrantonio Date: Sun, 22 Mar 2020 13:23:48 -0400 Subject: [PATCH 13/21] forgot to add migration to git --- mercury/migrations/0012_auto_20200320_1735.py | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 mercury/migrations/0012_auto_20200320_1735.py diff --git a/mercury/migrations/0012_auto_20200320_1735.py b/mercury/migrations/0012_auto_20200320_1735.py new file mode 100644 index 00000000..ca27bbe6 --- /dev/null +++ b/mercury/migrations/0012_auto_20200320_1735.py @@ -0,0 +1,30 @@ +# Generated by Django 2.2.11 on 2020-03-20 17:35 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('mercury', '0011_merge_20200314_0111'), + ] + + operations = [ + migrations.RemoveField( + model_name='agmeasurement', + name='measurement_event', + ), + migrations.RemoveField( + model_name='agmeasurement', + name='measurement_sensor', + ), + migrations.DeleteModel( + name='AGEvent', + ), + migrations.DeleteModel( + name='AGMeasurement', + ), + migrations.DeleteModel( + name='AGSensor', + ), + ] From 6ca01456ac239d11a6e99bb6c8b74db53322c292 Mon Sep 17 00:00:00 2001 From: dandipietrantonio Date: Sun, 22 Mar 2020 17:16:17 -0400 Subject: [PATCH 14/21] Added some tests to sensors view, still needs more --- mercury/templates/sensor.html | 113 ++--- mercury/tests/test_configure_sensors.py | 552 ++++++++++++------------ mercury/views/sensor.py | 3 + 3 files changed, 339 insertions(+), 329 deletions(-) diff --git a/mercury/templates/sensor.html b/mercury/templates/sensor.html index 5e0f2981..024e8041 100644 --- a/mercury/templates/sensor.html +++ b/mercury/templates/sensor.html @@ -236,63 +236,68 @@

    There are no sensors to edit

    -

    Edit Existing Sensor Types

    -
    Warning: deleting sensor types will delete all sensors of that type.
    -


    - {% for sensor_type in sensor_types %} - - {% csrf_token %} -
    -
    - - -

    - - - - - - - - - - - - {% for field_name, unit_and_format in sensor_type.format.items %} - - - - + + {% endfor %} + +
    Field Name Field Data Type Unit
    - +
    + + + + + + + + + + + + {% for field_name, unit_and_format in sensor_type.format.items %} + + + + + + - - - {% endfor %} - -
    Field Name Field Data Type Unit
    + -

    - - Delete -


    - {% endfor %} -
    - +

    + + Delete +


    + {% endfor %} +

    + + {% else %} +

    There are no sensor types to edit

    + + {% endif%}
    diff --git a/mercury/tests/test_configure_sensors.py b/mercury/tests/test_configure_sensors.py index cc02faeb..c1107a6e 100644 --- a/mercury/tests/test_configure_sensors.py +++ b/mercury/tests/test_configure_sensors.py @@ -1,26 +1,41 @@ from django.test import TestCase from django.urls import reverse from mercury.models import EventCodeAccess -from ag_data.models import AGSensor +from ag_data.models import AGSensor, AGSensorType class TestConfigureSensorView(TestCase): TESTCODE = "testcode" - field_name_1 = "field-1" - field_name_2 = "field-2" - test_sensor = { - "name": "Wind Speed Sensor", - field_name_1: {"field_type": "string", "field_unit": "km"}, - field_name_2: {"field_type": "float", "field_unit": "mph"}, - } - def setUp(self): self.login_url = "mercury:EventAccess" self.sensor_url = "mercury:sensor" test_code = EventCodeAccess(event_code="testcode", enabled=True) test_code.save() + # Create test objects to compare to + self.test_type_object_name = "live-feed" + test_type_object = AGSensorType.objects.create( + name = self.test_type_object_name, + processing_formula = 0, + format = { + "test-field-1": { + "data_type": "test-data-type-1", + "unit": "test-unit-1", + }, + "test-field-2": { + "data_type": "test-data-type-2", + "unit": "test-unit-2", + }, + }, + ) + test_type_object.save() + + self.test_sensor = { + "name": "wind speed sensor", + "type_name": self.test_type_object_name, + } + def _get_with_event_code(self, url, event_code): self.client.get(reverse(self.login_url)) self.client.post(reverse(self.login_url), data={"eventcode": event_code}) @@ -45,17 +60,10 @@ def test_ConfigureSensorView_valid_POST_returns_status_ok(self): response = self.client.post( reverse(self.sensor_url), data={ + "submit_new_sensor": "", "sensor-name": self.test_sensor["name"], - "field-name": [self.field_name_1, self.field_name_2], - "field-type": [ - self.test_sensor[self.field_name_1]["field_type"], - self.test_sensor[self.field_name_2]["field_type"], - ], - "field-unit": [ - self.test_sensor[self.field_name_1]["field_unit"], - self.test_sensor[self.field_name_2]["field_unit"], - ], - }, + "select-sensor-type": self.test_sensor["type_name"] + } ) # Check that POST redirects to sensor (same page reloads) @@ -67,269 +75,263 @@ def test_ConfigureSensorView_valid_POST_success_object_created(self): self._get_with_event_code(self.sensor_url, self.TESTCODE) # POST good sensor data - self.client.post( - reverse(self.sensor_url), - data={ - "sensor-name": self.test_sensor["name"], - "field-name": [self.field_name_1, self.field_name_2], - "field-type": [ - self.test_sensor[self.field_name_1]["field_type"], - self.test_sensor[self.field_name_2]["field_type"], - ], - "field-unit": [ - self.test_sensor[self.field_name_1]["field_unit"], - self.test_sensor[self.field_name_2]["field_unit"], - ], - }, - ) - - # Check that AGSensor object is created in db with expected params - sensors = AGSensor.objects.all() - self.assertEqual(sensors.count(), 1) - - # Valid POST creates new AGSensor object with expected parameters - def test_ConfigureSensorView_valid_POST_object_created_with_correct_params(self): - # Login - self._get_with_event_code(self.sensor_url, self.TESTCODE) - - # POST sensor data - self.client.post( - reverse(self.sensor_url), - data={ - "sensor-name": self.test_sensor["name"], - "field-name": [self.field_name_1, self.field_name_2], - "field-type": [ - self.test_sensor[self.field_name_1]["field_type"], - self.test_sensor[self.field_name_2]["field_type"], - ], - "field-unit": [ - self.test_sensor[self.field_name_1]["field_unit"], - self.test_sensor[self.field_name_2]["field_unit"], - ], - }, - ) - - # Check that AGSensor object is created in db with expected values - sensors = AGSensor.objects.all() - sensor = sensors[0] - self.assertEqual(sensor.sensor_name, self.test_sensor["name"]) - self.assertEqual( - sensor.sensor_format[self.field_name_1]["format"], - self.test_sensor[self.field_name_1]["field_type"], - ) - self.assertEqual( - sensor.sensor_format[self.field_name_2]["format"], - self.test_sensor[self.field_name_2]["field_type"], - ) - self.assertEqual( - sensor.sensor_format[self.field_name_1]["unit"], - self.test_sensor[self.field_name_1]["field_unit"], - ) - self.assertEqual( - sensor.sensor_format[self.field_name_2]["unit"], - self.test_sensor[self.field_name_2]["field_unit"], - ) - - # Invalid POST tests - - # Duplicate field names still returns status ok - def test_ConfigureSensorView_invalid_POST_duplicate_fields_returns_status_ok(self): - # Login - self._get_with_event_code(self.sensor_url, self.TESTCODE) - - # POST sensor data response = self.client.post( reverse(self.sensor_url), data={ + "submit_new_sensor": "", "sensor-name": self.test_sensor["name"], - "field-name": [self.field_name_1, self.field_name_1], - "field-type": [ - self.test_sensor[self.field_name_1]["field_type"], - self.test_sensor[self.field_name_2]["field_type"], - ], - "field-unit": [ - self.test_sensor[self.field_name_1]["field_unit"], - self.test_sensor[self.field_name_2]["field_unit"], - ], - }, - ) - - # Check that POST redirects to sensor (same page reloads) - self.assertEqual(200, response.status_code) - - # Duplicate field names - no AGSensor object created - def test_ConfigureSensorView_invalid_POST_field_duplicates_no_object_created(self): - # Login - self._get_with_event_code(self.sensor_url, self.TESTCODE) - - # POST sensor data with duplicate field names - self.client.post( - reverse(self.sensor_url), - data={ - "sensor-name": self.test_sensor["name"], - "field-name": [self.field_name_1, self.field_name_1], - "field-type": [ - self.test_sensor[self.field_name_1]["field_type"], - self.test_sensor[self.field_name_2]["field_type"], - ], - "field-unit": [ - self.test_sensor[self.field_name_1]["field_unit"], - self.test_sensor[self.field_name_2]["field_unit"], - ], - }, - ) - - # Check that AGSensor object is created in db with expected params - sensors = AGSensor.objects.all() - self.assertEqual(sensors.count(), 0) - - # Sensor name missing still returns status OK - def test_ConfigureSensorView_invalid_POST_sensor_name_missing_status_ok(self): - # Login - self._get_with_event_code(self.sensor_url, self.TESTCODE) - - # POST sensor data - response = self.client.post( - reverse(self.sensor_url), - data={ - "sensor-name": "", - "field-name": [self.field_name_1, self.field_name_2], - "field-type": [ - self.test_sensor[self.field_name_1]["field_type"], - self.test_sensor[self.field_name_2]["field_type"], - ], - "field-unit": [ - self.test_sensor[self.field_name_1]["field_unit"], - self.test_sensor[self.field_name_2]["field_unit"], - ], - }, - ) - - # Check that POST redirects to sensor (same page reloads) - self.assertEqual(200, response.status_code) - - # Sensor name missing - no AGSensor object created - def test_ConfigureSensorView_bad_POST_sensor_name_missing_no_object_created(self): - # Login - self._get_with_event_code(self.sensor_url, self.TESTCODE) - - # POST sensor data - self.client.post( - reverse(self.sensor_url), - data={ - "sensor-name": "", - "field-name": [self.field_name_1, self.field_name_1], - "field-type": [ - self.test_sensor[self.field_name_1]["field_type"], - self.test_sensor[self.field_name_2]["field_type"], - ], - "field-unit": [ - self.test_sensor[self.field_name_1]["field_unit"], - self.test_sensor[self.field_name_2]["field_unit"], - ], - }, - ) - - # Check that AGSensor object is created in db with expected params - sensors = AGSensor.objects.all() - self.assertEqual(sensors.count(), 0) - - # Field name missing still returns status OK - def test_ConfigureSensorView_invalid_POST_field_name_missing_status_ok(self): - # Login - self._get_with_event_code(self.sensor_url, self.TESTCODE) - - # POST sensor data - response = self.client.post( - reverse(self.sensor_url), - data={ - "sensor-name": self.test_sensor["name"], - "field-name": [""], - "field-type": [self.test_sensor[self.field_name_1]["field_type"]], - "field-unit": [self.test_sensor[self.field_name_1]["field_unit"]], - }, - ) - - # Check that POST redirects to sensor (same page reloads) - self.assertEqual(200, response.status_code) - - # Field name missing - no AGSensor object created - def test_ConfigureSensorView_bad_POST_field_name_missing_no_object_created(self): - # Login - self._get_with_event_code(self.sensor_url, self.TESTCODE) - - # POST sensor data - self.client.post( - reverse(self.sensor_url), - data={ - "sensor-name": self.test_sensor["name"], - "field-name": [""], - "field-type": [self.test_sensor[self.field_name_1]["field_type"]], - "field-unit": [self.test_sensor[self.field_name_1]["field_unit"]], - }, + "select-sensor-type": self.test_sensor["type_name"] + } ) # Check that AGSensor object is created in db with expected params sensors = AGSensor.objects.all() - self.assertEqual(sensors.count(), 0) - - # Sensor name already in use - still returns status OK - def test_ConfigureSensorView_invalid_POST_sensor_name_taken_status_ok(self): - sensor_format = { - self.field_name_1: { - "unit": self.test_sensor[self.field_name_1]["field_type"], - "format": self.test_sensor[self.field_name_1]["field_unit"], - } - } - - AGSensor.objects.create( - sensor_name=self.test_sensor["name"], sensor_format=sensor_format - ) - - # Login - self._get_with_event_code(self.sensor_url, self.TESTCODE) - - # POST sensor data - response = self.client.post( - reverse(self.sensor_url), - data={ - "sensor-name": self.test_sensor["name"], - "field-name": [""], - "field-type": [self.test_sensor[self.field_name_1]["field_type"]], - "field-unit": [self.test_sensor[self.field_name_1]["field_unit"]], - }, - ) - - # Check that POST redirects to sensor (same page reloads) - self.assertEqual(200, response.status_code) - - # Sensor name already in use - new AGSensor object not created - def test_ConfigureSensorView_invalid_POST_sensor_name_taken_no_object_created(self): - sensor_format = { - self.field_name_1: { - "unit": self.test_sensor[self.field_name_1]["field_type"], - "format": self.test_sensor[self.field_name_1]["field_unit"], - } - } - - AGSensor.objects.create( - sensor_name=self.test_sensor["name"], sensor_format=sensor_format - ) + self.assertEqual(sensors.count(), 1) - # Login - self._get_with_event_code(self.sensor_url, self.TESTCODE) - # POST sensor data - self.client.post( - reverse(self.sensor_url), - data={ - "sensor-name": self.test_sensor["name"], - "field-name": [""], - "field-type": [self.test_sensor[self.field_name_1]["field_type"]], - "field-unit": [self.test_sensor[self.field_name_1]["field_unit"]], - }, - ) - - # Check that additional AGSensor object is not created in db - sensors = AGSensor.objects.all() - self.assertEqual(sensors.count(), 1) + # # Valid POST creates new AGSensor object with expected parameters + # def test_ConfigureSensorView_valid_POST_object_created_with_correct_params(self): + # # Login + # self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # # POST sensor data + # self.client.post( + # reverse(self.sensor_url), + # data={ + # "sensor-name": self.test_sensor["name"], + # "field-name": [self.field_name_1, self.field_name_2], + # "field-type": [ + # self.test_sensor[self.field_name_1]["field_type"], + # self.test_sensor[self.field_name_2]["field_type"], + # ], + # "field-unit": [ + # self.test_sensor[self.field_name_1]["field_unit"], + # self.test_sensor[self.field_name_2]["field_unit"], + # ], + # }, + # ) + + # # Check that AGSensor object is created in db with expected values + # sensors = AGSensor.objects.all() + # sensor = sensors[0] + # self.assertEqual(sensor.sensor_name, self.test_sensor["name"]) + # self.assertEqual( + # sensor.sensor_format[self.field_name_1]["format"], + # self.test_sensor[self.field_name_1]["field_type"], + # ) + # self.assertEqual( + # sensor.sensor_format[self.field_name_2]["format"], + # self.test_sensor[self.field_name_2]["field_type"], + # ) + # self.assertEqual( + # sensor.sensor_format[self.field_name_1]["unit"], + # self.test_sensor[self.field_name_1]["field_unit"], + # ) + # self.assertEqual( + # sensor.sensor_format[self.field_name_2]["unit"], + # self.test_sensor[self.field_name_2]["field_unit"], + # ) + + # # Invalid POST tests + + # # Duplicate field names still returns status ok + # def test_ConfigureSensorView_invalid_POST_duplicate_fields_returns_status_ok(self): + # # Login + # self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # # POST sensor data + # response = self.client.post( + # reverse(self.sensor_url), + # data={ + # "sensor-name": self.test_sensor["name"], + # "field-name": [self.field_name_1, self.field_name_1], + # "field-type": [ + # self.test_sensor[self.field_name_1]["field_type"], + # self.test_sensor[self.field_name_2]["field_type"], + # ], + # "field-unit": [ + # self.test_sensor[self.field_name_1]["field_unit"], + # self.test_sensor[self.field_name_2]["field_unit"], + # ], + # }, + # ) + + # # Check that POST redirects to sensor (same page reloads) + # self.assertEqual(200, response.status_code) + + # # Duplicate field names - no AGSensor object created + # def test_ConfigureSensorView_invalid_POST_field_duplicates_no_object_created(self): + # # Login + # self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # # POST sensor data with duplicate field names + # self.client.post( + # reverse(self.sensor_url), + # data={ + # "sensor-name": self.test_sensor["name"], + # "field-name": [self.field_name_1, self.field_name_1], + # "field-type": [ + # self.test_sensor[self.field_name_1]["field_type"], + # self.test_sensor[self.field_name_2]["field_type"], + # ], + # "field-unit": [ + # self.test_sensor[self.field_name_1]["field_unit"], + # self.test_sensor[self.field_name_2]["field_unit"], + # ], + # }, + # ) + + # # Check that AGSensor object is created in db with expected params + # sensors = AGSensor.objects.all() + # self.assertEqual(sensors.count(), 0) + + # # Sensor name missing still returns status OK + # def test_ConfigureSensorView_invalid_POST_sensor_name_missing_status_ok(self): + # # Login + # self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # # POST sensor data + # response = self.client.post( + # reverse(self.sensor_url), + # data={ + # "sensor-name": "", + # "field-name": [self.field_name_1, self.field_name_2], + # "field-type": [ + # self.test_sensor[self.field_name_1]["field_type"], + # self.test_sensor[self.field_name_2]["field_type"], + # ], + # "field-unit": [ + # self.test_sensor[self.field_name_1]["field_unit"], + # self.test_sensor[self.field_name_2]["field_unit"], + # ], + # }, + # ) + + # # Check that POST redirects to sensor (same page reloads) + # self.assertEqual(200, response.status_code) + + # # Sensor name missing - no AGSensor object created + # def test_ConfigureSensorView_bad_POST_sensor_name_missing_no_object_created(self): + # # Login + # self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # # POST sensor data + # self.client.post( + # reverse(self.sensor_url), + # data={ + # "sensor-name": "", + # "field-name": [self.field_name_1, self.field_name_1], + # "field-type": [ + # self.test_sensor[self.field_name_1]["field_type"], + # self.test_sensor[self.field_name_2]["field_type"], + # ], + # "field-unit": [ + # self.test_sensor[self.field_name_1]["field_unit"], + # self.test_sensor[self.field_name_2]["field_unit"], + # ], + # }, + # ) + + # # Check that AGSensor object is created in db with expected params + # sensors = AGSensor.objects.all() + # self.assertEqual(sensors.count(), 0) + + # # Field name missing still returns status OK + # def test_ConfigureSensorView_invalid_POST_field_name_missing_status_ok(self): + # # Login + # self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # # POST sensor data + # response = self.client.post( + # reverse(self.sensor_url), + # data={ + # "sensor-name": self.test_sensor["name"], + # "field-name": [""], + # "field-type": [self.test_sensor[self.field_name_1]["field_type"]], + # "field-unit": [self.test_sensor[self.field_name_1]["field_unit"]], + # }, + # ) + + # # Check that POST redirects to sensor (same page reloads) + # self.assertEqual(200, response.status_code) + + # # Field name missing - no AGSensor object created + # def test_ConfigureSensorView_bad_POST_field_name_missing_no_object_created(self): + # # Login + # self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # # POST sensor data + # self.client.post( + # reverse(self.sensor_url), + # data={ + # "sensor-name": self.test_sensor["name"], + # "field-name": [""], + # "field-type": [self.test_sensor[self.field_name_1]["field_type"]], + # "field-unit": [self.test_sensor[self.field_name_1]["field_unit"]], + # }, + # ) + + # # Check that AGSensor object is created in db with expected params + # sensors = AGSensor.objects.all() + # self.assertEqual(sensors.count(), 0) + + # # Sensor name already in use - still returns status OK + # def test_ConfigureSensorView_invalid_POST_sensor_name_taken_status_ok(self): + # sensor_format = { + # self.field_name_1: { + # "unit": self.test_sensor[self.field_name_1]["field_type"], + # "format": self.test_sensor[self.field_name_1]["field_unit"], + # } + # } + + # AGSensor.objects.create( + # sensor_name=self.test_sensor["name"], sensor_format=sensor_format + # ) + + # # Login + # self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # # POST sensor data + # response = self.client.post( + # reverse(self.sensor_url), + # data={ + # "sensor-name": self.test_sensor["name"], + # "field-name": [""], + # "field-type": [self.test_sensor[self.field_name_1]["field_type"]], + # "field-unit": [self.test_sensor[self.field_name_1]["field_unit"]], + # }, + # ) + + # # Check that POST redirects to sensor (same page reloads) + # self.assertEqual(200, response.status_code) + + # # Sensor name already in use - new AGSensor object not created + # def test_ConfigureSensorView_invalid_POST_sensor_name_taken_no_object_created(self): + # sensor_format = { + # self.field_name_1: { + # "unit": self.test_sensor[self.field_name_1]["field_type"], + # "format": self.test_sensor[self.field_name_1]["field_unit"], + # } + # } + + # AGSensor.objects.create( + # sensor_name=self.test_sensor["name"], sensor_format=sensor_format + # ) + + # # Login + # self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # # POST sensor data + # self.client.post( + # reverse(self.sensor_url), + # data={ + # "sensor-name": self.test_sensor["name"], + # "field-name": [""], + # "field-type": [self.test_sensor[self.field_name_1]["field_type"]], + # "field-unit": [self.test_sensor[self.field_name_1]["field_unit"]], + # }, + # ) + + # # Check that additional AGSensor object is not created in db + # sensors = AGSensor.objects.all() + # self.assertEqual(sensors.count(), 1) diff --git a/mercury/views/sensor.py b/mercury/views/sensor.py index 27fb3de4..51b65b50 100644 --- a/mercury/views/sensor.py +++ b/mercury/views/sensor.py @@ -201,8 +201,11 @@ def post(self, request, *args, **kwargs): elif ("submit_new_sensor" in request.POST): sensor_name = request.POST.get("sensor-name") + print("\n\n" + str(sensor_name) + "\n") sensor_type = request.POST.get("select-sensor-type") + print("\n\n" + str(sensor_type) + "\n") sensor_type = AGSensorType.objects.get(name=sensor_type) #str --> AGSensorType + print("\n\n" + str(sensor_type) + "\n") # reformat then validate name to avoid duplicated names or bad inputs like " " sensor_name = sensor_name.strip().lower() # remove excess whitespace and CAPS From 3f2104ede9e4d89c533955587812459a69cad6d8 Mon Sep 17 00:00:00 2001 From: dandipietrantonio Date: Mon, 23 Mar 2020 15:20:37 -0400 Subject: [PATCH 15/21] Added tests to sensor view --- mercury/tests/test_configure_sensors.py | 614 ++++++++++++++---------- mercury/views/sensor.py | 37 +- 2 files changed, 380 insertions(+), 271 deletions(-) diff --git a/mercury/tests/test_configure_sensors.py b/mercury/tests/test_configure_sensors.py index c1107a6e..0d69a3fa 100644 --- a/mercury/tests/test_configure_sensors.py +++ b/mercury/tests/test_configure_sensors.py @@ -14,16 +14,18 @@ def setUp(self): test_code.save() # Create test objects to compare to + self.field_name_1 = "test-field-1" + self.field_name_2 = "test-field-2" self.test_type_object_name = "live-feed" test_type_object = AGSensorType.objects.create( name = self.test_type_object_name, processing_formula = 0, format = { - "test-field-1": { + self.field_name_1: { "data_type": "test-data-type-1", "unit": "test-unit-1", }, - "test-field-2": { + self.field_name_2: { "data_type": "test-data-type-2", "unit": "test-unit-2", }, @@ -33,7 +35,15 @@ def setUp(self): self.test_sensor = { "name": "wind speed sensor", - "type_name": self.test_type_object_name, + "type_id": self.test_type_object_name, + } + + self.test_sensor_type = { + "type-name": "fuel level", + "processing formula": 0, + "field-names": ["test-field-1","test-field-2"], + "data-types": ["test-data-type-1", "test-data-type-2"], + "units": ["test-unit-1", "test-unit-2"], } def _get_with_event_code(self, url, event_code): @@ -51,8 +61,8 @@ def test_ConfigureSensorView_GET_success(self): # Valid POST tests - # Valid POST returns status OK - def test_ConfigureSensorView_valid_POST_returns_status_ok(self): + # Valid POST to create sensor returns status OK + def test_ConfigureSensorView_valid_POST_sensor_returns_status_ok(self): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -62,7 +72,7 @@ def test_ConfigureSensorView_valid_POST_returns_status_ok(self): data={ "submit_new_sensor": "", "sensor-name": self.test_sensor["name"], - "select-sensor-type": self.test_sensor["type_name"] + "select-sensor-type": self.test_sensor["type_id"] } ) @@ -70,7 +80,7 @@ def test_ConfigureSensorView_valid_POST_returns_status_ok(self): self.assertEqual(200, response.status_code) # Valid POST creates new AGSensor object - def test_ConfigureSensorView_valid_POST_success_object_created(self): + def test_ConfigureSensorView_valid_POST_sensor_success_object_created(self): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -80,7 +90,7 @@ def test_ConfigureSensorView_valid_POST_success_object_created(self): data={ "submit_new_sensor": "", "sensor-name": self.test_sensor["name"], - "select-sensor-type": self.test_sensor["type_name"] + "select-sensor-type": self.test_sensor["type_id"] } ) @@ -88,250 +98,352 @@ def test_ConfigureSensorView_valid_POST_success_object_created(self): sensors = AGSensor.objects.all() self.assertEqual(sensors.count(), 1) + # Valid POST creates new AGSensor object with expected parameters + def test_ConfigureSensorView_valid_POST_sensor_object_created_with_correct_params(self): + # Login + self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # POST sensor data + self.client.post( + reverse(self.sensor_url), + data={ + "submit_new_sensor": "", + "sensor-name": self.test_sensor["name"], + "select-sensor-type": self.test_sensor["type_id"] + } + ) + + # Check that AGSensor object is created in db with expected values + sensors = AGSensor.objects.all() + sensor = sensors[0] + self.assertEqual(sensor.name, self.test_sensor["name"]) + self.assertEqual(sensor.type_id.name, self.test_sensor["type_id"]) + + # Valid POST to create AGSensorType returns status OK + def test_ConfigureSensorView_valid_POST_sensor_type_returns_status_ok(self): + # Login + self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # POST sensor type data + response = self.client.post( + reverse(self.sensor_url), + data={ + "submit_new_type": "", + "type-name": self.test_sensor_type["type-name"], + "field-names": self.test_sensor_type["field-names"], + "data-types": self.test_sensor_type["data-types"], + "units": self.test_sensor_type["units"] + } + ) + + # Check that POST redirects to sensor (same page reloads) + self.assertEqual(200, response.status_code) + + # Valid POST creates new AGSensorType object + def test_ConfigureSensorView_valid_POST_sensor_type_success_object_created(self): + # Login + self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # POST good sensor type data + response = self.client.post( + reverse(self.sensor_url), + data={ + "submit_new_type": "", + "type-name": self.test_sensor_type["type-name"], + "field-names": self.test_sensor_type["field-names"], + "data-types": self.test_sensor_type["data-types"], + "units": self.test_sensor_type["units"] + } + ) + + # Check that AGSensor object is created in db with expected params + sensor_types = AGSensorType.objects.all() + self.assertEqual(sensor_types.count(), 2) #not 1 since we created a sensor_type in the setUp() function + + def test_ConfigureSensorView_valid_POST_sensor_type_object_created_with_correct_params(self): + # Login + self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # POST sensor data + self.client.post( + reverse(self.sensor_url), + data={ + "submit_new_type": "", + "type-name": self.test_sensor_type["type-name"], + "field-names": self.test_sensor_type["field-names"], + "data-types": self.test_sensor_type["data-types"], + "units": self.test_sensor_type["units"] + } + ) + + # Check that AGSensor object is created in db with expected values + sensor_types = AGSensorType.objects.all() + sensor_type = sensor_types[1] + self.assertEqual(sensor_type.name, self.test_sensor_type["type-name"]) + self.assertTrue(self.test_sensor_type["field-names"][0] in sensor_type.format) + self.assertTrue(self.test_sensor_type["field-names"][1] in sensor_type.format) + self.assertEqual( + sensor_type.format[self.field_name_1]["data_type"], + self.test_sensor_type["data-types"][0], + ) + self.assertEqual( + sensor_type.format[self.field_name_2]["data_type"], + self.test_sensor_type["data-types"][1], + ) + self.assertEqual( + sensor_type.format[self.field_name_1]["unit"], + self.test_sensor_type["units"][0], + ) + self.assertEqual( + sensor_type.format[self.field_name_2]["unit"], + self.test_sensor_type["units"][1], + ) - # # Valid POST creates new AGSensor object with expected parameters - # def test_ConfigureSensorView_valid_POST_object_created_with_correct_params(self): - # # Login - # self._get_with_event_code(self.sensor_url, self.TESTCODE) - - # # POST sensor data - # self.client.post( - # reverse(self.sensor_url), - # data={ - # "sensor-name": self.test_sensor["name"], - # "field-name": [self.field_name_1, self.field_name_2], - # "field-type": [ - # self.test_sensor[self.field_name_1]["field_type"], - # self.test_sensor[self.field_name_2]["field_type"], - # ], - # "field-unit": [ - # self.test_sensor[self.field_name_1]["field_unit"], - # self.test_sensor[self.field_name_2]["field_unit"], - # ], - # }, - # ) - - # # Check that AGSensor object is created in db with expected values - # sensors = AGSensor.objects.all() - # sensor = sensors[0] - # self.assertEqual(sensor.sensor_name, self.test_sensor["name"]) - # self.assertEqual( - # sensor.sensor_format[self.field_name_1]["format"], - # self.test_sensor[self.field_name_1]["field_type"], - # ) - # self.assertEqual( - # sensor.sensor_format[self.field_name_2]["format"], - # self.test_sensor[self.field_name_2]["field_type"], - # ) - # self.assertEqual( - # sensor.sensor_format[self.field_name_1]["unit"], - # self.test_sensor[self.field_name_1]["field_unit"], - # ) - # self.assertEqual( - # sensor.sensor_format[self.field_name_2]["unit"], - # self.test_sensor[self.field_name_2]["field_unit"], - # ) # # Invalid POST tests - # # Duplicate field names still returns status ok - # def test_ConfigureSensorView_invalid_POST_duplicate_fields_returns_status_ok(self): - # # Login - # self._get_with_event_code(self.sensor_url, self.TESTCODE) - - # # POST sensor data - # response = self.client.post( - # reverse(self.sensor_url), - # data={ - # "sensor-name": self.test_sensor["name"], - # "field-name": [self.field_name_1, self.field_name_1], - # "field-type": [ - # self.test_sensor[self.field_name_1]["field_type"], - # self.test_sensor[self.field_name_2]["field_type"], - # ], - # "field-unit": [ - # self.test_sensor[self.field_name_1]["field_unit"], - # self.test_sensor[self.field_name_2]["field_unit"], - # ], - # }, - # ) - - # # Check that POST redirects to sensor (same page reloads) - # self.assertEqual(200, response.status_code) - - # # Duplicate field names - no AGSensor object created - # def test_ConfigureSensorView_invalid_POST_field_duplicates_no_object_created(self): - # # Login - # self._get_with_event_code(self.sensor_url, self.TESTCODE) - - # # POST sensor data with duplicate field names - # self.client.post( - # reverse(self.sensor_url), - # data={ - # "sensor-name": self.test_sensor["name"], - # "field-name": [self.field_name_1, self.field_name_1], - # "field-type": [ - # self.test_sensor[self.field_name_1]["field_type"], - # self.test_sensor[self.field_name_2]["field_type"], - # ], - # "field-unit": [ - # self.test_sensor[self.field_name_1]["field_unit"], - # self.test_sensor[self.field_name_2]["field_unit"], - # ], - # }, - # ) - - # # Check that AGSensor object is created in db with expected params - # sensors = AGSensor.objects.all() - # self.assertEqual(sensors.count(), 0) - - # # Sensor name missing still returns status OK - # def test_ConfigureSensorView_invalid_POST_sensor_name_missing_status_ok(self): - # # Login - # self._get_with_event_code(self.sensor_url, self.TESTCODE) - - # # POST sensor data - # response = self.client.post( - # reverse(self.sensor_url), - # data={ - # "sensor-name": "", - # "field-name": [self.field_name_1, self.field_name_2], - # "field-type": [ - # self.test_sensor[self.field_name_1]["field_type"], - # self.test_sensor[self.field_name_2]["field_type"], - # ], - # "field-unit": [ - # self.test_sensor[self.field_name_1]["field_unit"], - # self.test_sensor[self.field_name_2]["field_unit"], - # ], - # }, - # ) - - # # Check that POST redirects to sensor (same page reloads) - # self.assertEqual(200, response.status_code) - - # # Sensor name missing - no AGSensor object created - # def test_ConfigureSensorView_bad_POST_sensor_name_missing_no_object_created(self): - # # Login - # self._get_with_event_code(self.sensor_url, self.TESTCODE) - - # # POST sensor data - # self.client.post( - # reverse(self.sensor_url), - # data={ - # "sensor-name": "", - # "field-name": [self.field_name_1, self.field_name_1], - # "field-type": [ - # self.test_sensor[self.field_name_1]["field_type"], - # self.test_sensor[self.field_name_2]["field_type"], - # ], - # "field-unit": [ - # self.test_sensor[self.field_name_1]["field_unit"], - # self.test_sensor[self.field_name_2]["field_unit"], - # ], - # }, - # ) - - # # Check that AGSensor object is created in db with expected params - # sensors = AGSensor.objects.all() - # self.assertEqual(sensors.count(), 0) - - # # Field name missing still returns status OK - # def test_ConfigureSensorView_invalid_POST_field_name_missing_status_ok(self): - # # Login - # self._get_with_event_code(self.sensor_url, self.TESTCODE) - - # # POST sensor data - # response = self.client.post( - # reverse(self.sensor_url), - # data={ - # "sensor-name": self.test_sensor["name"], - # "field-name": [""], - # "field-type": [self.test_sensor[self.field_name_1]["field_type"]], - # "field-unit": [self.test_sensor[self.field_name_1]["field_unit"]], - # }, - # ) - - # # Check that POST redirects to sensor (same page reloads) - # self.assertEqual(200, response.status_code) - - # # Field name missing - no AGSensor object created - # def test_ConfigureSensorView_bad_POST_field_name_missing_no_object_created(self): - # # Login - # self._get_with_event_code(self.sensor_url, self.TESTCODE) - - # # POST sensor data - # self.client.post( - # reverse(self.sensor_url), - # data={ - # "sensor-name": self.test_sensor["name"], - # "field-name": [""], - # "field-type": [self.test_sensor[self.field_name_1]["field_type"]], - # "field-unit": [self.test_sensor[self.field_name_1]["field_unit"]], - # }, - # ) - - # # Check that AGSensor object is created in db with expected params - # sensors = AGSensor.objects.all() - # self.assertEqual(sensors.count(), 0) - - # # Sensor name already in use - still returns status OK - # def test_ConfigureSensorView_invalid_POST_sensor_name_taken_status_ok(self): - # sensor_format = { - # self.field_name_1: { - # "unit": self.test_sensor[self.field_name_1]["field_type"], - # "format": self.test_sensor[self.field_name_1]["field_unit"], - # } - # } - - # AGSensor.objects.create( - # sensor_name=self.test_sensor["name"], sensor_format=sensor_format - # ) - - # # Login - # self._get_with_event_code(self.sensor_url, self.TESTCODE) - - # # POST sensor data - # response = self.client.post( - # reverse(self.sensor_url), - # data={ - # "sensor-name": self.test_sensor["name"], - # "field-name": [""], - # "field-type": [self.test_sensor[self.field_name_1]["field_type"]], - # "field-unit": [self.test_sensor[self.field_name_1]["field_unit"]], - # }, - # ) - - # # Check that POST redirects to sensor (same page reloads) - # self.assertEqual(200, response.status_code) - - # # Sensor name already in use - new AGSensor object not created - # def test_ConfigureSensorView_invalid_POST_sensor_name_taken_no_object_created(self): - # sensor_format = { - # self.field_name_1: { - # "unit": self.test_sensor[self.field_name_1]["field_type"], - # "format": self.test_sensor[self.field_name_1]["field_unit"], - # } - # } - - # AGSensor.objects.create( - # sensor_name=self.test_sensor["name"], sensor_format=sensor_format - # ) - - # # Login - # self._get_with_event_code(self.sensor_url, self.TESTCODE) - - # # POST sensor data - # self.client.post( - # reverse(self.sensor_url), - # data={ - # "sensor-name": self.test_sensor["name"], - # "field-name": [""], - # "field-type": [self.test_sensor[self.field_name_1]["field_type"]], - # "field-unit": [self.test_sensor[self.field_name_1]["field_unit"]], - # }, - # ) - - # # Check that additional AGSensor object is not created in db - # sensors = AGSensor.objects.all() - # self.assertEqual(sensors.count(), 1) + # Duplicate field names still returns status ok + def test_ConfigureSensorView_invalid_POST_sensor_no_name_returns_status_ok(self): + # Login + self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # POST sensor data + response = self.client.post( + reverse(self.sensor_url), + data={ + "submit_new_sensor": "", + "sensor-name": "", + "select-sensor-type": self.test_sensor["type_id"] + } + ) + + # Check that POST redirects to sensor (same page reloads) + self.assertEqual(200, response.status_code) + + # Duplicate field names - no AGSensor object created + def test_ConfigureSensorView_invalid_POST_sensor_no_name_no_object_created(self): + # Login + self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # POST sensor data with duplicate field names + self.client.post( + reverse(self.sensor_url), + data={ + "submit_new_sensor": "", + "sensor-name": "", + "select-sensor-type": self.test_sensor["type_id"] + } + ) + + # Check that AGSensor object is created in db with expected params + sensors = AGSensor.objects.all() + self.assertEqual(sensors.count(), 0) + + # Sensor name already in use - still returns status OK + def test_ConfigureSensorView_invalid_POST_sensor_name_taken_status_ok(self): + AGSensor.objects.create( + name=self.test_sensor["name"], type_id=AGSensorType.objects.get(name=self.test_type_object_name) + ) + + # Login + self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # POST sensor data + response = self.client.post( + reverse(self.sensor_url), + data={ + "submit_new_sensor": "", + "sensor-name": self.test_sensor["name"], + "select-sensor-type": self.test_sensor["type_id"] + } + ) + + # Check that POST redirects to sensor (same page reloads) + self.assertEqual(200, response.status_code) + + # Sensor name already in use - new AGSensor object not created + def test_ConfigureSensorView_invalid_POST_sensor_name_taken_no_object_created(self): + AGSensor.objects.create( + name=self.test_sensor["name"], type_id=AGSensorType.objects.get(name=self.test_type_object_name) + ) + + # Login + self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # POST sensor data + response = self.client.post( + reverse(self.sensor_url), + data={ + "submit_new_sensor": "", + "sensor-name": self.test_sensor["name"], + "select-sensor-type": self.test_sensor["type_id"] + } + ) + + # Check that additional AGSensor object is not created in db + sensors = AGSensor.objects.all() + self.assertEqual(sensors.count(), 1) + + # Sensor type name missing still returns status OK + def test_ConfigureSensorView_invalid_POST_sensor_type_name_missing_status_ok(self): + # Login + self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # POST sensor data + response = self.client.post( + reverse(self.sensor_url), + data={ + "submit_new_type": "", + "type-name": "", + "field-names": self.test_sensor_type["field-names"], + "data-types": self.test_sensor_type["data-types"], + "units": self.test_sensor_type["units"] + } + ) + + # Check that POST redirects to sensor (same page reloads) + self.assertEqual(200, response.status_code) + + # Sensor type name missing - no AGSensorType object created + def test_ConfigureSensorView_bad_POST_sensor_type_name_missing_no_object_created(self): + # Login + self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # POST sensor data + self.client.post( + reverse(self.sensor_url), + data={ + "submit_new_type": "", + "type-name": "", + "field-names": self.test_sensor_type["field-names"], + "data-types": self.test_sensor_type["data-types"], + "units": self.test_sensor_type["units"] + } + ) + + # Check that AGSensor object is created in db with expected params + sensors = AGSensor.objects.all() + self.assertEqual(sensors.count(), 0) + + # Field name missing still returns status OK + def test_ConfigureSensorView_invalid_POST_sensor_type_field_name_missing_status_ok(self): + # Login + self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # POST sensor data + response = self.client.post( + reverse(self.sensor_url), + data={ + "submit_new_type": "", + "type-name": self.test_sensor_type["type-name"], + "field-names": [self.field_name_1], + "data-types": self.test_sensor_type["data-types"], + "units": self.test_sensor_type["units"] + } + ) + + # Check that POST redirects to sensor (same page reloads) + self.assertEqual(200, response.status_code) + + # Field name missing - no AGSensorType object created + def test_ConfigureSensorView_bad_POST_sensor_type_field_name_missing_no_object_created(self): + # Login + self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # POST sensor data + self.client.post( + reverse(self.sensor_url), + data={ + "submit_new_type": "", + "type-name": self.test_sensor_type["type-name"], + "field-names": [self.field_name_1], + "data-types": self.test_sensor_type["data-types"], + "units": self.test_sensor_type["units"] + } + ) + + # Check that AGSensor object is created in db with expected params + sensors = AGSensor.objects.all() + self.assertEqual(sensors.count(), 0) + + # AGSensorType name taken returns status OK + def test_ConfigureSensorView_invalid_POST_sensor_type_field_name_missing_status_ok(self): + # Login + self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # POST sensor data + response = self.client.post( + reverse(self.sensor_url), + data={ + "submit_new_type": "", + "type-name": self.test_type_object_name, #AGSensorType created in setUp() + "field-names": self.test_sensor_type["field-names"], + "data-types": self.test_sensor_type["data-types"], + "units": self.test_sensor_type["units"] + } + ) + + # Check that POST redirects to sensor (same page reloads) + self.assertEqual(200, response.status_code) + + # AGSensorType name taken - no AGSensorType object created + def test_ConfigureSensorView_bad_POST_sensor_type_field_name_missing_no_object_created(self): + # Login + self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # POST sensor data + self.client.post( + reverse(self.sensor_url), + data={ + "submit_new_type": "", + "type-name": self.test_type_object_name, #AGSensorType created in setUp() + "field-names": self.test_sensor_type["field-names"], + "data-types": self.test_sensor_type["data-types"], + "units": self.test_sensor_type["units"] + } + ) + + # Check that AGSensor object is created in db with expected params + sensors = AGSensor.objects.all() + self.assertEqual(sensors.count(), 0) + + # AGSensorType duplicated field name returns status OK + def test_ConfigureSensorView_invalid_POST_sensor_type_field_name_missing_status_ok(self): + # Login + self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # POST sensor data + response = self.client.post( + reverse(self.sensor_url), + data={ + "submit_new_type": "", + "type-name": self.test_sensor_type["type-name"], + "field-names": [self.field_name_1, self.field_name_1], + "data-types": self.test_sensor_type["data-types"], + "units": self.test_sensor_type["units"] + } + ) + + # Check that POST redirects to sensor (same page reloads) + self.assertEqual(200, response.status_code) + + # AGSensorType duplicated field name - no AGSensorType object created + def test_ConfigureSensorView_bad_POST_sensor_type_field_name_missing_no_object_created(self): + # Login + self._get_with_event_code(self.sensor_url, self.TESTCODE) + + # POST sensor data + self.client.post( + reverse(self.sensor_url), + data={ + "submit_new_type": "", + "type-name": self.test_sensor_type["type-name"], + "field-names": [self.field_name_1, self.field_name_1], + "data-types": self.test_sensor_type["data-types"], + "units": self.test_sensor_type["units"] + } + ) + + # Check that AGSensor object is created in db with expected params + sensors = AGSensor.objects.all() + self.assertEqual(sensors.count(), 0) diff --git a/mercury/views/sensor.py b/mercury/views/sensor.py index 51b65b50..599d2791 100644 --- a/mercury/views/sensor.py +++ b/mercury/views/sensor.py @@ -11,6 +11,23 @@ log.setLevel(logging.ERROR) +def validate_add_sensor_inputs(sensor_name, request): + """This validates the form before a user submits a new sensor to prevent bad inputs""" + + form_valid = True + + # no sensor name + if not sensor_name: + messages.error(request, "Sensor name is missing or invalid.") + form_valid = False + + # duplicated sensor name + if AGSensor.objects.filter(name=sensor_name).count() > 0: + messages.error(request, "Sensor name is already taken.") + form_valid = False + + return form_valid, request + def validate_add_sensor_type_inputs(type_name, field_name_list, request): """This validates the form before a user submits a new sensor type to prevent bad inputs""" @@ -39,23 +56,6 @@ def validate_add_sensor_type_inputs(type_name, field_name_list, request): return form_valid, request -def validate_add_sensor_inputs(sensor_name, request): - """This validates the form before a user submits a new sensor to prevent bad inputs""" - - form_valid = True - - # no sensor name - if not sensor_name: - messages.error(request, "Sensor name is missing or invalid.") - form_valid = False - - # duplicated sensor name - if AGSensor.objects.filter(name=sensor_name).count() > 0: - messages.error(request, "Sensor name is already taken.") - form_valid = False - - return form_valid, request - def delete_sensor(request, sensor_id): """This deletes a sensor from the database based on user button click""" @@ -201,11 +201,8 @@ def post(self, request, *args, **kwargs): elif ("submit_new_sensor" in request.POST): sensor_name = request.POST.get("sensor-name") - print("\n\n" + str(sensor_name) + "\n") sensor_type = request.POST.get("select-sensor-type") - print("\n\n" + str(sensor_type) + "\n") sensor_type = AGSensorType.objects.get(name=sensor_type) #str --> AGSensorType - print("\n\n" + str(sensor_type) + "\n") # reformat then validate name to avoid duplicated names or bad inputs like " " sensor_name = sensor_name.strip().lower() # remove excess whitespace and CAPS From 6ec0af61590fed1601d5cde2698f9a4989340c82 Mon Sep 17 00:00:00 2001 From: Daisy Crego Date: Mon, 23 Mar 2020 15:20:41 -0400 Subject: [PATCH 16/21] Modify GF config post view to create a dashboard and datasource each time a new API token/data source combo is added. No error handling yet. Modify add sensor view to create a new grafana panel with the new sensor model each time a new sensor is saved. --- mercury/views/gf_config.py | 13 +++++++++++++ mercury/views/sensor.py | 14 ++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/mercury/views/gf_config.py b/mercury/views/gf_config.py index 7261708c..edc41f7e 100644 --- a/mercury/views/gf_config.py +++ b/mercury/views/gf_config.py @@ -4,6 +4,7 @@ from django.views.generic import TemplateView from mercury.forms import GFConfigForm from mercury.models import GFConfig +from mercury.grafanaAPI.grafana_api import Grafana log = logging.getLogger(__name__) log.setLevel(logging.ERROR) @@ -39,6 +40,18 @@ def post(self, request, *args, **kwargs): ) config_data.save() + grafana = Grafana(config_data.gf_host, config_data.gf_token) + dashboard = grafana.create_dashboard() + if dashboard: + config_data.gf_dashboard_uid = dashboard["uid"] + config_data.save() + else: + # log an error that dashboard couldn't be created using these + # credentials, check API token and hostname + pass + + grafana.create_postgres_datasource() + configs = GFConfig.objects.all().order_by("id") config_form = GFConfigForm() context = {"config_form": config_form, "configs": configs} diff --git a/mercury/views/sensor.py b/mercury/views/sensor.py index 51b65b50..7609d8f9 100644 --- a/mercury/views/sensor.py +++ b/mercury/views/sensor.py @@ -2,10 +2,10 @@ from django.shortcuts import render, redirect from django.views.generic import TemplateView from ..event_check import require_event_code - from ag_data.models import AGSensor, AGSensorType - +from mercury.models import GFConfig from django.contrib import messages +from mercury.grafanaAPI.grafana_api import Grafana log = logging.getLogger(__name__) log.setLevel(logging.ERROR) @@ -215,6 +215,16 @@ def post(self, request, *args, **kwargs): if valid: new_sensor = AGSensor.objects.create(name=sensor_name, type_id=sensor_type) new_sensor.save() + + gf_configs = GFConfig.objects.all() + if len(gf_configs) > 0: + gf_config = gf_configs[0] + grafana = Grafana(gf_config.gf_host, gf_config.gf_token) + grafana.add_panel(new_sensor, gf_config.gf_dashboard_uid) + # error - no gf_config available, please do that first + # or silently fail + pass + sensors = AGSensor.objects.all() context = { "sensors": sensors, From e986fb4d9eeafb030402dbb07864d537e3885c12 Mon Sep 17 00:00:00 2001 From: dandipietrantonio Date: Mon, 23 Mar 2020 15:32:17 -0400 Subject: [PATCH 17/21] Fixed formatting for tests --- mercury/tests/test_configure_sensors.py | 153 ++++++++++++++---------- mercury/views/sensor.py | 68 +++++++---- 2 files changed, 131 insertions(+), 90 deletions(-) diff --git a/mercury/tests/test_configure_sensors.py b/mercury/tests/test_configure_sensors.py index 0d69a3fa..24efd842 100644 --- a/mercury/tests/test_configure_sensors.py +++ b/mercury/tests/test_configure_sensors.py @@ -18,9 +18,9 @@ def setUp(self): self.field_name_2 = "test-field-2" self.test_type_object_name = "live-feed" test_type_object = AGSensorType.objects.create( - name = self.test_type_object_name, - processing_formula = 0, - format = { + name=self.test_type_object_name, + processing_formula=0, + format={ self.field_name_1: { "data_type": "test-data-type-1", "unit": "test-unit-1", @@ -30,7 +30,7 @@ def setUp(self): "unit": "test-unit-2", }, }, - ) + ) test_type_object.save() self.test_sensor = { @@ -41,7 +41,7 @@ def setUp(self): self.test_sensor_type = { "type-name": "fuel level", "processing formula": 0, - "field-names": ["test-field-1","test-field-2"], + "field-names": ["test-field-1", "test-field-2"], "data-types": ["test-data-type-1", "test-data-type-2"], "units": ["test-unit-1", "test-unit-2"], } @@ -70,10 +70,10 @@ def test_ConfigureSensorView_valid_POST_sensor_returns_status_ok(self): response = self.client.post( reverse(self.sensor_url), data={ - "submit_new_sensor": "", + "submit_new_sensor": "", "sensor-name": self.test_sensor["name"], - "select-sensor-type": self.test_sensor["type_id"] - } + "select-sensor-type": self.test_sensor["type_id"], + }, ) # Check that POST redirects to sensor (same page reloads) @@ -85,13 +85,13 @@ def test_ConfigureSensorView_valid_POST_sensor_success_object_created(self): self._get_with_event_code(self.sensor_url, self.TESTCODE) # POST good sensor data - response = self.client.post( + self.client.post( reverse(self.sensor_url), data={ - "submit_new_sensor": "", + "submit_new_sensor": "", "sensor-name": self.test_sensor["name"], - "select-sensor-type": self.test_sensor["type_id"] - } + "select-sensor-type": self.test_sensor["type_id"], + }, ) # Check that AGSensor object is created in db with expected params @@ -99,7 +99,9 @@ def test_ConfigureSensorView_valid_POST_sensor_success_object_created(self): self.assertEqual(sensors.count(), 1) # Valid POST creates new AGSensor object with expected parameters - def test_ConfigureSensorView_valid_POST_sensor_object_created_with_correct_params(self): + def test_ConfigureSensorView_valid_POST_sensor_object_created_with_correct_params( + self, + ): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -107,10 +109,10 @@ def test_ConfigureSensorView_valid_POST_sensor_object_created_with_correct_param self.client.post( reverse(self.sensor_url), data={ - "submit_new_sensor": "", + "submit_new_sensor": "", "sensor-name": self.test_sensor["name"], - "select-sensor-type": self.test_sensor["type_id"] - } + "select-sensor-type": self.test_sensor["type_id"], + }, ) # Check that AGSensor object is created in db with expected values @@ -132,8 +134,8 @@ def test_ConfigureSensorView_valid_POST_sensor_type_returns_status_ok(self): "type-name": self.test_sensor_type["type-name"], "field-names": self.test_sensor_type["field-names"], "data-types": self.test_sensor_type["data-types"], - "units": self.test_sensor_type["units"] - } + "units": self.test_sensor_type["units"], + }, ) # Check that POST redirects to sensor (same page reloads) @@ -145,22 +147,26 @@ def test_ConfigureSensorView_valid_POST_sensor_type_success_object_created(self) self._get_with_event_code(self.sensor_url, self.TESTCODE) # POST good sensor type data - response = self.client.post( + self.client.post( reverse(self.sensor_url), data={ "submit_new_type": "", "type-name": self.test_sensor_type["type-name"], "field-names": self.test_sensor_type["field-names"], "data-types": self.test_sensor_type["data-types"], - "units": self.test_sensor_type["units"] - } + "units": self.test_sensor_type["units"], + }, ) # Check that AGSensor object is created in db with expected params sensor_types = AGSensorType.objects.all() - self.assertEqual(sensor_types.count(), 2) #not 1 since we created a sensor_type in the setUp() function + self.assertEqual( + sensor_types.count(), 2 + ) # not 1 since we created a sensor_type in the setUp() function - def test_ConfigureSensorView_valid_POST_sensor_type_object_created_with_correct_params(self): + def test_ConfigureSensorView_valid_POST_sensor_type_object_created_with_correct_params( + self, + ): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -172,8 +178,8 @@ def test_ConfigureSensorView_valid_POST_sensor_type_object_created_with_correct_ "type-name": self.test_sensor_type["type-name"], "field-names": self.test_sensor_type["field-names"], "data-types": self.test_sensor_type["data-types"], - "units": self.test_sensor_type["units"] - } + "units": self.test_sensor_type["units"], + }, ) # Check that AGSensor object is created in db with expected values @@ -199,7 +205,6 @@ def test_ConfigureSensorView_valid_POST_sensor_type_object_created_with_correct_ self.test_sensor_type["units"][1], ) - # # Invalid POST tests # Duplicate field names still returns status ok @@ -211,10 +216,10 @@ def test_ConfigureSensorView_invalid_POST_sensor_no_name_returns_status_ok(self) response = self.client.post( reverse(self.sensor_url), data={ - "submit_new_sensor": "", + "submit_new_sensor": "", "sensor-name": "", - "select-sensor-type": self.test_sensor["type_id"] - } + "select-sensor-type": self.test_sensor["type_id"], + }, ) # Check that POST redirects to sensor (same page reloads) @@ -229,10 +234,10 @@ def test_ConfigureSensorView_invalid_POST_sensor_no_name_no_object_created(self) self.client.post( reverse(self.sensor_url), data={ - "submit_new_sensor": "", + "submit_new_sensor": "", "sensor-name": "", - "select-sensor-type": self.test_sensor["type_id"] - } + "select-sensor-type": self.test_sensor["type_id"], + }, ) # Check that AGSensor object is created in db with expected params @@ -242,7 +247,8 @@ def test_ConfigureSensorView_invalid_POST_sensor_no_name_no_object_created(self) # Sensor name already in use - still returns status OK def test_ConfigureSensorView_invalid_POST_sensor_name_taken_status_ok(self): AGSensor.objects.create( - name=self.test_sensor["name"], type_id=AGSensorType.objects.get(name=self.test_type_object_name) + name=self.test_sensor["name"], + type_id=AGSensorType.objects.get(name=self.test_type_object_name), ) # Login @@ -252,10 +258,10 @@ def test_ConfigureSensorView_invalid_POST_sensor_name_taken_status_ok(self): response = self.client.post( reverse(self.sensor_url), data={ - "submit_new_sensor": "", + "submit_new_sensor": "", "sensor-name": self.test_sensor["name"], - "select-sensor-type": self.test_sensor["type_id"] - } + "select-sensor-type": self.test_sensor["type_id"], + }, ) # Check that POST redirects to sensor (same page reloads) @@ -264,20 +270,21 @@ def test_ConfigureSensorView_invalid_POST_sensor_name_taken_status_ok(self): # Sensor name already in use - new AGSensor object not created def test_ConfigureSensorView_invalid_POST_sensor_name_taken_no_object_created(self): AGSensor.objects.create( - name=self.test_sensor["name"], type_id=AGSensorType.objects.get(name=self.test_type_object_name) + name=self.test_sensor["name"], + type_id=AGSensorType.objects.get(name=self.test_type_object_name), ) # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) # POST sensor data - response = self.client.post( + self.client.post( reverse(self.sensor_url), data={ - "submit_new_sensor": "", + "submit_new_sensor": "", "sensor-name": self.test_sensor["name"], - "select-sensor-type": self.test_sensor["type_id"] - } + "select-sensor-type": self.test_sensor["type_id"], + }, ) # Check that additional AGSensor object is not created in db @@ -297,15 +304,17 @@ def test_ConfigureSensorView_invalid_POST_sensor_type_name_missing_status_ok(sel "type-name": "", "field-names": self.test_sensor_type["field-names"], "data-types": self.test_sensor_type["data-types"], - "units": self.test_sensor_type["units"] - } + "units": self.test_sensor_type["units"], + }, ) # Check that POST redirects to sensor (same page reloads) self.assertEqual(200, response.status_code) # Sensor type name missing - no AGSensorType object created - def test_ConfigureSensorView_bad_POST_sensor_type_name_missing_no_object_created(self): + def test_ConfigureSensorView_bad_POST_sensor_type_name_missing_no_object_created( + self, + ): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -317,8 +326,8 @@ def test_ConfigureSensorView_bad_POST_sensor_type_name_missing_no_object_created "type-name": "", "field-names": self.test_sensor_type["field-names"], "data-types": self.test_sensor_type["data-types"], - "units": self.test_sensor_type["units"] - } + "units": self.test_sensor_type["units"], + }, ) # Check that AGSensor object is created in db with expected params @@ -326,7 +335,9 @@ def test_ConfigureSensorView_bad_POST_sensor_type_name_missing_no_object_created self.assertEqual(sensors.count(), 0) # Field name missing still returns status OK - def test_ConfigureSensorView_invalid_POST_sensor_type_field_name_missing_status_ok(self): + def test_ConfigureSensorView_invalid_POST_sensor_type_field_name_missing_status_ok( + self, + ): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -338,15 +349,17 @@ def test_ConfigureSensorView_invalid_POST_sensor_type_field_name_missing_status_ "type-name": self.test_sensor_type["type-name"], "field-names": [self.field_name_1], "data-types": self.test_sensor_type["data-types"], - "units": self.test_sensor_type["units"] - } + "units": self.test_sensor_type["units"], + }, ) # Check that POST redirects to sensor (same page reloads) self.assertEqual(200, response.status_code) # Field name missing - no AGSensorType object created - def test_ConfigureSensorView_bad_POST_sensor_type_field_name_missing_no_object_created(self): + def test_ConfigureSensorView_bad_POST_sensor_type_field_name_missing_no_object_created( + self, + ): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -358,8 +371,8 @@ def test_ConfigureSensorView_bad_POST_sensor_type_field_name_missing_no_object_c "type-name": self.test_sensor_type["type-name"], "field-names": [self.field_name_1], "data-types": self.test_sensor_type["data-types"], - "units": self.test_sensor_type["units"] - } + "units": self.test_sensor_type["units"], + }, ) # Check that AGSensor object is created in db with expected params @@ -367,7 +380,9 @@ def test_ConfigureSensorView_bad_POST_sensor_type_field_name_missing_no_object_c self.assertEqual(sensors.count(), 0) # AGSensorType name taken returns status OK - def test_ConfigureSensorView_invalid_POST_sensor_type_field_name_missing_status_ok(self): + def test_ConfigureSensorView_invalid_POST_sensor_type_name_taken_status_ok( + self, + ): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -376,18 +391,20 @@ def test_ConfigureSensorView_invalid_POST_sensor_type_field_name_missing_status_ reverse(self.sensor_url), data={ "submit_new_type": "", - "type-name": self.test_type_object_name, #AGSensorType created in setUp() + "type-name": self.test_type_object_name, # AGSensorType created in setUp() "field-names": self.test_sensor_type["field-names"], "data-types": self.test_sensor_type["data-types"], - "units": self.test_sensor_type["units"] - } + "units": self.test_sensor_type["units"], + }, ) # Check that POST redirects to sensor (same page reloads) self.assertEqual(200, response.status_code) # AGSensorType name taken - no AGSensorType object created - def test_ConfigureSensorView_bad_POST_sensor_type_field_name_missing_no_object_created(self): + def test_ConfigureSensorView_invalid_POST_sensor_type_name_taken_no_object_created( + self, + ): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -396,11 +413,11 @@ def test_ConfigureSensorView_bad_POST_sensor_type_field_name_missing_no_object_c reverse(self.sensor_url), data={ "submit_new_type": "", - "type-name": self.test_type_object_name, #AGSensorType created in setUp() + "type-name": self.test_type_object_name, # AGSensorType created in setUp() "field-names": self.test_sensor_type["field-names"], "data-types": self.test_sensor_type["data-types"], - "units": self.test_sensor_type["units"] - } + "units": self.test_sensor_type["units"], + }, ) # Check that AGSensor object is created in db with expected params @@ -408,7 +425,9 @@ def test_ConfigureSensorView_bad_POST_sensor_type_field_name_missing_no_object_c self.assertEqual(sensors.count(), 0) # AGSensorType duplicated field name returns status OK - def test_ConfigureSensorView_invalid_POST_sensor_type_field_name_missing_status_ok(self): + def test_ConfigureSensorView_bad_POST_sensor_type_duplicate_field_name_missing_status_ok( + self, + ): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -420,15 +439,17 @@ def test_ConfigureSensorView_invalid_POST_sensor_type_field_name_missing_status_ "type-name": self.test_sensor_type["type-name"], "field-names": [self.field_name_1, self.field_name_1], "data-types": self.test_sensor_type["data-types"], - "units": self.test_sensor_type["units"] - } + "units": self.test_sensor_type["units"], + }, ) # Check that POST redirects to sensor (same page reloads) self.assertEqual(200, response.status_code) # AGSensorType duplicated field name - no AGSensorType object created - def test_ConfigureSensorView_bad_POST_sensor_type_field_name_missing_no_object_created(self): + def test_ConfigureSensorView_bad_POST_sensor_type_duplicate_field_name_no_object_created( + self, + ): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -440,8 +461,8 @@ def test_ConfigureSensorView_bad_POST_sensor_type_field_name_missing_no_object_c "type-name": self.test_sensor_type["type-name"], "field-names": [self.field_name_1, self.field_name_1], "data-types": self.test_sensor_type["data-types"], - "units": self.test_sensor_type["units"] - } + "units": self.test_sensor_type["units"], + }, ) # Check that AGSensor object is created in db with expected params diff --git a/mercury/views/sensor.py b/mercury/views/sensor.py index 73f2e99d..3cdd3721 100644 --- a/mercury/views/sensor.py +++ b/mercury/views/sensor.py @@ -28,8 +28,10 @@ def validate_add_sensor_inputs(sensor_name, request): return form_valid, request + def validate_add_sensor_type_inputs(type_name, field_name_list, request): - """This validates the form before a user submits a new sensor type to prevent bad inputs""" + """This validates the form before a user submits a new sensor type to + prevent bad inputs""" form_valid = True @@ -56,6 +58,7 @@ def validate_add_sensor_type_inputs(type_name, field_name_list, request): return form_valid, request + def delete_sensor(request, sensor_id): """This deletes a sensor from the database based on user button click""" @@ -63,14 +66,20 @@ def delete_sensor(request, sensor_id): sensor_to_delete.delete() return redirect("/sensor") + def delete_sensor_type(request, type_id): """This deletes a sensor type from the database based on user button click""" - for sensor in AGSensor.objects.all(): #delete sensors with this type first to avoid foreignkey error + for ( + sensor + ) in ( + AGSensor.objects.all() + ): # delete sensors with this type first to avoid foreignkey error sensor.delete() type_to_delete = AGSensorType.objects.get(id=type_id) type_to_delete.delete() return redirect("/sensor") + def update_sensor(request, sensor_id): """This updates a sensor in the database based on user input""" @@ -81,7 +90,7 @@ def update_sensor(request, sensor_id): sensor_name = sensor_name.strip().lower() # remove excess whitespace and CAPS valid, request = validate_add_sensor_inputs(sensor_name, request) - sensor_types = AGSensorType.objects.all() #for when we return context later + sensor_types = AGSensorType.objects.all() # for when we return context later if valid: sensor_to_update.name = sensor_name sensor_type = request.POST.get("edit-select-sensor-type") @@ -91,7 +100,7 @@ def update_sensor(request, sensor_id): context = { "sensors": sensors, "sensor_types": sensor_types, - } + } else: sensors = AGSensor.objects.all() context = { @@ -105,7 +114,7 @@ def update_sensor(request, sensor_id): def update_sensor_type(request, type_id): """This updates a sensor type in the database based on user input""" - #Currently causing a strange URL bug, need to debug + # Currently causing a strange URL bug, need to debug type_to_update = AGSensorType.objects.get(id=type_id) type_name = request.POST.get("edit-type-name") @@ -124,17 +133,17 @@ def update_sensor_type(request, type_id): for field in fields: type_format[field[0]] = {"data_type": field[1], "unit": field[2]} - sensors = AGSensor.objects.all() #for when we return context later + sensors = AGSensor.objects.all() # for when we return context later if valid: - type_to_update.name=type_name - type_to_update.processing_formula=0 - type_to_update.format=type_format + type_to_update.name = type_name + type_to_update.processing_formula = 0 + type_to_update.format = type_format type_to_update.save() sensor_types = AGSensorType.objects.all() context = { "sensor_types": sensor_types, "sensors": sensors, - } + } else: sensor_types = AGSensorType.objects.all() context = { @@ -161,7 +170,7 @@ def get(self, request, *args, **kwargs): @require_event_code def post(self, request, *args, **kwargs): - if ("submit_new_type" in request.POST): + if "submit_new_type" in request.POST: type_name = request.POST.get("type-name") field_names = request.POST.getlist("field-names") field_types = request.POST.getlist("data-types") @@ -170,7 +179,9 @@ def post(self, request, *args, **kwargs): # reformat then validate inputs to avoid duplicated names or bad inputs like " " type_name = type_name.strip().lower() # remove excess whitespace and CAPS field_names = [string.strip().lower() for string in field_names] - valid, request = validate_add_sensor_type_inputs(type_name, field_names, request) + valid, request = validate_add_sensor_type_inputs( + type_name, field_names, request + ) # create sensor format which is dictionary of dictionaries type_format = {} @@ -178,16 +189,17 @@ def post(self, request, *args, **kwargs): for field in fields: type_format[field[0]] = {"data_type": field[1], "unit": field[2]} - - sensors = AGSensor.objects.all() #for when we return context later + sensors = AGSensor.objects.all() # for when we return context later if valid: - new_type = AGSensorType.objects.create(name=type_name, processing_formula=0, format=type_format) + new_type = AGSensorType.objects.create( + name=type_name, processing_formula=0, format=type_format + ) new_type.save() sensor_types = AGSensorType.objects.all() context = { "sensor_types": sensor_types, "sensors": sensors, - } + } else: sensor_types = AGSensorType.objects.all() context = { @@ -198,19 +210,27 @@ def post(self, request, *args, **kwargs): } return render(request, self.template_name, context) - - elif ("submit_new_sensor" in request.POST): + + elif "submit_new_sensor" in request.POST: sensor_name = request.POST.get("sensor-name") sensor_type = request.POST.get("select-sensor-type") - sensor_type = AGSensorType.objects.get(name=sensor_type) #str --> AGSensorType + sensor_type = AGSensorType.objects.get( + name=sensor_type + ) # str --> AGSensorType # reformat then validate name to avoid duplicated names or bad inputs like " " - sensor_name = sensor_name.strip().lower() # remove excess whitespace and CAPS + sensor_name = ( + sensor_name.strip().lower() + ) # remove excess whitespace and CAPS valid, request = validate_add_sensor_inputs(sensor_name, request) - sensor_types = AGSensorType.objects.all() #for when we return context later + sensor_types = ( + AGSensorType.objects.all() + ) # for when we return context later if valid: - new_sensor = AGSensor.objects.create(name=sensor_name, type_id=sensor_type) + new_sensor = AGSensor.objects.create( + name=sensor_name, type_id=sensor_type + ) new_sensor.save() gf_configs = GFConfig.objects.all() @@ -226,7 +246,7 @@ def post(self, request, *args, **kwargs): context = { "sensors": sensors, "sensor_types": sensor_types, - } + } else: sensors = AGSensor.objects.all() context = { @@ -235,4 +255,4 @@ def post(self, request, *args, **kwargs): "sensor_type": sensor_type, "sensor_types": sensor_types, } - return render(request, self.template_name, context) \ No newline at end of file + return render(request, self.template_name, context) From b1c999ccd4cedfae74ac74e28edaf3c29c4e193a Mon Sep 17 00:00:00 2001 From: Daisy Crego Date: Mon, 23 Mar 2020 15:34:43 -0400 Subject: [PATCH 18/21] Fix migrations files to handle recent merge. --- .../migrations/0016_merge_20200323_1532.py | 14 ++++++++ mercury/models.py | 36 ------------------- 2 files changed, 14 insertions(+), 36 deletions(-) create mode 100644 mercury/migrations/0016_merge_20200323_1532.py diff --git a/mercury/migrations/0016_merge_20200323_1532.py b/mercury/migrations/0016_merge_20200323_1532.py new file mode 100644 index 00000000..b2358325 --- /dev/null +++ b/mercury/migrations/0016_merge_20200323_1532.py @@ -0,0 +1,14 @@ +# Generated by Django 2.2.6 on 2020-03-23 15:32 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('mercury', '0015_gfconfig_gf_db_grafana_name'), + ('mercury', '0012_auto_20200320_1735'), + ] + + operations = [ + ] diff --git a/mercury/models.py b/mercury/models.py index 0eeba67c..4d8d5be5 100644 --- a/mercury/models.py +++ b/mercury/models.py @@ -1,40 +1,4 @@ from django.db import models -from django.contrib.postgres.fields import JSONField -import uuid -from django.utils import timezone - - -class AGEvent(models.Model): - """This model stores the information about events. When a new event is created, - a UUID4-typed event_uuid will be assigned to this event and also store the current - date for this event. """ - - event_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) - event_name = models.CharField(max_length=40, blank=True) - event_date = models.DateTimeField(default=timezone.now) - event_description = models.CharField(max_length=100, null=False, blank=True) - event_location = models.CharField(max_length=100, null=False, blank=True) - - -class AGSensor(models.Model): - sensor_id = models.AutoField(primary_key=True) - sensor_name = models.CharField(max_length=1024, blank=True) - sensor_processing_formula = models.IntegerField(default=0, null=False) - sensor_format = JSONField() - - -class AGMeasurement(models.Model): - measurement_uuid = models.UUIDField( - primary_key=True, default=uuid.uuid4, editable=False - ) - measurement_timestamp = models.DateTimeField(default=timezone.now, blank=False) - measurement_event = models.ForeignKey( - AGEvent, on_delete=models.CASCADE, blank=False, null=False - ) - measurement_sensor = models.ForeignKey( - AGSensor, on_delete=models.CASCADE, blank=False, null=False - ) - measurement_value = JSONField() class GFConfig(models.Model): From 9c65299717069d59e5d53af8e4a5b0d3c8be99ed Mon Sep 17 00:00:00 2001 From: Daisy Crego Date: Mon, 23 Mar 2020 15:42:28 -0400 Subject: [PATCH 19/21] Black and flake8. --- mercury/tests/test_configure_sensors.py | 46 ++++++++++++------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/mercury/tests/test_configure_sensors.py b/mercury/tests/test_configure_sensors.py index 24efd842..989bd71d 100644 --- a/mercury/tests/test_configure_sensors.py +++ b/mercury/tests/test_configure_sensors.py @@ -53,7 +53,7 @@ def _get_with_event_code(self, url, event_code): session = self.client.session return response, session - def test_ConfigureSensorView_GET_success(self): + def test_configure_sensor_view_get_success(self): response, session = self._get_with_event_code(self.sensor_url, self.TESTCODE) self.assertEqual(200, response.status_code) self.assertEqual(True, session["event_code_active"]) @@ -62,7 +62,7 @@ def test_ConfigureSensorView_GET_success(self): # Valid POST tests # Valid POST to create sensor returns status OK - def test_ConfigureSensorView_valid_POST_sensor_returns_status_ok(self): + def test_configure_sensor_valid_POST_sensor_returns_status_ok(self): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -80,7 +80,7 @@ def test_ConfigureSensorView_valid_POST_sensor_returns_status_ok(self): self.assertEqual(200, response.status_code) # Valid POST creates new AGSensor object - def test_ConfigureSensorView_valid_POST_sensor_success_object_created(self): + def test_configure_sensor_valid_post_sensor_success_object_created(self): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -99,7 +99,7 @@ def test_ConfigureSensorView_valid_POST_sensor_success_object_created(self): self.assertEqual(sensors.count(), 1) # Valid POST creates new AGSensor object with expected parameters - def test_ConfigureSensorView_valid_POST_sensor_object_created_with_correct_params( + def test_configure_sensor_valid_post_sensor_object_created_with_correct_params( self, ): # Login @@ -122,7 +122,7 @@ def test_ConfigureSensorView_valid_POST_sensor_object_created_with_correct_param self.assertEqual(sensor.type_id.name, self.test_sensor["type_id"]) # Valid POST to create AGSensorType returns status OK - def test_ConfigureSensorView_valid_POST_sensor_type_returns_status_ok(self): + def test_configure_sensor_valid_post_sensor_type_returns_status_ok(self): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -142,7 +142,7 @@ def test_ConfigureSensorView_valid_POST_sensor_type_returns_status_ok(self): self.assertEqual(200, response.status_code) # Valid POST creates new AGSensorType object - def test_ConfigureSensorView_valid_POST_sensor_type_success_object_created(self): + def test_configure_sensor_valid_post_sensor_type_success_object_created(self): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -164,7 +164,7 @@ def test_ConfigureSensorView_valid_POST_sensor_type_success_object_created(self) sensor_types.count(), 2 ) # not 1 since we created a sensor_type in the setUp() function - def test_ConfigureSensorView_valid_POST_sensor_type_object_created_with_correct_params( + def test_configure_sensor_valid_post_sensor_type_object_created_with_correct_params( self, ): # Login @@ -208,7 +208,7 @@ def test_ConfigureSensorView_valid_POST_sensor_type_object_created_with_correct_ # # Invalid POST tests # Duplicate field names still returns status ok - def test_ConfigureSensorView_invalid_POST_sensor_no_name_returns_status_ok(self): + def test_configure_sensor_invalid_post_sensor_no_name_returns_status_ok(self): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -226,7 +226,7 @@ def test_ConfigureSensorView_invalid_POST_sensor_no_name_returns_status_ok(self) self.assertEqual(200, response.status_code) # Duplicate field names - no AGSensor object created - def test_ConfigureSensorView_invalid_POST_sensor_no_name_no_object_created(self): + def test_configure_sensor_invalid_POST_sensor_no_name_no_object_created(self): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -245,7 +245,7 @@ def test_ConfigureSensorView_invalid_POST_sensor_no_name_no_object_created(self) self.assertEqual(sensors.count(), 0) # Sensor name already in use - still returns status OK - def test_ConfigureSensorView_invalid_POST_sensor_name_taken_status_ok(self): + def test_configure_sensor_view_invalid_post_sensor_name_taken_status_ok(self): AGSensor.objects.create( name=self.test_sensor["name"], type_id=AGSensorType.objects.get(name=self.test_type_object_name), @@ -268,7 +268,7 @@ def test_ConfigureSensorView_invalid_POST_sensor_name_taken_status_ok(self): self.assertEqual(200, response.status_code) # Sensor name already in use - new AGSensor object not created - def test_ConfigureSensorView_invalid_POST_sensor_name_taken_no_object_created(self): + def test_configure_sensor_invalid_POST_sensor_name_taken_no_object_created(self): AGSensor.objects.create( name=self.test_sensor["name"], type_id=AGSensorType.objects.get(name=self.test_type_object_name), @@ -292,7 +292,7 @@ def test_ConfigureSensorView_invalid_POST_sensor_name_taken_no_object_created(se self.assertEqual(sensors.count(), 1) # Sensor type name missing still returns status OK - def test_ConfigureSensorView_invalid_POST_sensor_type_name_missing_status_ok(self): + def test_configure_sensor_invalid_POST_sensor_type_name_missing_status_ok(self): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -312,7 +312,7 @@ def test_ConfigureSensorView_invalid_POST_sensor_type_name_missing_status_ok(sel self.assertEqual(200, response.status_code) # Sensor type name missing - no AGSensorType object created - def test_ConfigureSensorView_bad_POST_sensor_type_name_missing_no_object_created( + def test_configure_sensor_bad_post_sensor_type_name_missing_no_object_created( self, ): # Login @@ -335,7 +335,7 @@ def test_ConfigureSensorView_bad_POST_sensor_type_name_missing_no_object_created self.assertEqual(sensors.count(), 0) # Field name missing still returns status OK - def test_ConfigureSensorView_invalid_POST_sensor_type_field_name_missing_status_ok( + def test_configure_sensor_view_invalid_post_sensor_type_field_name_missing_status_ok( self, ): # Login @@ -357,7 +357,7 @@ def test_ConfigureSensorView_invalid_POST_sensor_type_field_name_missing_status_ self.assertEqual(200, response.status_code) # Field name missing - no AGSensorType object created - def test_ConfigureSensorView_bad_POST_sensor_type_field_name_missing_no_object_created( + def test_configure_sensor_bad_post_sensor_type_field_name_missing_no_object_created( self, ): # Login @@ -380,9 +380,7 @@ def test_ConfigureSensorView_bad_POST_sensor_type_field_name_missing_no_object_c self.assertEqual(sensors.count(), 0) # AGSensorType name taken returns status OK - def test_ConfigureSensorView_invalid_POST_sensor_type_name_taken_status_ok( - self, - ): + def test_configure_sensor_invalid_post_sensor_type_name_taken_status_ok(self,): # Login self._get_with_event_code(self.sensor_url, self.TESTCODE) @@ -391,7 +389,8 @@ def test_ConfigureSensorView_invalid_POST_sensor_type_name_taken_status_ok( reverse(self.sensor_url), data={ "submit_new_type": "", - "type-name": self.test_type_object_name, # AGSensorType created in setUp() + "type-name": self.test_type_object_name, + # AGSensorType created in setUp() "field-names": self.test_sensor_type["field-names"], "data-types": self.test_sensor_type["data-types"], "units": self.test_sensor_type["units"], @@ -402,7 +401,7 @@ def test_ConfigureSensorView_invalid_POST_sensor_type_name_taken_status_ok( self.assertEqual(200, response.status_code) # AGSensorType name taken - no AGSensorType object created - def test_ConfigureSensorView_invalid_POST_sensor_type_name_taken_no_object_created( + def test_configure_sensor_view_invalid_post_sensor_type_name_taken_no_object_created( self, ): # Login @@ -413,7 +412,8 @@ def test_ConfigureSensorView_invalid_POST_sensor_type_name_taken_no_object_creat reverse(self.sensor_url), data={ "submit_new_type": "", - "type-name": self.test_type_object_name, # AGSensorType created in setUp() + "type-name": self.test_type_object_name, + # AGSensorType created in setUp() "field-names": self.test_sensor_type["field-names"], "data-types": self.test_sensor_type["data-types"], "units": self.test_sensor_type["units"], @@ -425,7 +425,7 @@ def test_ConfigureSensorView_invalid_POST_sensor_type_name_taken_no_object_creat self.assertEqual(sensors.count(), 0) # AGSensorType duplicated field name returns status OK - def test_ConfigureSensorView_bad_POST_sensor_type_duplicate_field_name_missing_status_ok( + def test_configure_sensor_bad_post_sensor_type_dup_field_name_missing_status_ok( self, ): # Login @@ -447,7 +447,7 @@ def test_ConfigureSensorView_bad_POST_sensor_type_duplicate_field_name_missing_s self.assertEqual(200, response.status_code) # AGSensorType duplicated field name - no AGSensorType object created - def test_ConfigureSensorView_bad_POST_sensor_type_duplicate_field_name_no_object_created( + def test_configure_sensor_bad_post_sensor_type_dup_field_name_no_object_created( self, ): # Login From c0799658a04f2ea6d92ce706a3b118211ad902d8 Mon Sep 17 00:00:00 2001 From: Daisy Crego Date: Mon, 23 Mar 2020 15:56:57 -0400 Subject: [PATCH 20/21] Add AGEvent model back into the db, because it was being referenced in many places and simply deleting it broke a lot of things. --- mercury/forms.py | 2 +- mercury/migrations/0017_agevent.py | 25 +++++++++++++++++++++++++ mercury/models.py | 14 ++++++++++++++ mercury/views/dashboard.py | 2 +- mercury/views/event.py | 2 +- mercury/views/events.py | 2 +- mercury/views/simulator.py | 2 +- 7 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 mercury/migrations/0017_agevent.py diff --git a/mercury/forms.py b/mercury/forms.py index b998e734..2d096c7c 100644 --- a/mercury/forms.py +++ b/mercury/forms.py @@ -1,8 +1,8 @@ """This module defines the ModelForms (or Forms) that are used by the rendering engine to accept input for various features of the site""" from django import forms -from ag_data.models import AGEvent from mercury.models import ( + AGEvent, GFConfig, TemperatureSensor, AccelerationSensor, diff --git a/mercury/migrations/0017_agevent.py b/mercury/migrations/0017_agevent.py new file mode 100644 index 00000000..fe487916 --- /dev/null +++ b/mercury/migrations/0017_agevent.py @@ -0,0 +1,25 @@ +# Generated by Django 2.2.6 on 2020-03-23 15:55 + +from django.db import migrations, models +import django.utils.timezone +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('mercury', '0016_merge_20200323_1532'), + ] + + operations = [ + migrations.CreateModel( + name='AGEvent', + fields=[ + ('event_uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('event_name', models.CharField(blank=True, max_length=40)), + ('event_date', models.DateTimeField(default=django.utils.timezone.now)), + ('event_description', models.CharField(blank=True, max_length=100)), + ('event_location', models.CharField(blank=True, max_length=100)), + ], + ), + ] diff --git a/mercury/models.py b/mercury/models.py index 4d8d5be5..3423f6b8 100644 --- a/mercury/models.py +++ b/mercury/models.py @@ -1,4 +1,6 @@ from django.db import models +import uuid +from django.utils import timezone class GFConfig(models.Model): @@ -20,6 +22,18 @@ class GFConfig(models.Model): gf_current = models.BooleanField(default=False, blank=True) +class AGEvent(models.Model): + """This model stores the information about events. When a new event is created, + a UUID4-typed event_uuid will be assigned to this event and also store the current + date for this event. """ + + event_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) + event_name = models.CharField(max_length=40, blank=True) + event_date = models.DateTimeField(default=timezone.now) + event_description = models.CharField(max_length=100, null=False, blank=True) + event_location = models.CharField(max_length=100, null=False, blank=True) + + class TemperatureSensor(models.Model): """This model represents the Temperature sensor that we expect to be potentially available in the future in the NYU Motorsports diff --git a/mercury/views/dashboard.py b/mercury/views/dashboard.py index 45857d28..d67ed943 100644 --- a/mercury/views/dashboard.py +++ b/mercury/views/dashboard.py @@ -1,6 +1,6 @@ from django.shortcuts import render from django.views.generic import TemplateView -from ag_data.models import AGEvent +from mercury.models import AGEvent from mercury.models import ( TemperatureSensor, AccelerationSensor, diff --git a/mercury/views/event.py b/mercury/views/event.py index 9027cf31..abce1b76 100644 --- a/mercury/views/event.py +++ b/mercury/views/event.py @@ -4,7 +4,7 @@ from ..event_check import require_event_code from mercury.forms import EventForm -from ag_data.models import AGEvent +from mercury.models import AGEvent log = logging.getLogger(__name__) log.setLevel(logging.ERROR) diff --git a/mercury/views/events.py b/mercury/views/events.py index 9f60cd70..bc4574a1 100644 --- a/mercury/views/events.py +++ b/mercury/views/events.py @@ -4,7 +4,7 @@ from django.views.generic import TemplateView from ..event_check import require_event_code from mercury.forms import EventForm -from ag_data.models import AGEvent +from mercury.models import AGEvent log = logging.getLogger(__name__) log.setLevel(logging.ERROR) diff --git a/mercury/views/simulator.py b/mercury/views/simulator.py index de892f26..81a9d184 100644 --- a/mercury/views/simulator.py +++ b/mercury/views/simulator.py @@ -3,8 +3,8 @@ from django.http import HttpResponse from django.shortcuts import render from django.views.generic import TemplateView -from ag_data.models import AGEvent from mercury.models import ( + AGEvent, TemperatureSensor, AccelerationSensor, WheelSpeedSensor, From 63e36c03d0b601aa717c0a6839c4f0c4e32237a2 Mon Sep 17 00:00:00 2001 From: Daisy Crego Date: Mon, 23 Mar 2020 16:03:07 -0400 Subject: [PATCH 21/21] Add reference to AGEvent model back into test which was failing. --- mercury/tests/test_event.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mercury/tests/test_event.py b/mercury/tests/test_event.py index 5aa6d5aa..8fe0189f 100644 --- a/mercury/tests/test_event.py +++ b/mercury/tests/test_event.py @@ -1,7 +1,6 @@ from django.test import TestCase from django.urls import reverse -from mercury.models import EventCodeAccess -from ag_data.models import AGEvent +from mercury.models import EventCodeAccess, AGEvent import datetime