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 %}
-
+
-
About Earth Engine
-
Sit Amet Consectetur Adipiscing
-
+
About Earth Engine
+
Sit Amet Consectetur Adipiscing
+
+
-
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Euismod nisi porta lorem mollis. Congue quisque egestas diam in arcu cursus euismod. Auctor neque vitae tempus quam pellentesque nec nam. Erat imperdiet sed euismod nisi porta lorem. Nunc eget lorem dolor sed viverra ipsum nunc aliquet bibendum. Sed blandit libero volutpat sed cras ornare. Convallis tellus id interdum velit laoreet id. Amet mauris commodo quis imperdiet massa tincidunt. Mi bibendum neque egestas congue quisque egestas diam in. Enim nec dui nunc mattis enim ut tellus elementum sagittis. Cursus mattis molestie a iaculis at erat pellentesque. Ut tellus elementum sagittis vitae et leo.
-
Eu Consequat ac Felis
-
Eu consequat ac felis donec et odio. Eget arcu dictum varius duis at consectetur lorem. Lorem ipsum dolor sit amet consectetur. Turpis egestas integer eget aliquet nibh praesent. Mattis rhoncus urna neque viverra justo nec. Iaculis urna id volutpat lacus laoreet non curabitur gravida arcu. Convallis posuere morbi leo urna molestie at elementum eu. Fermentum et sollicitudin ac orci phasellus egestas tellus. Convallis aenean et tortor at risus. Morbi tristique senectus et netus et malesuada fames ac. Sed vulputate mi sit amet mauris commodo quis. Nisi quis eleifend quam adipiscing vitae proin sagittis nisl. Id venenatis a condimentum vitae sapien pellentesque habitant morbi tristique. Id cursus metus aliquam eleifend mi in nulla. Proin fermentum leo vel orci porta non pulvinar neque laoreet. Lobortis mattis aliquam faucibus purus in massa tempor. Varius vel pharetra vel turpis nunc.
-
Mauris rhoncus aenean vel elit: Blandit aliquam etiam erat velit. Auctor neque vitae tempus quam pellentesque nec nam. Augue mauris augue neque gravida in fermentum et. Tempus urna et pharetra pharetra. Vel turpis nunc eget lorem. Vitae nunc sed velit dignissim. Enim tortor at auctor urna nunc id. Pellentesque habitant morbi tristique senectus et netus et. Tellus integer feugiat scelerisque varius morbi enim nunc faucibus.
-
Blandit turpis cursus in hac habitasse platea: Tellus elementum sagittis vitae et leo duis ut diam quam. Amet nisl purus in mollis nunc sed. Ac feugiat sed lectus vestibulum. Suscipit adipiscing bibendum est ultricies integer quis. Tortor pretium viverra suspendisse potenti nullam ac tortor. Blandit turpis cursus in hac. Id porta nibh venenatis cras sed felis eget velit. Fermentum posuere urna nec tincidunt praesent semper feugiat nibh sed. Pellentesque elit ullamcorper dignissim cras tincidunt lobortis feugiat vivamus at. Sapien et ligula ullamcorper malesuada proin libero nunc consequat. Aliquet enim tortor at auctor urna nunc id. Fringilla ut morbi tincidunt augue interdum velit euismod in. In arcu cursus euismod quis viverra nibh. Vulputate ut pharetra sit amet. Purus in massa tempor nec. Pellentesque massa placerat duis ultricies lacus sed. Integer feugiat scelerisque varius morbi enim. Vitae tempus quam pellentesque nec nam.
-
Sed cras ornare arcu dui vivamus arcu: Pellentesque adipiscing commodo elit at. Fusce id velit ut tortor pretium viverra. Nunc vel risus commodo viverra. Dui faucibus in ornare quam viverra orci sagittis eu volutpat. Aliquet nibh praesent tristique magna. Purus sit amet volutpat consequat. Gravida neque convallis a cras. Aenean euismod elementum nisi quis eleifend. At tellus at urna condimentum mattis pellentesque id nibh tortor. Sit amet massa vitae tortor. Volutpat lacus laoreet non curabitur gravida arcu ac. Vulputate dignissim suspendisse in est ante. Tempor commodo ullamcorper a lacus vestibulum. Quis vel eros donec ac odio tempor. Lacus sed turpis tincidunt id aliquet risus feugiat in ante. Metus aliquam eleifend mi in.
'
-
+
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Euismod nisi porta lorem mollis. Congue quisque egestas diam in arcu cursus euismod. Auctor neque vitae tempus quam pellentesque nec nam. Erat imperdiet sed euismod nisi porta lorem. Nunc eget lorem dolor sed viverra ipsum nunc aliquet bibendum. Sed blandit libero volutpat sed cras ornare. Convallis tellus id interdum velit laoreet id. Amet mauris commodo quis imperdiet massa tincidunt. Mi bibendum neque egestas congue quisque egestas diam in. Enim nec dui nunc mattis enim ut tellus elementum sagittis. Cursus mattis molestie a iaculis at erat pellentesque. Ut tellus elementum sagittis vitae et leo.
+
Eu Consequat ac Felis
+
Eu consequat ac felis donec et odio. Eget arcu dictum varius duis at consectetur lorem. Lorem ipsum dolor sit amet consectetur. Turpis egestas integer eget aliquet nibh praesent. Mattis rhoncus urna neque viverra justo nec. Iaculis urna id volutpat lacus laoreet non curabitur gravida arcu. Convallis posuere morbi leo urna molestie at elementum eu. Fermentum et sollicitudin ac orci phasellus egestas tellus. Convallis aenean et tortor at risus. Morbi tristique senectus et netus et malesuada fames ac. Sed vulputate mi sit amet mauris commodo quis. Nisi quis eleifend quam adipiscing vitae proin sagittis nisl. Id venenatis a condimentum vitae sapien pellentesque habitant morbi tristique. Id cursus metus aliquam eleifend mi in nulla. Proin fermentum leo vel orci porta non pulvinar neque laoreet. Lobortis mattis aliquam faucibus purus in massa tempor. Varius vel pharetra vel turpis nunc.
+
Mauris rhoncus aenean vel elit: Blandit aliquam etiam erat velit. Auctor neque vitae tempus quam pellentesque nec nam. Augue mauris augue neque gravida in fermentum et. Tempus urna et pharetra pharetra. Vel turpis nunc eget lorem. Vitae nunc sed velit dignissim. Enim tortor at auctor urna nunc id. Pellentesque habitant morbi tristique senectus et netus et. Tellus integer feugiat scelerisque varius morbi enim nunc faucibus.
+
Blandit turpis cursus in hac habitasse platea: Tellus elementum sagittis vitae et leo duis ut diam quam. Amet nisl purus in mollis nunc sed. Ac feugiat sed lectus vestibulum. Suscipit adipiscing bibendum est ultricies integer quis. Tortor pretium viverra suspendisse potenti nullam ac tortor. Blandit turpis cursus in hac. Id porta nibh venenatis cras sed felis eget velit. Fermentum posuere urna nec tincidunt praesent semper feugiat nibh sed. Pellentesque elit ullamcorper dignissim cras tincidunt lobortis feugiat vivamus at. Sapien et ligula ullamcorper malesuada proin libero nunc consequat. Aliquet enim tortor at auctor urna nunc id. Fringilla ut morbi tincidunt augue interdum velit euismod in. In arcu cursus euismod quis viverra nibh. Vulputate ut pharetra sit amet. Purus in massa tempor nec. Pellentesque massa placerat duis ultricies lacus sed. Integer feugiat scelerisque varius morbi enim. Vitae tempus quam pellentesque nec nam.
+
Sed cras ornare arcu dui vivamus arcu: Pellentesque adipiscing commodo elit at. Fusce id velit ut tortor pretium viverra. Nunc vel risus commodo viverra. Dui faucibus in ornare quam viverra orci sagittis eu volutpat. Aliquet nibh praesent tristique magna. Purus sit amet volutpat consequat. Gravida neque convallis a cras. Aenean euismod elementum nisi quis eleifend. At tellus at urna condimentum mattis pellentesque id nibh tortor. Sit amet massa vitae tortor. Volutpat lacus laoreet non curabitur gravida arcu ac. Vulputate dignissim suspendisse in est ante. Tempor commodo ullamcorper a lacus vestibulum. Quis vel eros donec ac odio tempor. Lacus sed turpis tincidunt id aliquet risus feugiat in ante. Metus aliquam eleifend mi in.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque sed ipsum mollis, congue metus vitae, fringilla tortor. Cras non magna tempus, pretium nibh a, accumsan sapien. Quisque quis diam justo. Mauris ut diam molestie, scelerisque nibh ac, convallis mauris. Sed risus ex, blandit eu lectus vitae, vulputate fermentum metus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Integer pretium sagittis arcu at aliquet. Quisque quis sodales urna. Suspendisse nisl odio, facilisis ac iaculis quis, accumsan non justo. Nunc eu porttitor neque.
-
Sed vel nisl leo. Quisque venenatis erat nec erat laoreet, ac vulputate magna sodales. Ut in enim finibus, finibus orci sit amet, feugiat erat. Vivamus id lorem arcu. Integer lacus lorem, rhoncus vitae elit eu, vestibulum placerat nibh. Ut eget lectus in quam blandit molestie nec et leo. Ut augue libero, commodo id ligula sit amet, placerat molestie enim. Cras justo odio, vulputate id odio non, ultricies mollis sem. Integer et vestibulum erat, eu dictum nunc. Donec eu diam ac ligula aliquam egestas in non lectus. Nullam quis arcu eget massa feugiat sollicitudin. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla quis urna efficitur, sagittis ante eget, accumsan nulla.
-
Pellentesque tempor neque in odio ullamcorper, a varius lectus euismod. Donec odio nunc, mollis aliquam imperdiet eget, lacinia sit amet dui. Morbi quis pellentesque lorem. Nam volutpat vestibulum ex vel interdum. Etiam accumsan luctus felis gravida sodales. Praesent malesuada lectus tortor, at maximus velit fringilla sed. Ut consequat nisl ut pretium egestas.
-
Quisque tincidunt ex a sem sagittis molestie. Nunc pellentesque et tortor quis lobortis. Etiam eget justo risus. Nunc a lobortis quam, id varius ante. Maecenas at rhoncus enim. Maecenas aliquam non elit quis tempor. Morbi eu ligula imperdiet, imperdiet neque non, faucibus eros. Vivamus ac sollicitudin nunc. Vivamus sagittis ut orci eu auctor. Nulla sit amet facilisis felis, eu tincidunt sapien. Nulla sit amet dignissim nisi. Cras pellentesque rutrum rhoncus. Nulla nibh erat, congue sit amet feugiat in, eleifend at massa. Maecenas risus massa, placerat non velit vel, laoreet cursus nunc.
-
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nam ultricies accumsan elit vel volutpat. Proin nec nibh ac dolor tempor sollicitudin. Praesent nisi elit, placerat eget diam nec, viverra euismod felis. Nunc accumsan nulla non eros bibendum, mollis hendrerit enim cursus. In ex lorem, hendrerit ut nibh nec, vestibulum placerat massa. Proin at odio non nisl eleifend venenatis ut at tortor.
\ No newline at end of file
diff --git a/tethysapp/earth_engine/templates/earth_engine/home.html b/tethysapp/earth_engine/templates/earth_engine/home.html
index eca72b3..dfd22b3 100644
--- a/tethysapp/earth_engine/templates/earth_engine/home.html
+++ b/tethysapp/earth_engine/templates/earth_engine/home.html
@@ -7,74 +7,73 @@
{% endblock %}
{% block header_buttons %}
- {% include "earth_engine/header_buttons.html" %}
+ {% include tethys_app.package|add:"/header_buttons.html" %}
{% endblock %}
{% block app_content %}
-
-
-
-
-
About
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Eget est lorem ipsum dolor sit amet. Morbi tincidunt augue interdum velit euismod in pellentesque.
-
Ac felis donec et odio pellentesque. Quis ipsum suspendisse ultrices gravida dictum fusce ut. Curabitur gravida arcu ac tortor dignissim convallis aenean et tortor. Sed euismod nisi porta lorem mollis. Nisi scelerisque eu ultrices vitae. Sit amet consectetur adipiscing elit duis. At in tellus integer feugiat scelerisque varius morbi enim.
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
-
+
+
+
+
+
About
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Eget est lorem ipsum dolor sit amet. Morbi tincidunt augue interdum velit euismod in pellentesque.
+
Ac felis donec et odio pellentesque. Quis ipsum suspendisse ultrices gravida dictum fusce ut. Curabitur gravida arcu ac tortor dignissim convallis aenean et tortor. Sed euismod nisi porta lorem mollis. Nisi scelerisque eu ultrices vitae. Sit amet consectetur adipiscing elit duis. At in tellus integer feugiat scelerisque varius morbi enim.