diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..6deafc2 --- /dev/null +++ b/.flake8 @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 120 diff --git a/install.yml b/install.yml index 16e908e..78ded9c 100644 --- a/install.yml +++ b/install.yml @@ -1,5 +1,7 @@ # This file should be committed to your app code. version: 1.0 +# This should be greater or equal to your tethys-platform in your environment +tethys_version: ">=4.0.0" # This should match the app - package name in your setup.py name: ggst @@ -10,11 +12,7 @@ requirements: channels: - conda-forge packages: - - geopandas - - shapely - - xarray - rioxarray - - netCDF4 - geopandas pip: - area diff --git a/tethysapp/ggst/api.py b/tethysapp/ggst/api.py index 9e73eaa..a3a127b 100644 --- a/tethysapp/ggst/api.py +++ b/tethysapp/ggst/api.py @@ -11,8 +11,11 @@ storage_options, region_api_ts, ) +from tethys_sdk.routing import controller + +@controller(name="subset-region-zipfile", url="ggst/api/subsetRegionZipfile/") @api_view(["POST"]) @authentication_classes( ( @@ -48,6 +51,8 @@ def subset_region_zip(request): return JsonResponse({"error": f"Error processing request: {e}"}) + +@controller(name="region-zip-timeseries", url="ggst/api/zipRegionTimeseries/") @api_view(["POST"]) @authentication_classes( ( @@ -84,6 +89,7 @@ def region_zip_timeseries(request): @api_view(["GET"]) +@controller(name="get-region-timeseries", url="ggst/api/getRegionTimeseries/") @authentication_classes( ( TokenAuthentication, @@ -117,7 +123,8 @@ def subset_region_api(request): return JsonResponse(json_obj) - +@api_view(["GET"]) +@controller(name="get-storage-options", url="ggst/api/getStorageOptions/") def api_get_storage_options(request): return_obj = {} @@ -126,7 +133,8 @@ def api_get_storage_options(request): return_obj["storage_options"] = options return JsonResponse(return_obj) - +@api_view(["GET"]) +@controller(name="get-point-values", url="ggst/api/getPointValues/") def api_get_point_values(request): return_obj = {} diff --git a/tethysapp/ggst/app.py b/tethysapp/ggst/app.py index bfcf47f..4214e5a 100644 --- a/tethysapp/ggst/app.py +++ b/tethysapp/ggst/app.py @@ -1,9 +1,5 @@ -from tethys_sdk.base import TethysAppBase, url_map_maker -from tethys_sdk.app_settings import ( - PersistentStoreDatabaseSetting, - PersistentStoreConnectionSetting, - CustomSetting, -) +from tethys_sdk.base import TethysAppBase +from tethys_sdk.app_settings import (CustomSetting) class Ggst(TethysAppBase): @@ -12,7 +8,7 @@ class Ggst(TethysAppBase): """ name = "Grace Groundwater Subsetting Tool" - index = "ggst:home" + index = "home" icon = "ggst/images/logo.jpg" package = "ggst" root_url = "ggst" @@ -22,122 +18,7 @@ class Ggst(TethysAppBase): enable_feedback = False feedback_emails = [] - def url_maps(self): - """ - Add controllers - """ - UrlMap = url_map_maker(self.root_url) - - url_maps = ( - UrlMap(name="home", url="ggst", controller="ggst.controllers.home"), - UrlMap( - name="global-map", - url="ggst/global-map", - controller="ggst.controllers.global_map", - ), - UrlMap( - name="global-map-ts", - url="ggst/global-map/get-plot-global", - controller="ggst.controllers_ajax.get_global_plot", - ), - UrlMap( - name="region-map", - url="ggst/region-map", - controller="ggst.controllers.region_map", - ), - UrlMap( - name="update-global-files", - url="ggst/update-global-files", - controller="ggst.controllers.update_global_files", - ), - UrlMap( - name="update-global-files-trigger", - url="ggst/update-global-files/update", - controller="ggst.controllers_ajax.global_files_update", - ), - UrlMap( - name="region-map-plot", - url="ggst/region-map/get-plot-region", - controller="ggst.controllers_ajax.get_region_plot", - ), - UrlMap( - name="region-map-center", - url="ggst/region-map/map-center", - controller="ggst.controllers_ajax.get_region_center", - ), - UrlMap( - name="region-map-range", - url="ggst/region-map/range", - controller="ggst.controllers_ajax.get_legend_range", - ), - UrlMap( - name="add-region", - url="ggst/add-region", - controller="ggst.controllers.add_region", - ), - UrlMap( - name="add-region-submit", - url="ggst/add-region/submit", - controller="ggst.controllers_ajax.region_add", - ), - UrlMap( - name="delete-region", - url="ggst/delete-region", - controller="ggst.controllers.delete_region", - ), - UrlMap( - name="submit-delete-region", - url="ggst/delete-region/delete", - controller="ggst.controllers_ajax.region_delete", - ), - UrlMap( - name="subset_region", - url="ggst/api/subsetRegion", - controller="ggst.api.subset_region_api", - ), - UrlMap( - name="subset_region_zip", - url="ggst/api/subsetRegionZipfile", - controller="ggst.api.subset_region_zip", - ), - UrlMap( - name="global_time_step", - url="ggst/global-map/timestep", - controller="ggst.controllers_ajax.get_time_step_options", - ), - UrlMap( - name="region_time_step", - url="ggst/region-map/timestep", - controller="ggst.controllers_ajax.get_time_step_options", - ), - UrlMap( - name="region_geojson", - url="ggst/region-map/geojson", - controller="ggst.controllers_ajax.get_region_geojson", - ), - UrlMap( - name="regional_time_series", - url="ggst/region-map/get-region-summary", - controller="ggst.controllers_ajax.get_region_chart", - ), - UrlMap( - name="api_get_point_values", - url="ggst/api/getPointValues", - controller="ggst.api.api_get_point_values", - ), - UrlMap( - name="api_get_storage_options", - url="ggst/api/getStorageOptions", - controller="ggst.api.api_get_storage_options", - ), - UrlMap( - name="api_get_region_timeseries", - url="ggst/api/getRegionTimeseries", - controller="ggst.api.region_zip_timeseries", - ), - ) - - return url_maps + controller_modules = ['controllers_ajax', "api"] def custom_settings(self): custom_settings = ( diff --git a/tethysapp/ggst/controllers.py b/tethysapp/ggst/controllers.py index ea23b50..3d74280 100644 --- a/tethysapp/ggst/controllers.py +++ b/tethysapp/ggst/controllers.py @@ -2,6 +2,7 @@ from django.contrib.auth.decorators import user_passes_test from django.shortcuts import render, reverse, redirect from tethys_sdk.gizmos import TextInput, Button +from tethys_sdk.routing import controller from .app import Ggst as app from .utils import ( @@ -18,6 +19,7 @@ job_manager = app.get_job_manager() +@controller def home(request): """ Controller for the app home page. @@ -29,6 +31,7 @@ def home(request): return render(request, "ggst/home.html", context) +@controller(name='global-map', url='ggst/global-map') def global_map(request): """ Controller for the Global Map page. @@ -48,6 +51,7 @@ def global_map(request): return render(request, "ggst/global_map.html", context) +@controller(name='region-map', url='ggst/region-map') def region_map(request): """ Controller for the Region Map home page. @@ -81,18 +85,19 @@ def region_map(request): @user_passes_test(user_permission_test) +@controller(name='add-region', url='ggst/add-region') def add_region(request): region_name_input = TextInput( display_text="Region Display Name", name="region-name-input", placeholder="e.g.: Utah", - icon_append="glyphicon glyphicon-home", + icon_append="bi bi-house-door", ) # Input for the Region Display Name add_button = Button( display_text="Add Region", - icon="glyphicon glyphicon-plus", + icon="bi bi-plus", style="success", name="submit-add-region", attributes={"id": "submit-add-region"}, @@ -104,6 +109,7 @@ def add_region(request): @user_passes_test(user_permission_test) +@controller(name='delete-region', url='ggst/delete-region') def delete_region(request): region_select = get_region_select() @@ -111,7 +117,7 @@ def delete_region(request): delete_button = Button( display_text="Delete Region", - icon="glyphicon glyphicon-minus", + icon="bi bi-dash", style="danger", name="submit-delete-region", attributes={"id": "submit-delete-region"}, @@ -126,13 +132,14 @@ def delete_region(request): return render(request, "ggst/delete_region.html", context) +@controller(name='update-global-files', url='ggst/update-global-files') def update_global_files(request): """ Controller for the Update Global Files page. """ update_button = Button( display_text="Update Files", - icon="glyphicon glyphicon-plus", + icon="bi bi-plus", style="success", name="submit-update-files", attributes={"id": "submit-update-files"}, diff --git a/tethysapp/ggst/controllers_ajax.py b/tethysapp/ggst/controllers_ajax.py index 106cc35..9b899a2 100644 --- a/tethysapp/ggst/controllers_ajax.py +++ b/tethysapp/ggst/controllers_ajax.py @@ -2,6 +2,7 @@ from django.contrib.auth.decorators import user_passes_test from django.http import JsonResponse, HttpResponseRedirect +from tethys_sdk.routing import controller from .utils import ( delete_region_dir, @@ -18,9 +19,13 @@ @user_passes_test(user_permission_test) +@controller(name="add-region-submit", url="ggst/add-region/submit") def region_add(request): - if request.is_ajax() and request.method == "POST": + if ( + request.headers.get("x-requested-with") == "XMLHttpRequest" + and request.method == "POST" + ): try: info = request.POST @@ -35,9 +40,13 @@ def region_add(request): @user_passes_test(user_permission_test) +@controller(name="submit-delete-region", url="ggst/delete-region/delete") def region_delete(request): - if request.is_ajax() and request.method == "POST": + if ( + request.headers.get("x-requested-with") == "XMLHttpRequest" + and request.method == "POST" + ): try: info = request.POST @@ -53,14 +62,22 @@ def region_delete(request): @user_passes_test(user_permission_test) +@controller(name="update-global-files-trigger", url="ggst/update-global-files/update") def global_files_update(request): - if request.is_ajax() and request.method == "POST": + if ( + request.headers.get("x-requested-with") == "XMLHttpRequest" + and request.method == "POST" + ): trigger_global_process() return HttpResponseRedirect("../") -def get_time_step_options(request): - if request.is_ajax() and request.method == "POST": +@controller(name="map_time_step", url="ggst/{map_type}/timestep") +def get_time_step_options(request, map_type): + if ( + request.headers.get("x-requested-with") == "XMLHttpRequest" + and request.method == "POST" + ): try: return_obj = {} info = request.POST @@ -73,9 +90,13 @@ def get_time_step_options(request): return JsonResponse({"error": str(e)}) +@controller(name="global-map-ts", url="ggst/global-map/get-plot-global") def get_global_plot(request): - if request.is_ajax() and request.method == "POST": + if ( + request.headers.get("x-requested-with") == "XMLHttpRequest" + and request.method == "POST" + ): try: return_obj = {} info = request.POST @@ -95,9 +116,13 @@ def get_global_plot(request): return JsonResponse({"error": str(e)}) +@controller(name="region-map-plot", url="ggst/region-map/get-plot-region") def get_region_plot(request): - if request.is_ajax() and request.method == "POST": + if ( + request.headers.get("x-requested-with") == "XMLHttpRequest" + and request.method == "POST" + ): # try: return_obj = {} info = request.POST @@ -120,8 +145,12 @@ def get_region_plot(request): return JsonResponse({"error": f"Error processing request: {e}"}) +@controller(name="regional_time_series", url="ggst/region-map/get-region-summary") def get_region_chart(request): - if request.is_ajax() and request.method == "POST": + if ( + request.headers.get("x-requested-with") == "XMLHttpRequest" + and request.method == "POST" + ): try: return_obj = {} info = request.POST @@ -140,8 +169,12 @@ def get_region_chart(request): return JsonResponse({"error": f"Error processing request: {e}"}) +@controller(name="region-map-center", url="ggst/region-map/map-center") def get_region_center(request): - if request.is_ajax() and request.method == "POST": + if ( + request.headers.get("x-requested-with") == "XMLHttpRequest" + and request.method == "POST" + ): try: return_obj = {} info = request.POST @@ -158,8 +191,12 @@ def get_region_center(request): return JsonResponse({"error": str(e)}) +@controller(name="region-map-range", url="ggst/region-map/range") def get_legend_range(request): - if request.is_ajax() and request.method == "POST": + if ( + request.headers.get("x-requested-with") == "XMLHttpRequest" + and request.method == "POST" + ): try: return_obj = {} info = request.POST @@ -174,8 +211,12 @@ def get_legend_range(request): return JsonResponse({"error": str(e)}) +@controller(name="region_geojson", url="ggst/region-map/geojson") def get_region_geojson(request): - if request.is_ajax() and request.method == "POST": + if ( + request.headers.get("x-requested-with") == "XMLHttpRequest" + and request.method == "POST" + ): try: return_obj = {} info = request.POST diff --git a/tethysapp/ggst/public/css/region_map.css b/tethysapp/ggst/public/css/region_map.css index 0a88889..ee1fbea 100644 --- a/tethysapp/ggst/public/css/region_map.css +++ b/tethysapp/ggst/public/css/region_map.css @@ -119,9 +119,6 @@ margin:0; height: 100%; } -#app-content-wrapper #app-content{ - -} .info.legend { background-color: #888888; diff --git a/tethysapp/ggst/public/js/add_region.js b/tethysapp/ggst/public/js/add_region.js index f75c047..c6aaf4d 100644 --- a/tethysapp/ggst/public/js/add_region.js +++ b/tethysapp/ggst/public/js/add_region.js @@ -46,9 +46,9 @@ var LIBRARY_OBJECT = (function() { //Reset the alerts if everything is going well reset_alert = function(){ - $("#message").addClass('hidden'); + $("#message").addClass('d-none'); $("#message").empty() - .addClass('hidden') + .addClass('d-none') .removeClass('alert-success') .removeClass('alert-info') .removeClass('alert-warning') diff --git a/tethysapp/ggst/public/js/delete_region.js b/tethysapp/ggst/public/js/delete_region.js index 4effca9..a620ad5 100644 --- a/tethysapp/ggst/public/js/delete_region.js +++ b/tethysapp/ggst/public/js/delete_region.js @@ -42,9 +42,9 @@ var LIBRARY_OBJECT = (function() { //Reset the alerts if everything is going well reset_alert = function(){ - $("#message").addClass('hidden'); + $("#message").addClass('d-none'); $("#message").empty() - .addClass('hidden') + .addClass('d-none') .removeClass('alert-success') .removeClass('alert-info') .removeClass('alert-warning') diff --git a/tethysapp/ggst/public/js/global_map.js b/tethysapp/ggst/public/js/global_map.js index 341af42..84f2947 100644 --- a/tethysapp/ggst/public/js/global_map.js +++ b/tethysapp/ggst/public/js/global_map.js @@ -83,9 +83,9 @@ var LIBRARY_OBJECT = (function() { }; //Reset the alerts if everything is going well reset_alert = function(){ - $("#message").addClass('hidden'); + $("#message").addClass('d-none'); $("#message").empty() - .addClass('hidden') + .addClass('d-none') .removeClass('alert-success') .removeClass('alert-info') .removeClass('alert-warning') @@ -301,8 +301,8 @@ var LIBRARY_OBJECT = (function() { add_wms = function(layer_val, storage_type, style, mode_type, range_min, range_max){ // map.removeLayer(tdWmsLayer); // map.removeLayer(contourTimeLayer); - $('.lcontrol').removeClass('hidden'); - $('.leaflet-bar-timecontrol').removeClass('hidden'); + $('.lcontrol').removeClass('d-none'); + $('.leaflet-bar-timecontrol').removeClass('d-none'); graceGroup.clearLayers(); contourGroup.clearLayers(); let wmsUrl = wms_url + 'GRC_' + storage_type + '.nc'; @@ -315,7 +315,7 @@ var LIBRARY_OBJECT = (function() { layers: 'lwe_thickness', format: 'image/png', transparent: true, - styles: 'contour/'+style, + styles: 'contours', crs: L.CRS.EPSG4326, opacity: '1.0', colorscalerange: [range_min, range_max], @@ -346,7 +346,7 @@ var LIBRARY_OBJECT = (function() { layers: 'lwe_thickness', format: 'image/png', transparent: true, - styles: 'boxfill/'+style, + styles: 'raster/'+style, crs: L.CRS.EPSG4326, opacity: opacity, colorscalerange: [range_min, range_max], @@ -379,7 +379,7 @@ var LIBRARY_OBJECT = (function() { var src = wmsUrl + "?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetLegendGraphic&LAYER=lwe_thickness"+ - "&colorscalerange="+range_min+","+range_max+"&PALETTE="+style+"&transparent=TRUE"; + "&colorscalerange="+range_min+","+range_max+"&STYLES=raster/"+style+"&transparent=FALSE&WIDTH=50&HEIGHT=300"; // var src = wmsUrl + "?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetLegendGraphic&LAYER=lwe_thickness&PALETTE=boxfill/"+style+"&transparent=TRUE"; $("#legend-image").attr("src", src); map.timeDimension.setCurrentTime(layer_arr[1]); @@ -523,8 +523,8 @@ var LIBRARY_OBJECT = (function() { }); })); // updateChart(); -// $loading.addClass('hidden'); - $("#chart").removeClass('hidden'); +// $loading.addClass('d-none'); + $("#chart").removeClass('d-none'); }else{ // console.log(result); console.log('error'); diff --git a/tethysapp/ggst/public/js/main.js b/tethysapp/ggst/public/js/main.js index 3bd8561..13c5a74 100644 --- a/tethysapp/ggst/public/js/main.js +++ b/tethysapp/ggst/public/js/main.js @@ -38,10 +38,10 @@ function addErrorMessage(error, div_id) { div_id_string = '#'+div_id; } $(div_id_string).html( - '' + + '' + 'Error: ' + error ) - .removeClass('hidden') + .removeClass('d-none') .removeClass('alert-success') .removeClass('alert-info') .removeClass('alert-warning') @@ -56,9 +56,9 @@ function addSuccessMessage(message, div_id) { div_id_string = '#'+div_id; } $(div_id_string).html( - '' + + '' + 'Sucess: ' + message - ).removeClass('hidden') + ).removeClass('d-none') .removeClass('alert-danger') .removeClass('alert-info') .removeClass('alert-warning') @@ -79,12 +79,12 @@ function appendErrorMessage(message, div_id, message_div_id) { $('#'+div_id).remove(); $(message_div_id_string).append( '