Skip to content

Commit

Permalink
Merge pull request #183 from ODM2/release/0.5.0
Browse files Browse the repository at this point in the history
Release/0.5.0
  • Loading branch information
jcaraballo17 authored Feb 26, 2018
2 parents 80b59ef + 361f04e commit 5bb9aa0
Show file tree
Hide file tree
Showing 44 changed files with 4,084 additions and 3,206 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13 changes: 11 additions & 2 deletions src/WebSDL/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'widget_tweaks'
'widget_tweaks',
'requests',
]

MIDDLEWARE_CLASSES = [
Expand All @@ -61,6 +62,7 @@
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
Expand Down Expand Up @@ -152,11 +154,14 @@

RECAPTCHA_VERIFY_URL = "https://www.google.com/recaptcha/api/siteverify"

EMAIL_SENDER = data['password_email_sender'] if 'password_email_sender' in data else '',

EMAIL_SENDER = data['email_sender'] if 'email_sender' in data else '',
NOTIFY_EMAIL = data['notify_email_sender'] if 'notify_email_sender' in data else ''

DEFAULT_FROM_EMAIL = EMAIL_SENDER[0] if isinstance(EMAIL_SENDER, tuple) else EMAIL_SENDER

NOTIFY_EMAIL_SENDER = NOTIFY_EMAIL[0] if isinstance(NOTIFY_EMAIL, tuple) else NOTIFY_EMAIL

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

EMAIL_SERVER = data['email_host'] if 'email_host' in data else '',
Expand All @@ -167,6 +172,10 @@

INFLUX_URL_QUERY = data['influx_query']

INFLUX_UPDATE_URL = data['influx_updater_query']['url']

INFLUX_UPDATE_BODY = data['influx_updater_query']['body']

# This data period is measured in days
SENSOR_DATA_PERIOD = data['sensor_data_period'] if 'sensor_data_period' in data else '2'

Expand Down
13 changes: 11 additions & 2 deletions src/WebSDL/settings/settings_template.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
"host": "-optional",
"recaptcha_secret_key": "-optional",
"recaptcha_user_key": "-optional",
"email_sender": "[email protected]",
"password_email_sender": "[email protected]",
"email_host": "mail.usu.edu",
"influx_query": "{hostname_with_url_and_auth_and_db}&q=SELECT%20%2A%20FROM%20%22uuid_{result_uuid}%22%20WHERE%20%22time%22%20%3E=%20%27{last_measurement}%27-{days_of_data}d",
"tsa_url": "http://data.envirodiy.org/tsa/",
"sensor_data_period": "3",
"databases": [
{
"name": "default",
Expand All @@ -24,5 +27,11 @@
"host": "",
"port": ""
}
]
],
"hydroshare_oauth": {
"client_id": "client_id_here",
"client_secret": "client_secret_here",
"redirect_uri": "http://localhost:8000/oauth/hydroshare/",
"response_type": "code"
}
}
2,823 changes: 2,823 additions & 0 deletions src/dataloader/migrations/0001_initial.py

Large diffs are not rendered by default.

25 changes: 18 additions & 7 deletions src/dataloader/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,11 +294,13 @@ class Meta:
class MethodType(ControlledVocabulary):
class Meta:
db_table = 'cv_methodtype'
ordering = ['name']


class OrganizationType(ControlledVocabulary):
class Meta:
db_table = 'cv_organizationtype'
ordering = ['name']


class PropertyDataType(ControlledVocabulary):
Expand Down Expand Up @@ -349,6 +351,7 @@ class Meta:
class SiteType(ControlledVocabulary):
class Meta:
db_table = 'cv_sitetype'
ordering = ['name']


class Status(ControlledVocabulary):
Expand All @@ -364,16 +367,19 @@ class Meta:
class UnitsType(ControlledVocabulary):
class Meta:
db_table = 'cv_unitstype'
ordering = ['name']


class VariableName(ControlledVocabulary):
class Meta:
db_table = 'cv_variablename'
ordering = ['name']


class VariableType(ControlledVocabulary):
class Meta:
db_table = 'cv_variabletype'
ordering = ['name']


class ReferenceMaterialMedium(ControlledVocabulary):
Expand Down Expand Up @@ -421,7 +427,7 @@ class Organization(ODM2Model):
people = models.ManyToManyField('People', through='Affiliation')

def __str__(self):
return '%s' % self.organization_name
return '%s' % self.organization_code

def __repr__(self):
return "<Organization('%s', '%s', '%s', '%s')>" % (
Expand All @@ -430,6 +436,7 @@ def __repr__(self):

class Meta:
db_table = 'organizations'
ordering = ['organization_code']


@python_2_unicode_compatible
Expand Down Expand Up @@ -710,6 +717,7 @@ def __repr__(self):

class Meta:
db_table = 'units'
ordering = ['unit_abbreviation']


@python_2_unicode_compatible
Expand All @@ -719,7 +727,7 @@ class Variable(models.Model):
variable_code = models.CharField(db_column='variablecode', max_length=50)
variable_name = models.ForeignKey('VariableName', db_column='variablenamecv')
variable_definition = models.CharField(db_column='variabledefinition', blank=True, max_length=500)
speciation = models.ForeignKey('Speciation', db_column='speciationcv')
speciation = models.ForeignKey('Speciation', db_column='speciationcv', blank=True, null=True)
no_data_value = models.FloatField(db_column='nodatavalue')

extension_property_values = models.ManyToManyField('ExtensionProperty', related_name='variables',
Expand All @@ -728,7 +736,7 @@ class Variable(models.Model):
through='VariableExternalIdentifier')

def __str__(self):
return '%s: %s' % (self.variable_name_id, self.variable_code)
return '%s' % self.variable_code

def __repr__(self):
return "<Variable('%s', '%s', '%s', '%s')>" % (
Expand All @@ -737,6 +745,7 @@ def __repr__(self):

class Meta:
db_table = 'variables'
ordering = ['variable_code']


@python_2_unicode_compatible
Expand Down Expand Up @@ -883,6 +892,7 @@ def __repr__(self):

class Meta:
db_table = 'equipmentmodels'
ordering = ['model_manufacturer', 'model_name']


@python_2_unicode_compatible
Expand All @@ -898,9 +908,9 @@ class InstrumentOutputVariable(models.Model):
objects = InstrumentOutputVariableManager()

def __str__(self):
return '%s %s %s: %s - %s' % (
self.variable.variable_name_id, self.variable.variable_code,
self.instrument_raw_output_unit.unit_abbreviation, self.instrument_method.method_code, self.model.model_name
return '%s: %s measured in %s' % (
self.model.model_manufacturer, self.variable.variable_code,
self.instrument_raw_output_unit.unit_abbreviation
)

def __repr__(self):
Expand All @@ -912,6 +922,7 @@ def __repr__(self):

class Meta:
db_table = 'instrumentoutputvariables'
ordering = ['model__model_manufacturer', 'variable__variable_code']


@python_2_unicode_compatible
Expand Down Expand Up @@ -1717,7 +1728,7 @@ class Meta:

class VariableExternalIdentifier(ExternalIdentifierBridge):
variable = models.ForeignKey('Variable', db_column='variableid')
variable_external_identifier = models.CharField(db_column='variableexternalidentifier', max_length=255)
variable_external_identifier = models.CharField(db_column='variableexternalidentifer', max_length=255)
variable_external_identifier_uri = models.CharField(db_column='variableexternalidentifieruri', blank=True, max_length=255)

def __repr__(self):
Expand Down
64 changes: 64 additions & 0 deletions src/dataloaderinterface/admin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,67 @@
from django.contrib import admin

from dataloader.models import *


# Register your models here.
from dataloaderinterface.models import SiteRegistration, SiteSensor


def update_sensor_data(obj, form, sensor_fields):
old_object = obj.__class__.objects.get(pk=obj.pk)
old_data = {field: getattr(old_object, field) for field in sensor_fields if field in form.changed_data}
new_data = {field: getattr(obj, field) for field in sensor_fields if field in form.changed_data}
SiteSensor.objects.filter(**old_data).update(**new_data)


@admin.register(SiteSensor)
class SiteSensorAdmin(admin.ModelAdmin):
pass


@admin.register(SiteRegistration)
class SiteRegistrationAdmin(admin.ModelAdmin):
pass


@admin.register(Organization)
class OrganizationAdmin(admin.ModelAdmin):
pass


@admin.register(EquipmentModel)
class EquipmentModelAdmin(admin.ModelAdmin):
sensor_fields = ['model_name', 'model_manufacturer']

def save_model(self, request, obj, form, change):
if change:
update_sensor_data(obj, form, self.sensor_fields)

super(EquipmentModelAdmin, self).save_model(request, obj, form, change)


@admin.register(Variable)
class VariableAdmin(admin.ModelAdmin):
sensor_fields = ['variable_name', 'variable_code']

def save_model(self, request, obj, form, change):
if change:
update_sensor_data(obj, form, self.sensor_fields)

super(VariableAdmin, self).save_model(request, obj, form, change)


@admin.register(Unit)
class UnitAdmin(admin.ModelAdmin):
sensor_fields = ['unit_name', 'unit_abbreviation']

def save_model(self, request, obj, form, change):
if change:
update_sensor_data(obj, form, self.sensor_fields)

super(UnitAdmin, self).save_model(request, obj, form, change)


@admin.register(InstrumentOutputVariable)
class InstrumentOutputVariableAdmin(admin.ModelAdmin):
pass
35 changes: 30 additions & 5 deletions src/dataloaderinterface/forms.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from datetime import datetime

from django.forms import NumberInput, TimeInput

from dataloader.models import SamplingFeature, People, Organization, Affiliation, Result, Site, EquipmentModel, Medium, \
OrganizationType, ActionBy, SiteType
from django import forms
Expand All @@ -8,7 +10,14 @@
from django.db.models.query_utils import Q
from django.forms.formsets import formset_factory

from dataloaderinterface.models import ODM2User
from dataloaderinterface.models import ODM2User, SiteAlert


class SiteTypeSelect(forms.Select):
def create_option(self, name, value, label, selected, index, subindex=None, attrs=None):
option = super(SiteTypeSelect, self).create_option(name, value, label, selected, index, subindex, attrs)
option['attrs']['title'] = self.choices.queryset.get(name=value).definition if value else ''
return option


# AUTHORIZATION
Expand Down Expand Up @@ -84,7 +93,7 @@ class Meta:

class ActionByForm(forms.ModelForm):
use_required_attribute = False
affiliation = forms.ModelChoiceField(queryset=Affiliation.objects.all(), required=False, help_text='', label='Deployed By')
affiliation = forms.ModelChoiceField(queryset=Affiliation.objects.all(), required=False, help_text='Select the user that deployed or manages the site', label='Deployed By')

class Meta:
model = ActionBy
Expand Down Expand Up @@ -135,12 +144,15 @@ class Meta:

class SiteForm(forms.ModelForm):
allowed_site_types = [
'Aggregate groundwater use', 'Ditch', 'Atmosphere', 'Estuary', 'House', 'Land', 'Pavement', 'Stream', 'Spring',
'Lake, Reservoir, Impoundment', 'Laboratory or sample-preparation area', 'Soil hole', 'Storm sewer', 'Tidal stream', 'Wetland'
'Borehole', 'Ditch', 'Atmosphere', 'Estuary', 'House', 'Land', 'Pavement', 'Stream', 'Spring',
'Lake, Reservoir, Impoundment', 'Laboratory or sample-preparation area', 'Observation well', 'Soil hole',
'Storm sewer', 'Stream gage', 'Tidal stream', 'Water quality station', 'Weather station', 'Wetland', 'Other'
]

site_type = forms.ModelChoiceField(
queryset=SiteType.objects.filter(name__in=allowed_site_types), help_text='Select the type of site you are deploying (e.g., "Stream")'
queryset=SiteType.objects.filter(name__in=allowed_site_types),
help_text='Select the type of site you are deploying (e.g., "Stream")',
widget=SiteTypeSelect
)
use_required_attribute = False

Expand Down Expand Up @@ -195,3 +207,16 @@ class Meta:


ResultFormSet = formset_factory(ResultForm, extra=0, can_order=False, min_num=1, can_delete=True)


class SiteAlertForm(forms.ModelForm):
notify = forms.BooleanField(required=False, initial=False, label='Notify me if site stops receiving sensor data')
hours_threshold = forms.DurationField(required=False, label='Notify after', widget=NumberInput(attrs={'min': 1}))
suffix = ' hours of site inactivity'

class Meta:
model = SiteAlert
fields = ['notify', 'hours_threshold']
labels = {
'notify': 'Receive email notifications for this site',
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from datetime import timedelta
from django.core.management.base import BaseCommand

from dataloaderinterface.models import SiteSensor


class Command(BaseCommand):
help = ''

def handle(self, *args, **options):
sensors = SiteSensor.objects.filter(last_measurement_datetime__isnull=False)
for sensor in sensors:
sensor.last_measurement_utc_datetime = sensor.last_measurement_datetime - timedelta(hours=sensor.last_measurement_utc_offset)
sensor.save(update_fields=['last_measurement_utc_datetime'])
print('Last measurement utc datetime added to all sensors.')
Loading

0 comments on commit 5bb9aa0

Please sign in to comment.