diff --git a/install.yml b/install.yml index ffbaf82..68d19c6 100644 --- a/install.yml +++ b/install.yml @@ -1,5 +1,5 @@ # This file should be committed to your app code. -version: 1.0 +version: 1.1 # 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 @@ -10,14 +10,18 @@ requirements: skip: false conda: channels: - - conda-forge + - conda-forge packages: - - earthengine-api - - oauth2client - - geojson - - pyshp + - earthengine-api + - oauth2client + - geojson + - pandas + - pyshp + - simplejson + - djangorestframework + pip: npm: -post: \ No newline at end of file +post: diff --git a/setup.py b/setup.py index 7f32563..b2fc626 100644 --- a/setup.py +++ b/setup.py @@ -10,8 +10,9 @@ dependencies = [] # -- Get Resource File -- # -resource_files = find_all_resource_files(app_package, TethysAppBase.package_namespace) - +resource_files = find_all_resource_files( + app_package, TethysAppBase.package_namespace +) setup( name=release_package, @@ -28,4 +29,4 @@ include_package_data=True, zip_safe=False, install_requires=dependencies, -) \ No newline at end of file +) diff --git a/tethysapp/earth_engine/app.py b/tethysapp/earth_engine/app.py index d368756..003f5b0 100644 --- a/tethysapp/earth_engine/app.py +++ b/tethysapp/earth_engine/app.py @@ -1,12 +1,11 @@ from tethys_sdk.base import TethysAppBase -class EarthEngine(TethysAppBase): +class App(TethysAppBase): """ Tethys app class for Earth Engine. """ - - name = 'Google Earth Engine Tutorial' + name = 'Earth Engine' description = '' package = 'earth_engine' # WARNING: Do not change this value index = 'home' @@ -15,4 +14,4 @@ class EarthEngine(TethysAppBase): color = '#524745' tags = '' enable_feedback = False - feedback_emails = [] \ No newline at end of file + feedback_emails = [] diff --git a/tethysapp/earth_engine/controllers/home.py b/tethysapp/earth_engine/controllers/home.py index 4509cf1..3963bcb 100644 --- a/tethysapp/earth_engine/controllers/home.py +++ b/tethysapp/earth_engine/controllers/home.py @@ -1,7 +1,8 @@ import logging -from django.shortcuts import render from tethys_sdk.routing import controller +from ..app import App + log = logging.getLogger(f'tethys.apps.{__name__}') @@ -11,7 +12,7 @@ def home(request): Controller for the app home page. """ context = {} - return render(request, 'earth_engine/home.html', context) + return App.render(request, 'home.html', context) @controller @@ -20,4 +21,4 @@ def about(request): Controller for the app about page. """ context = {} - return render(request, 'earth_engine/about.html', context) + return App.render(request, 'about.html', context) \ No newline at end of file diff --git a/tethysapp/earth_engine/controllers/rest.py b/tethysapp/earth_engine/controllers/rest.py index a1a15e0..e41c533 100644 --- a/tethysapp/earth_engine/controllers/rest.py +++ b/tethysapp/earth_engine/controllers/rest.py @@ -1,14 +1,15 @@ -import datetime as dt import logging -import geojson -from django.http import JsonResponse, HttpResponseBadRequest, HttpResponseServerError +from django.http import JsonResponse, HttpResponseBadRequest +from tethys_sdk.routing import controller from rest_framework.authentication import TokenAuthentication from rest_framework.decorators import api_view, authentication_classes -from simplejson import JSONDecodeError -from tethys_sdk.routing import controller +from ..gee.products import EE_PRODUCTS +import datetime as dt from ..helpers import compute_dates_for_product +import geojson +from simplejson import JSONDecodeError +from django.http import HttpResponseServerError from ..gee.methods import get_time_series_from_image_collection -from ..gee.products import EE_PRODUCTS log = logging.getLogger(f'tethys.apps.{__name__}') @@ -145,6 +146,8 @@ def get_time_series(request): f'The "scale" parameter must be a valid number, but "{scale_str}" was given.' ) + + # geometry bad_geometry_msg = 'The "geometry" parameter is required and must be a valid geojson string.' if not geometry_str: @@ -192,3 +195,4 @@ def get_time_series(request): } return JsonResponse(response_data) + diff --git a/tethysapp/earth_engine/controllers/viewer.py b/tethysapp/earth_engine/controllers/viewer.py index 1ebca8f..a377e84 100644 --- a/tethysapp/earth_engine/controllers/viewer.py +++ b/tethysapp/earth_engine/controllers/viewer.py @@ -4,22 +4,23 @@ from simplejson.errors import JSONDecodeError from django.http import JsonResponse, HttpResponseNotAllowed, HttpResponseRedirect -from django.shortcuts import render from tethys_sdk.routing import controller from tethys_sdk.gizmos import SelectInput, DatePicker, Button, MapView, MVView, PlotlyView, MVDraw +from ..app import App + from ..helpers import generate_figure, handle_shapefile_upload, compute_dates_for_product from ..gee.methods import get_image_collection_asset, get_time_series_from_image_collection, \ get_boundary_fc_props_for_user from ..gee.products import EE_PRODUCTS -log = logging.getLogger(f'tethys.apps.{__name__}') +log = logging.getLogger(f'tethys.apps.{__name__}') -@controller(user_workspace=True, url='viewer') -def viewer(request, user_workspace): +@controller(user_media=True, url='viewer') +def viewer(request, user_media): """ - Controller for the app viewer page. + Controller for the app home page. """ default_platform = 'modis' default_sensors = EE_PRODUCTS[default_platform] @@ -115,7 +116,7 @@ def viewer(request, user_workspace): style='outline-secondary', attributes={'id': 'load_map'} ) - + # Get bounding box from user boundary if it exists boundary_props = get_boundary_fc_props_for_user(request.user) @@ -143,7 +144,7 @@ def viewer(request, user_workspace): maxZoom=18, minZoom=2 ), - draw=MVDraw( + draw = MVDraw( controls=['Pan', 'Modify', 'Delete', 'Move', 'Point', 'Polygon', 'Box'], initial='Pan', output_format='GeoJSON' @@ -176,11 +177,10 @@ def viewer(request, user_workspace): 'data-bs-target': '#set-boundary-modal', # ID of the Set Boundary Modal } ) - # Handle Set Boundary Form set_boundary_error = '' if request.POST and request.FILES: - set_boundary_error = handle_shapefile_upload(request, user_workspace) + set_boundary_error = handle_shapefile_upload(request, user_media) if not set_boundary_error: # Redirect back to this page to clear form @@ -202,8 +202,8 @@ def viewer(request, user_workspace): 'map_view': map_view } - return render(request, 'earth_engine/viewer.html', context) + return App.render(request, 'viewer.html', context) @controller(url='viewer/get-image-collection') def get_image_collection(request): @@ -316,4 +316,6 @@ def get_time_series_plot(request): context['error'] = f'An unexpected error has occurred. Please try again.' log.exception('An unexpected error occurred.') - return render(request, 'earth_engine/plot.html', context) + print(context) + return App.render(request, 'plot.html', context) + diff --git a/tethysapp/earth_engine/gee/cloud_mask.py b/tethysapp/earth_engine/gee/cloud_mask.py index 6ffc3bf..ec8a5e9 100644 --- a/tethysapp/earth_engine/gee/cloud_mask.py +++ b/tethysapp/earth_engine/gee/cloud_mask.py @@ -10,7 +10,7 @@ def mask_l8_sr(image): cloudsBitMask = (1 << 5) # Get the pixel QA band. - qa = image.select('pixel_qa') + qa = image.select('QA_PIXEL') # Both flags should be set to zero, indicating clear conditions. mask = qa.bitwiseAnd(cloudShadowBitMask).eq(0).And(qa.bitwiseAnd(cloudsBitMask).eq(0)) @@ -21,7 +21,7 @@ def cloud_mask_l457(image): """ Cloud Mask for Landsat 7 surface reflectance. Derived From: https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LE07_C01_T1_SR """ - qa = image.select('pixel_qa') + qa = image.select('QA_PIXEL') # If the cloud bit (5) is set and the cloud confidence (7) is high # or the cloud shadow bit is set (3), then it's a bad pixel. @@ -46,4 +46,4 @@ def mask_s2_clouds(image): # Both flags should be set to zero, indicating clear conditions. mask = qa.bitwiseAnd(cloudBitMask).eq(0).And(qa.bitwiseAnd(cirrusBitMask).eq(0)) - return image.updateMask(mask).divide(10000) + return image.updateMask(mask).divide(10000) \ No newline at end of file diff --git a/tethysapp/earth_engine/gee/methods.py b/tethysapp/earth_engine/gee/methods.py index d2cb32f..667c203 100644 --- a/tethysapp/earth_engine/gee/methods.py +++ b/tethysapp/earth_engine/gee/methods.py @@ -1,13 +1,14 @@ -import math -import os import logging import ee from ee.ee_exception import EEException -import geojson -import pandas as pd -from .products import EE_PRODUCTS from . import params as gee_account +from .products import EE_PRODUCTS from . import cloud_mask as cm +import geojson +import pandas as pd +import os +import json +import math log = logging.getLogger(f'tethys.apps.{__name__}') @@ -15,20 +16,14 @@ try: credentials = ee.ServiceAccountCredentials(gee_account.service_account, gee_account.private_key) ee.Initialize(credentials) + log.info('Successfully initialized GEE using service account.') except EEException as e: - print(str(e)) + log.warning('Unable to initialize GEE using service account. If installing ignore this warning.') else: try: ee.Initialize() except EEException as e: - from oauth2client.service_account import ServiceAccountCredentials - credentials = ServiceAccountCredentials.from_p12_keyfile( - service_account_email='', - filename='', - private_key_password='notasecret', - scopes=ee.oauth.SCOPE + ' https://www.googleapis.com/auth/drive ' - ) - ee.Initialize(credentials) + log.warning('Unable to initialize GEE with local credentials. If installing ignore this warning.') def image_to_map_id(image_name, vis_params={}): @@ -44,7 +39,6 @@ def image_to_map_id(image_name, vis_params={}): except EEException: log.exception('An error occurred while attempting to retrieve the map id.') - def get_image_collection_asset(request, platform, sensor, product, date_from=None, date_to=None, reducer='median'): """ Get tile url for image collection asset. @@ -91,7 +85,6 @@ def get_image_collection_asset(request, platform, sensor, product, date_from=Non except EEException: log.exception('An error occurred while attempting to retrieve the image collection asset.') - def get_time_series_from_image_collection(platform, sensor, product, index_name, scale=30, geometry=None, date_from=None, date_to=None, reducer='median', orient='df'): """ @@ -156,8 +149,7 @@ def get_index(image): log.debug(f'Time Series: {time_series}') return time_series - - + def upload_shapefile_to_gee(user, shp_file): """ Upload a shapefile to Google Earth Engine as an asset. @@ -185,16 +177,15 @@ def upload_shapefile_to_gee(user, shp_file): features.append(ee.Feature(geojson_feature)) feature_collection = ee.FeatureCollection(features) - # Get unique folder for each user to story boundary asset user_boundary_asset_path = get_user_boundary_path(user) - + # Overwrite an existing asset with this name by deleting it first try: ee.batch.data.deleteAsset(user_boundary_asset_path) except EEException as e: # Nothing to delete, so pass - if 'Asset not found' not in str(e): + if 'Asset not found' not in str(e) and 'does not exist' not in str(e): log.exception('Encountered an unhandled EEException.') raise e @@ -207,7 +198,6 @@ def upload_shapefile_to_gee(user, shp_file): task.start() - def get_asset_dir_for_user(user): """ Get a unique asset directory for given user. @@ -250,7 +240,6 @@ def get_asset_dir_for_user(user): return user_root_dir - def get_user_boundary_path(user): """ Get a unique path for the user boundary asset. @@ -265,7 +254,6 @@ def get_user_boundary_path(user): user_boundary_asset_path = os.path.join(user_asset_dir, 'boundary') return user_boundary_asset_path - def get_boundary_fc_for_user(user): """ Get the boundary FeatureClass for the given user if it exists. @@ -288,7 +276,6 @@ def get_boundary_fc_for_user(user): return None - def get_boundary_fc_props_for_user(user): """ Get various properties of the boundary FeatureCollection. @@ -327,4 +314,4 @@ def get_boundary_fc_props_for_user(user): 'centroid': centroid.get('coordinates') } - return fc_props + return fc_props \ No newline at end of file diff --git a/tethysapp/earth_engine/gee/params.py b/tethysapp/earth_engine/gee/params.py index aa7e8d3..a6274d1 100644 --- a/tethysapp/earth_engine/gee/params.py +++ b/tethysapp/earth_engine/gee/params.py @@ -1,2 +1,4 @@ +from pathlib import Path + service_account = '' # your google service account private_key = '' # path to the json private key for the service account diff --git a/tethysapp/earth_engine/gee/products.py b/tethysapp/earth_engine/gee/products.py index b3cb5f5..6641c4a 100644 --- a/tethysapp/earth_engine/gee/products.py +++ b/tethysapp/earth_engine/gee/products.py @@ -3,7 +3,7 @@ 'terra': { 'snow': { 'display': 'Snow Cover Daily Global 500m', - 'collection': 'MODIS/006/MOD10A1', + 'collection': 'MODIS/061/MOD10A1', 'index': 'NDSI_Snow_Cover', 'vis_params': { 'min': 0.0, @@ -15,7 +15,7 @@ }, 'temperature': { 'display': 'Land Surface Temperature and Emissivity Daily Global 1km', - 'collection': 'MODIS/006/MOD11A1', + 'collection': 'MODIS/061/MOD11A1', 'index': 'LST_Day_1km', 'vis_params': { 'min': 13000.0, @@ -98,91 +98,63 @@ } }, 'landsat': { - '7': { + '8': { 'surface': { 'display': 'Surface Reflectance', - 'collection': 'LANDSAT/LE07/C01/T1_SR', + 'collection': 'LANDSAT/LC08/C02/T1_L2', 'index': None, 'vis_params': { - 'bands': ['B3', 'B2', 'B1'], + 'bands': ['SR_B4', 'SR_B3', 'SR_B2'], 'min': 0, 'max': 3000, 'gamma': 1.4, }, - 'cloud_mask': 'cloud_mask_l457', - 'start_date': '1999-01-01', - 'end_date': None # to present - }, - 'evi': { - 'display': '8-day Enhanced Vegetation Index (EVI)', - 'collection': 'LANDSAT/LE07/C01/T1_8DAY_EVI', - 'index': 'EVI', - 'vis_params': { - 'min': 0.0, - 'max': 1.0, - 'palette': [ - 'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901', - '66A000', '529400', '3E8601', '207401', '056201', '004C00', '023B01', - '012E01', '011D01', '011301' - ], - }, - 'start_date': '1999-01-01', + 'cloud_mask': 'mask_l8_sr', + 'start_date': '2013-04-01', 'end_date': None # to present }, - 'ndwi': { - 'display': '8-day Normalized Difference Water Index (NDWI)', - 'collection': 'LANDSAT/LE07/C01/T1_8DAY_NDWI', - 'index': 'NDWI', + 'toa': { + 'display': 'Top-of-Atmosphere(TOA) Reflectance', + 'collection': 'LANDSAT/LC08/C02/T1_TOA', + 'index': None, 'vis_params': { - 'min': 0.0, - 'max': 1.0, - 'palette': ['0000ff', '00ffff', 'ffff00', 'ff0000', 'ffffff'], + 'bands': ['B4', 'B3', 'B2'], + 'min': 0, + 'max': 3000, + 'gamma': 1.4, }, - 'start_date': '1999-01-01', + 'start_date': '2013-04-01', 'end_date': None # to present }, }, - '8': { + '9': { 'surface': { 'display': 'Surface Reflectance', - 'collection': 'LANDSAT/LC08/C01/T1_SR', + 'collection': 'LANDSAT/LC09/C02/T1_L2', 'index': None, 'vis_params': { - 'bands': ['B4', 'B3', 'B2'], + 'bands': ['SR_B4', 'SR_B3', 'SR_B2'], 'min': 0, 'max': 3000, 'gamma': 1.4, }, 'cloud_mask': 'mask_l8_sr', - 'start_date': '2013-04-01', + 'start_date': '2021-10-31', 'end_date': None # to present }, - 'ndvi': { - 'display': '8-day Normalized Difference Vegetation (NDVI)', - 'collection': 'LANDSAT/LC08/C01/T1_8DAY_NDVI', - 'index': 'NDVI', - 'vis_params': { - 'min': 0.0, - 'max': 1.0, - 'palette': [ - 'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901', - '66A000', '529400', '3E8601', '207401', '056201', '004C00', '023B01', - '012E01', '011D01', '011301' - ], - }, - 'start_date': '2013-04-01', - 'end_date': None # to present - }, - 'ndsi': { - 'display': '8-day Normalized Difference Snow Index (NDSI)', - 'collection': 'LANDSAT/LC08/C01/T1_8DAY_NDSI', - 'index': 'NDSI', + 'toa': { + 'display': 'Top-of-Atmosphere(TOA) Reflectance', + 'collection': 'LANDSAT/LC09/C02/T1_TOA', + 'index': None, 'vis_params': { - 'palette': ['000088', '0000FF', '8888FF', 'FFFFFF'], + 'bands': ['B4', 'B3', 'B2'], + 'min': 0, + 'max': 3000, + 'gamma': 1.4, }, - 'start_date': '2013-04-01', + 'start_date': '2021-10-31', 'end_date': None # to present }, } } -} +} \ No newline at end of file diff --git a/tethysapp/earth_engine/helpers.py b/tethysapp/earth_engine/helpers.py index da759bc..65f9b1a 100644 --- a/tethysapp/earth_engine/helpers.py +++ b/tethysapp/earth_engine/helpers.py @@ -1,18 +1,17 @@ -import datetime as dt +import pandas as pd +from plotly import graph_objs as go import os -import logging -import glob import tempfile import zipfile -import ee -import pandas as pd -from plotly import graph_objs as go import shapefile +import glob +import logging +import ee from .gee.methods import upload_shapefile_to_gee +import datetime as dt log = logging.getLogger(f'tethys.apps.{__name__}') - def generate_figure(figure_title, time_series): """ Generate a figure from a list of time series Pandas DataFrames. @@ -61,14 +60,12 @@ def generate_figure(figure_title, time_series): return figure - -def handle_shapefile_upload(request, user_workspace): +def handle_shapefile_upload(request, user_media): """ Uploads shapefile to Google Earth Engine as an Asset. Args: request (django.Request): the request object. - user_workspace (tethys_sdk.workspaces.Workspace): the User workspace object. Returns: str: Error string if errors occurred. @@ -92,7 +89,7 @@ def handle_shapefile_upload(request, user_workspace): except zipfile.BadZipFile: # Return error message return 'You must provide a zip archive containing a shapefile.' - + # Verify that it contains a shapefile try: # Find a shapefile in directory where we extracted the archive @@ -105,12 +102,12 @@ def handle_shapefile_upload(request, user_workspace): # Check type (only Polygon supported) if shp_file.shapeType != shapefile.POLYGON: return 'Only shapefiles containing Polygons are supported.' + + # Setup user media directory for storing shapefile + media_dir = prep_boundary_dir(user_media.path) - # Setup workspace directory for storing shapefile - workspace_dir = prep_boundary_dir(user_workspace.path) - - # Write the shapefile to the workspace directory - write_boundary_shapefile(shp_file, workspace_dir) + # Write the shapefile to the media directory + write_boundary_shapefile(shp_file, media_dir) # Upload shapefile as Asset in GEE upload_shapefile_to_gee(request.user, shp_file) @@ -122,8 +119,7 @@ def handle_shapefile_upload(request, user_workspace): msg = 'An unexpected error occurred while uploading the shapefile to Google Earth Engine.' log.exception(msg) return msg - - + def find_shapefile(directory): """ Recursively find the path to the first file with an extension ".shp" in the given directory. @@ -148,7 +144,6 @@ def find_shapefile(directory): return shapefile_path - def prep_boundary_dir(root_path): """ Setup the workspace directory that will store the uploaded boundary shapefile. @@ -177,7 +172,6 @@ def prep_boundary_dir(root_path): return boundary_dir - def write_boundary_shapefile(shp_file, directory): """ Write the shapefile to the given directory. The shapefile will be called "boundary.shp". @@ -204,7 +198,6 @@ def write_boundary_shapefile(shp_file, directory): return shapefile_path - def compute_dates_for_product(product_dict): """ Compute default dates and date range for given product. @@ -236,4 +229,4 @@ def compute_dates_for_product(product_dict): 'end_valid_date_range': end_valid_date_range } - return product_dates + return product_dates \ No newline at end of file diff --git a/tethysapp/earth_engine/public/css/about.css b/tethysapp/earth_engine/public/css/about.css index 2674735..58978cf 100644 --- a/tethysapp/earth_engine/public/css/about.css +++ b/tethysapp/earth_engine/public/css/about.css @@ -1,24 +1,24 @@ .page-header h1 { - text-align: center; - font-size: 48pt; - color: black; + text-align: center; + font-size: 48pt; + color: black; } .about-img { - width: 100%; - max-width: 360px; - margin-bottom: 20px; + width: 100%; + max-width: 360px; + margin-bottom: 20px; } .about-footer-content { - text-align: center; - margin: 50px 0 100px 0; -} - -.about-footer-content h3 { - margin-bottom: 26px; -} - -.about-footer-content img { - margin: 0 5px; -} \ No newline at end of file + text-align: center; + margin: 50px 0 100px 0; + } + + .about-footer-content h3 { + margin-bottom: 26px; + } + + .about-footer-content img { + margin: 0 5px; + } \ No newline at end of file diff --git a/tethysapp/earth_engine/public/css/home.css b/tethysapp/earth_engine/public/css/home.css index bde0dd0..0644092 100644 --- a/tethysapp/earth_engine/public/css/home.css +++ b/tethysapp/earth_engine/public/css/home.css @@ -1,76 +1,75 @@ -#inner-app-content { - padding: 0; -} - .info-container { - background-color: #0000009f; - box-shadow: 3px 5px 3px rgba(0,0,0,0.35); - padding: 10px; - margin-bottom: 30px; + background-color: #0000009f; + box-shadow: 3px 5px 3px rgba(0,0,0,0.35); + padding: 10px; + margin-bottom: 30px; } .info-container .info-title { - color: #067ef5; - text-shadow: 2px 2px #000000; + color: #067ef5; + text-shadow: 2px 2px #000000; } .info-container p { - color: #eee; - text-shadow: 2px 2px #000000; - font-size: 16px; + color: #eee; + text-shadow: 2px 2px #000000; + font-size: 16px; } .info-container .media-body { - color: #eee; - text-shadow: 2px 2px #000000; + color: #eee; + text-shadow: 2px 2px #000000; } .info-container .media-object { - border-radius: 5px; + border-radius: 5px; } .info-container .media-heading { - color: #eee; - text-shadow: 2px 2px #000000; + color: #eee; + text-shadow: 2px 2px #000000; } #feature-image { - width: 100%; + width: 100%; } - #get-started-btn { - display: inline-block; - border-radius: 15px; - padding: 5px 10px; - background-color: #fff; - color: #044777; - border: solid 2px rgb(6, 126, 245); - text-transform: uppercase; - font-weight: 600; - align-items: center; - font-size: 14pt; - cursor: pointer; - width: fit-content; - text-decoration: none !important; - justify-content: center; - margin: 10px 0; + display: inline-block; + border-radius: 15px; + padding: 5px 10px; + background-color: #fff; + color: #044777; + border: solid 2px rgb(6, 126, 245); + text-transform: uppercase; + font-weight: 600; + align-items: center; + font-size: 14pt; + cursor: pointer; + width: fit-content; + text-decoration: none !important; + justify-content: center; + margin: 10px 0; } #get-started-btn:hover { - background-color: #eee; + background-color: #eee; } #get-started-btn:active, #get-started-btn:focus { - background-color: #044777; - color: white; + background-color: #044777; + color: white; } #home-content-container { - padding: 20px; - min-height: 100%; - background: url('/static/earth_engine/images/earth-engine-backdrop.png'); - background-color: #d2dadc; - background-position: center; - background-repeat: no-repeat + padding: 20px; + min-height: 100%; + background: url('/static/earth_engine/images/earth-engine-backdrop.png'); + background-color: #d2dadc; + background-position: center; + background-repeat: no-repeat +} + +#inner-app-content { + padding: 0; } \ No newline at end of file diff --git a/tethysapp/earth_engine/public/images/earth-engine-viewer.png b/tethysapp/earth_engine/public/images/earth-engine-viewer.png index 2d784ed..b897825 100644 Binary files a/tethysapp/earth_engine/public/images/earth-engine-viewer.png and b/tethysapp/earth_engine/public/images/earth-engine-viewer.png differ diff --git a/tethysapp/earth_engine/public/images/icon.gif b/tethysapp/earth_engine/public/images/icon.gif new file mode 100644 index 0000000..5c8236e Binary files /dev/null and b/tethysapp/earth_engine/public/images/icon.gif differ diff --git a/tethysapp/earth_engine/public/images/map-loader.gif b/tethysapp/earth_engine/public/images/map-loader.gif index 74da381..0ee0c73 100644 Binary files a/tethysapp/earth_engine/public/images/map-loader.gif and b/tethysapp/earth_engine/public/images/map-loader.gif differ diff --git a/tethysapp/earth_engine/public/js/gee_datasets.js b/tethysapp/earth_engine/public/js/gee_datasets.js index ff11280..2e451c3 100644 --- a/tethysapp/earth_engine/public/js/gee_datasets.js +++ b/tethysapp/earth_engine/public/js/gee_datasets.js @@ -24,14 +24,13 @@ var GEE_DATASETS = (function() { // Map Variables var m_map, - m_gee_layer; + m_gee_layer; /************************************************************************ * PRIVATE FUNCTION DECLARATIONS *************************************************************************/ // Dataset Select Methods var bind_controls, update_product_options, update_sensor_options, update_date_bounds, collect_data; - // Map Methods var update_map, update_data_layer, create_data_layer, clear_map; @@ -45,7 +44,7 @@ var GEE_DATASETS = (function() { bind_controls = function() { $('#platform').on('change', function() { let platform = $('#platform').val(); - + if (platform !== m_platform) { m_platform = platform; console.log(`Platform Changed to: ${m_platform}`); @@ -53,10 +52,10 @@ var GEE_DATASETS = (function() { update_sensor_options(); } }); - + $('#sensor').on('change', function() { let sensor = $('#sensor').val(); - + if (sensor !== m_sensor) { m_sensor = sensor; console.log(`Sensor Changed to: ${m_sensor}`); @@ -64,10 +63,10 @@ var GEE_DATASETS = (function() { update_product_options(); } }); - + $('#product').on('change', function() { let product = $('#product').val(); - + if (product !== m_product) { m_product = product; console.log(`Product Changed to: ${m_product}`); @@ -75,34 +74,33 @@ var GEE_DATASETS = (function() { update_date_bounds(); } }); - + $('#start_date').on('change', function() { let start_date = $('#start_date').val(); - + if (start_date !== m_start_date) { m_start_date = start_date; console.log(`Start Date Changed to: ${m_start_date}`); } }); - + $('#end_date').on('change', function() { let end_date = $('#end_date').val(); - + if (end_date !== m_end_date) { m_end_date = end_date; console.log(`End Date Changed to: ${m_end_date}`); } }); - + $('#reducer').on('change', function() { let reducer = $('#reducer').val(); - + if (reducer !== m_reducer) { m_reducer = reducer; console.log(`Reducer Changed to: ${m_reducer}`); } }); - $('#load_map').on('click', function() { update_map(); }); @@ -209,12 +207,11 @@ var GEE_DATASETS = (function() { product: m_product, start_date: m_start_date, end_date: m_end_date, - reducer: m_reducer, + reducer: m_reducer, geometry: get_geometry() }; return data; }; - // Map Methods update_map = function() { let data = collect_data(); @@ -249,25 +246,25 @@ var GEE_DATASETS = (function() { url: url, attributions: 'Google Earth Engine' }); - + source.on('tileloadstart', function() { $('#loader').addClass('show'); }); - + source.on('tileloadend', function() { $('#loader').removeClass('show'); }); - + source.on('tileloaderror', function() { $('#loader').removeClass('show'); }); - + m_gee_layer = new ol.layer.Tile({ source: source, opacity: 0.7 }); - // Insert below the draw layer (so drawn polygons and points render on top of the data layer). + // Insert below the draw layer (so drawn polygons and points render on top of data layer). m_map.getLayers().insertAt(1, m_gee_layer); }; @@ -301,7 +298,7 @@ var GEE_DATASETS = (function() { '' ); $('#plot-modal').modal('show'); - }; + } /************************************************************************ * PUBLIC INTERFACE @@ -314,10 +311,10 @@ var GEE_DATASETS = (function() { $(function() { // Initialize Global Variables bind_controls(); - + // EE Products EE_PRODUCTS = $('#ee-products').data('ee-products'); - + // Initialize values m_platform = $('#platform').val(); m_sensor = $('#sensor').val(); @@ -325,7 +322,7 @@ var GEE_DATASETS = (function() { INITIAL_START_DATE = m_start_date = $('#start_date').val(); INITIAL_END_DATE = m_end_date = $('#end_date').val(); m_reducer = $('#reducer').val(); - + m_map = TETHYS_MAP_VIEW.getMap(); // Open boundary file modal if it has an error diff --git a/tethysapp/earth_engine/workspaces/app_workspace/.gitkeep b/tethysapp/earth_engine/resources/.gitkeep similarity index 100% rename from tethysapp/earth_engine/workspaces/app_workspace/.gitkeep rename to tethysapp/earth_engine/resources/.gitkeep diff --git a/tethysapp/earth_engine/templates/earth_engine/about.html b/tethysapp/earth_engine/templates/earth_engine/about.html index b2390bf..c1becea 100644 --- a/tethysapp/earth_engine/templates/earth_engine/about.html +++ b/tethysapp/earth_engine/templates/earth_engine/about.html @@ -1,9 +1,9 @@ {% extends "tethys_apps/app_header_content.html" %} -{% load static %} +{% load static tethys %} {% block styles %} {{ block.super }} - + {% endblock %} {% block header_buttons %} @@ -11,49 +11,49 @@ {% endblock %} {% block app_content %} -
+
-
+
{% endblock %} {% block after_app_content %} diff --git a/tethysapp/earth_engine/templates/earth_engine/base.html b/tethysapp/earth_engine/templates/earth_engine/base.html index 6ca00b0..e45b3c2 100644 --- a/tethysapp/earth_engine/templates/earth_engine/base.html +++ b/tethysapp/earth_engine/templates/earth_engine/base.html @@ -1,6 +1,6 @@ {% extends "tethys_apps/app_base.html" %} -{% load static %} +{% load static tethys %} {% block title %}{{ tethys_app.name }}{% endblock %} @@ -13,7 +13,7 @@ {% block app_title %}{{ tethys_app.name }}{% endblock %} {% block header_buttons %} - {% include "earth_engine/header_buttons.html" %} + {% include tethys_app.package|add:"/header_buttons.html" %} {% endblock %} {% block app_navigation_items %} @@ -32,20 +32,20 @@ {% block app_content %} {% endblock %} -{% block app_actions_override %} -{% endblock %} - {% block after_app_content %} {{ block.super }} {% include "earth_engine/disclaimer.html" %} {% endblock %} +{% block app_actions_override %} +{% endblock %} + {% block content_dependent_styles %} {{ block.super }} - + {% endblock %} {% block scripts %} {{ block.super }} - + {% endblock %} \ No newline at end of file diff --git a/tethysapp/earth_engine/templates/earth_engine/disclaimer.html b/tethysapp/earth_engine/templates/earth_engine/disclaimer.html index 78b9e17..5c79850 100644 --- a/tethysapp/earth_engine/templates/earth_engine/disclaimer.html +++ b/tethysapp/earth_engine/templates/earth_engine/disclaimer.html @@ -1,58 +1,57 @@ -