From 0d828fcced3d141e1a2b556f08cd770e8f8b3d97 Mon Sep 17 00:00:00 2001 From: Matthew McFarland Date: Thu, 10 Mar 2016 15:52:45 -0500 Subject: [PATCH 01/20] Add stream network to overlay layers * Configure app & windshaft to serve and style nhdflowlines * Consolidate generation of overlay list * Renamed "stream slider" streams to be DRB specific * Adds new category type to overlay layers DRB Streams will probably be removed in the near future as the feature is deprecated. --- src/mmw/apps/home/views.py | 3 +- src/mmw/js/src/core/layerControl.js | 24 ++++++++++++-- src/mmw/js/src/core/streamSliderControl.js | 2 +- src/mmw/js/src/core/views.js | 37 ++++++++++------------ src/mmw/mmw/settings/layer_settings.py | 15 +++++++-- src/tiler/server.js | 3 +- src/tiler/styles.mss | 7 ++-- 7 files changed, 59 insertions(+), 32 deletions(-) diff --git a/src/mmw/apps/home/views.py b/src/mmw/apps/home/views.py index 5614c37c2..aa3132297 100644 --- a/src/mmw/apps/home/views.py +++ b/src/mmw/apps/home/views.py @@ -120,10 +120,11 @@ def get_client_settings(request): 'client_settings': json.dumps({ EMBED_FLAG: request.session.get(EMBED_FLAG, False), 'base_layers': get_layer_config(['basemap']), - 'stream_layers': get_layer_config(['stream']), + 'stream_drb_layers': get_layer_config(['stream_drb']), 'boundary_layers': get_layer_config(['boundary']), 'vector_layers': get_layer_config(['vector', 'overlay']), 'raster_layers': get_layer_config(['raster', 'overlay']), + 'stream_layers': get_layer_config(['stream', 'overlay']), 'draw_tools': settings.DRAW_TOOLS, 'map_controls': settings.MAP_CONTROLS, 'google_maps_api_key': settings.GOOGLE_MAPS_API_KEY, diff --git a/src/mmw/js/src/core/layerControl.js b/src/mmw/js/src/core/layerControl.js index 7f6d16d70..6aadd882c 100644 --- a/src/mmw/js/src/core/layerControl.js +++ b/src/mmw/js/src/core/layerControl.js @@ -138,14 +138,22 @@ module.exports = L.Control.Layers.extend({ input.checked = true; } - if (_.contains(['raster', 'vector'], obj.overlayType)) { + if (_.contains(['stream', 'raster', 'vector'], obj.overlayType)) { var subcontainer = document.getElementById('overlay-subclass-' + obj.overlayType); if (subcontainer === null) { subcontainer = document.createElement('div'); subcontainer.id = 'overlay-subclass-' + obj.overlayType; this._overlaysList.appendChild(subcontainer); - var title = obj.overlayType === 'vector' ? 'Boundary' : 'Coverage'; + var title; + if (obj.overlayType === 'vector') { + title = 'Boundary'; + } else if (obj.overlayType === 'raster') { + title = 'Coverage'; + } else if (obj.overlayType === 'stream') { + title = 'Streams'; + } + var textNode = document.createElement('h4'); textNode.innerHTML = title; subcontainer.appendChild(textNode); @@ -174,7 +182,17 @@ module.exports = L.Control.Layers.extend({ }; if (tabType === 'overlay') { - this._layers[id].overlayType = layer.options.vector ? 'vector' : 'raster'; + var overlayType; + if (layer.options.vector) { + overlayType = 'vector'; + } else if (layer.options.raster) { + overlayType = 'raster'; + } else if (layer.options.stream) { + overlayType = 'stream'; + } + + this._layers[id].overlayType = overlayType; + } else if (tabType === 'observation') { this._layers[id].overlayType = tabType; } diff --git a/src/mmw/js/src/core/streamSliderControl.js b/src/mmw/js/src/core/streamSliderControl.js index e760d4e52..cfc3e52cb 100644 --- a/src/mmw/js/src/core/streamSliderControl.js +++ b/src/mmw/js/src/core/streamSliderControl.js @@ -58,7 +58,7 @@ var StreamSliderView = Marionette.ItemView.extend({ initialize: function(options) { this.streamFeatures = options.streamFeatures; - this.streamLayers = settings.get('stream_layers'); + this.streamLayers = settings.get('stream_drb_layers'); }, onShow: function() { diff --git a/src/mmw/js/src/core/views.js b/src/mmw/js/src/core/views.js index c4b0d1eef..d8b9d2de0 100644 --- a/src/mmw/js/src/core/views.js +++ b/src/mmw/js/src/core/views.js @@ -295,26 +295,23 @@ var MapView = Marionette.ItemView.extend({ }, prepareOverlayLayers: function() { - var nullVectorLayer = { - display: 'nullVector', - vector: true, - empty: true - }, - nullRasterLayer = { - display: 'nullRaster', - raster: true, - empty: true - }, - vectorOverlayLayers = settings.get('vector_layers'), - rasterOverlayLayers = settings.get('raster_layers'); - - vectorOverlayLayers = !_.isEmpty(vectorOverlayLayers) ? - [nullVectorLayer].concat(vectorOverlayLayers) : []; - - rasterOverlayLayers = !_.isEmpty(rasterOverlayLayers) ? - [nullRasterLayer].concat(rasterOverlayLayers) : []; - - return vectorOverlayLayers.concat(rasterOverlayLayers); + // For each type of overlay, create an empty "layer" used for + // the "None" option and order the actual defined layer configs + // after it. + var overlayTypes = ['stream', 'vector', 'raster'], + overlayLayers = _.map(overlayTypes, function(type) { + var nullLayer = { + display: 'null' + type, + empty: true + }; + + nullLayer[type] = true; + + var layers = settings.get(type + '_layers'); + return [nullLayer].concat(layers); + }); + + return _.flatten(overlayLayers); }, setupGeoLocation: function(maxAge) { diff --git a/src/mmw/mmw/settings/layer_settings.py b/src/mmw/mmw/settings/layer_settings.py index b6d116cae..28a917165 100644 --- a/src/mmw/mmw/settings/layer_settings.py +++ b/src/mmw/mmw/settings/layer_settings.py @@ -109,6 +109,15 @@ 'overlay': True, 'minZoom': 9, }, + { + 'code': 'stream', + 'display': 'National Stream Network', + 'table_name': 'nhdflowline', + 'boundary': False, + 'stream': True, + 'overlay': True, + 'minZoom': 10 + }, { 'display': 'National Land Cover Database', 'short_display': 'NLCD', @@ -144,19 +153,19 @@ 'code': 'stream-low', 'display': 'Low-Res', 'table_name': 'deldem4net100r', - 'stream': True, + 'stream_drb': True, }, { 'code': 'stream-medium', 'display': 'Medium-Res', 'table_name': 'deldem4net50r', - 'stream': True, + 'stream_drb': True, }, { 'code': 'stream-high', 'display': 'High-Res', 'table_name': 'deldem4net20r', - 'stream': True, + 'stream_drb': True, }, { 'type': 'mapbox', diff --git a/src/tiler/server.js b/src/tiler/server.js index 3237fc7ba..dd5ad6e2c 100644 --- a/src/tiler/server.js +++ b/src/tiler/server.js @@ -35,7 +35,8 @@ var interactivity = { huc12: 'boundary_huc12', 'stream-low': 'drb_stream_network_100', 'stream-medium': 'drb_stream_network_50', - 'stream-high': 'drb_stream_network_20' + 'stream-high': 'drb_stream_network_20', + stream: 'nhdflowline' }, shouldCacheRequest = function(req) { // Caching can happen if the bucket to write to is defined diff --git a/src/tiler/styles.mss b/src/tiler/styles.mss index a2140f4f3..dbe5751ec 100644 --- a/src/tiler/styles.mss +++ b/src/tiler/styles.mss @@ -20,13 +20,14 @@ } } -@zoomBase: 0.3; +@zoomBase: 0.5; #drb_stream_network_20, #drb_stream_network_50, -#drb_stream_network_100 +#drb_stream_network_100, +#nhdflowline { - line-color: #78CAE6; + line-color: #1562A9; [zoom<=10] { line-width: 1.0 * @zoomBase; } [zoom=11] { line-width: 2.0 * @zoomBase; } [zoom=12] { line-width: 4.0 * @zoomBase; } From 043b6c6f6d2557809d720ce272ddb93091946137 Mon Sep 17 00:00:00 2001 From: Hector Castro Date: Thu, 10 Mar 2016 15:55:31 -0500 Subject: [PATCH 02/20] Use retires with exponential backoff when choosing workers When the call to ping available workers is made, if no workers come back and the string of calls results in an AttributeError, retry the call for workers again. The current parameters should retry after: - 0.5s - 1s (2 x 0.5) - 2s (2 x 1), and then fail --- src/mmw/apps/modeling/views.py | 13 ++++++++++++- src/mmw/requirements/base.txt | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/mmw/apps/modeling/views.py b/src/mmw/apps/modeling/views.py index cb9335cd7..9b146063f 100644 --- a/src/mmw/apps/modeling/views.py +++ b/src/mmw/apps/modeling/views.py @@ -20,6 +20,8 @@ import celery from celery import chain +from retry import retry + from apps.core.models import Job from apps.core.tasks import save_job_error, save_job_result from apps.modeling import tasks @@ -235,8 +237,17 @@ def choose_worker(): def predicate(worker_name): return settings.STACK_COLOR in worker_name or 'debug' in worker_name + @retry(Exception, delay=0.5, backoff=2, tries=3) + def get_list_of_workers(): + workers = celery.current_app.control.inspect().ping() + + if workers is None: + raise Exception('Unable to receive a PONG from any workers') + + return workers.keys() + workers = filter(predicate, - celery.current_app.control.inspect().ping().keys()) + get_list_of_workers()) return random.choice(workers) diff --git a/src/mmw/requirements/base.txt b/src/mmw/requirements/base.txt index 46c7d77d5..f455b8034 100644 --- a/src/mmw/requirements/base.txt +++ b/src/mmw/requirements/base.txt @@ -12,3 +12,4 @@ djangorestframework-gis==0.8.2 tr55==1.1.3 requests==2.9.1 rollbar>=0.11.0,<=0.12.0 +retry==0.9.1 From ecaa03c8fc7c78815ec61fac90e1fb6a8c1c8284 Mon Sep 17 00:00:00 2001 From: Terence Tuhinanshu Date: Fri, 11 Mar 2016 12:40:17 -0500 Subject: [PATCH 03/20] Fix precipitation slider in IE IE listens to the `change` event of the slider, which is fired on every drag. All other browsers support `input` event, which is fired when the user stops dragging. By supporting `change` conditionally we ensure the proper functionality in all cases. --- src/mmw/js/src/main_water_balance.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/mmw/js/src/main_water_balance.js b/src/mmw/js/src/main_water_balance.js index ef1d22417..77caca923 100644 --- a/src/mmw/js/src/main_water_balance.js +++ b/src/mmw/js/src/main_water_balance.js @@ -113,7 +113,12 @@ var initialize = function(model) { } // Wire up events - $precipSlider.on('input', recalculate); + var isIE = ("ActiveXObject" in window); + if (isIE) { + $precipSlider.on('change', recalculate); + } else { + $precipSlider.on('input', recalculate); + } $('a[data-toggle="tab"]').on('shown.bs.tab', recalculate); // Trigger the first time page loads From 4eca4beb6fb6ab467aa397569a61ab971bc8672c Mon Sep 17 00:00:00 2001 From: Terence Tuhinanshu Date: Fri, 11 Mar 2016 17:13:05 -0500 Subject: [PATCH 04/20] Fix precipitation label wrapping issue The precipitation label was previously wrapping onto the precipitation slider. By ensuring that there is no float, and eliminating the extra line-break, we address the overflow. --- src/mmw/apps/water_balance/templates/home_page/index.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mmw/apps/water_balance/templates/home_page/index.html b/src/mmw/apps/water_balance/templates/home_page/index.html index 939b3c3ce..c914a8d08 100644 --- a/src/mmw/apps/water_balance/templates/home_page/index.html +++ b/src/mmw/apps/water_balance/templates/home_page/index.html @@ -187,8 +187,7 @@

0.0 cm