Skip to content

Commit

Permalink
DBCC22-1485 Regional weather panel
Browse files Browse the repository at this point in the history
  • Loading branch information
fatbird authored and ray-oxd committed Mar 29, 2024
1 parent 02299b1 commit c070bce
Show file tree
Hide file tree
Showing 20 changed files with 654 additions and 214 deletions.
7 changes: 6 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ REACT_APP_RECAPTCHA_SITE_KEY=<reCAPTCHA site key>
# API
DRIVEBC_INLAND_FERRY_API_BASE_URL=<inland ferry api url>
DRIVEBC_IMAGE_API_BASE_URL=<image api url>
DRIVEBC_IMAGE_BASE_URL=<base url for local images>
DRIVEBC_IMAGE_PROXY_URL=<image proxy url>
DRIVEBC_WEBCAM_API_BASE_URL=<camera api url>
DRIVEBC_OPEN_511_API_BASE_URL=<open511 api url>
Expand All @@ -73,4 +74,8 @@ WEATHER_CLIENT_SECRET=<weather client secret>
# TESTS
# optional: set to config.test.DbcRunner to user test runner allowing for
# skipping db creation entirely
TEST_RUNNER=config.test.DbcRunner
TEST_RUNNER=config.test.DbcRunner

# OPTIONAL: include, set to true, to trigger optional backend code supporting
# dev in a docker environment (e.g., URLs for local image serving)
DEV_ENVIRONMENT=true
2 changes: 1 addition & 1 deletion compose/backend/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ echo 'creating superuser done; starting service'
# python manage.py runserver 0.0.0.0:8000
#trap : TERM INT; sleep 9999999999d & wait
export DJANGO_SETTINGS_MODULE=config.settings
gunicorn -b 0.0.0.0 config.wsgi 2> /tmp/gunicorn.log
gunicorn -b 0.0.0.0 --reload config.wsgi 2> /tmp/gunicorn.log
267 changes: 136 additions & 131 deletions src/backend/apps/feed/client.py

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions src/backend/apps/feed/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,17 +233,19 @@ class Meta:
fields = (
'id',
'code',
'station',
'location_latitude',
'location_longitude',
'name',
'region',
'observation_name',
'observation_zone',
'observation_utc_offset',
'observation_text_summary',
'conditions',
'forecast_group',
'hourly_forecast_group',
'observed',
'forecast_issued',
'sunrise',
'sunset',
'warnings',
)


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Generated by Django 4.2.3 on 2024-03-26 22:42

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('weather', '0011_alter_currentweather_datasets'),
]

operations = [
migrations.RemoveField(
model_name='regionalweather',
name='observation_name',
),
migrations.RemoveField(
model_name='regionalweather',
name='observation_text_summary',
),
migrations.RemoveField(
model_name='regionalweather',
name='observation_utc_offset',
),
migrations.RemoveField(
model_name='regionalweather',
name='observation_zone',
),
migrations.AddField(
model_name='regionalweather',
name='forecast_issued',
field=models.DateTimeField(null=True),
),
migrations.AddField(
model_name='regionalweather',
name='observed',
field=models.DateTimeField(null=True),
),
migrations.AddField(
model_name='regionalweather',
name='station',
field=models.CharField(max_length=3, null=True),
),
migrations.AddField(
model_name='regionalweather',
name='sunrise',
field=models.DateTimeField(null=True),
),
migrations.AddField(
model_name='regionalweather',
name='sunset',
field=models.DateTimeField(null=True),
),
migrations.AddField(
model_name='regionalweather',
name='warnings',
field=models.JSONField(null=True),
),
]
24 changes: 16 additions & 8 deletions src/backend/apps/weather/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,33 @@


class RegionalWeather(BaseModel):
location = models.PointField(null=True)
""" Weather reports and forecasts from Environment Canada """

code = models.CharField(max_length=10, null=True)
location_latitude = models.CharField(max_length=10, null=True)
location_longitude = models.CharField(max_length=10, null=True)
station = models.CharField(max_length=3, null=True)
name = models.CharField(max_length=100, null=True)
region = models.CharField(max_length=255, null=True)

observation_name = models.CharField(max_length=50, null=True)
observation_zone = models.CharField(max_length=10, null=True)
observation_utc_offset = models.IntegerField(null=True)
observation_text_summary = models.CharField(max_length=255, null=True)
location_latitude = models.CharField(max_length=10, null=True)
location_longitude = models.CharField(max_length=10, null=True)
location = models.PointField(null=True)

observed = models.DateTimeField(null=True) # current conditions
forecast_issued = models.DateTimeField(null=True)
sunrise = models.DateTimeField(null=True)
sunset = models.DateTimeField(null=True)

conditions = models.JSONField(null=True)
forecast_group = models.JSONField(null=True)
hourly_forecast_group = models.JSONField(null=True)

warnings = models.JSONField(null=True)

def get_forecasts(self):
return self.forecast_group.get('Forecasts', [])

def __str__(self):
return f"Regional Forecast for {self.pk}"
return f"Regional Forecast for {self.code} ({self.station})"

def save(self, *args, **kwargs):
latitude, longitude = self.convert_coordinates(str(self.location_latitude), str(self.location_longitude))
Expand All @@ -44,6 +50,8 @@ def convert_coordinates(self, latitude_str, longitude_str):


class CurrentWeather(BaseModel):
""" Weather reports from MOTI sites """

location = models.PointField(null=True)
weather_station_name = models.CharField(max_length=100)
elevation = models.IntegerField(null=True)
Expand Down
18 changes: 17 additions & 1 deletion src/backend/apps/weather/serializers.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
from datetime import datetime
from zoneinfo import ZoneInfo

from apps.weather.models import CurrentWeather, RegionalWeather
from rest_framework import serializers


tz = ZoneInfo("America/Vancouver")


class RegionalWeatherSerializer(serializers.ModelSerializer):

class Meta:
model = RegionalWeather
exclude = ['location_latitude', 'location_longitude']
fields = ['location',
'conditions',
'name',
'station',
'observed',
'forecast_issued',
'sunrise',
'sunset',
'warnings',
]


# Current Weather serializer
Expand Down
28 changes: 15 additions & 13 deletions src/backend/apps/weather/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,24 @@
logger = logging.getLogger(__name__)


def populate_regional_weather_from_data(new_regional_weather_data):
code = new_regional_weather_data.get('code')
def populate_regional_weather_from_data(new_data):
code = new_data.get('code')
existing_record = RegionalWeather.objects.filter(code=code).first()
data = {
'code': code,
'location_latitude': new_regional_weather_data.get('location_latitude'),
'location_longitude': new_regional_weather_data.get('location_longitude'),
'name': new_regional_weather_data.get('name'),
'region': new_regional_weather_data.get('region'),
'observation_name': new_regional_weather_data.get('observation_name'),
'observation_zone': new_regional_weather_data.get('observation_zone'),
'observation_utc_offset': new_regional_weather_data.get('observation_utc_offset'),
'observation_text_summary': new_regional_weather_data.get('observation_text_summary'),
'conditions': new_regional_weather_data.get('conditions'),
'forecast_group': new_regional_weather_data.get('forecast_group'),
'hourly_forecast_group': new_regional_weather_data.get('hourly_forecast_group'),
'location_latitude': new_data.get('location_latitude'),
'location_longitude': new_data.get('location_longitude'),
'name': new_data.get('name'),
'region': new_data.get('region'),
'conditions': new_data.get('conditions'),
'forecast_group': new_data.get('forecast_group'),
'hourly_forecast_group': new_data.get('hourly_forecast_group'),
'station': new_data.get('station'),
'observed': new_data.get('observed'),
'forecast_issued': new_data.get('forecast_issued'),
'sunrise': new_data.get('sunrise'),
'sunset': new_data.get('sunset'),
'warnings': new_data.get('warnings'),
}

if existing_record:
Expand Down
7 changes: 6 additions & 1 deletion src/frontend/src/Components/Filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -320,12 +320,17 @@ export default function Filters(props) {
<span className="tooltip-info">?</span>
</OverlayTrigger>
</div>

<div className={'filter-item filter-item--weather' + (weather ? ' checked' : '') + (disableFeatures ? ' disabled' : '')}>
<input
type="checkbox"
name="weather"
id="filter--weather"
onChange={e => {toggleHandler('weather', e.target.checked); setWeather(!weather)}}
onChange={e => {
toggleHandler('weather', e.target.checked);
toggleHandler('regional', e.target.checked);
setWeather(!weather)}
}
defaultChecked={mapContext.visible_layers.weather}
disabled={disableFeatures}
/>
Expand Down
Loading

0 comments on commit c070bce

Please sign in to comment.