Repository: spacetelescope/jwql

Issue:
Create "template branch" as web development scaffold
After a conversation with @DanielKuebi today, I realized that there is a need for more structured example for how to contribute a new web page to the project - beyond the three brief lines that are in the presentation about the web app.

We determined that it would be helpful to create a "template branch" of sorts, that could include:
- A new HTML template
- A new template view function in `views.py`
- A new URL
- Interfaces to the existing `monitor_template` to demonstrate how the web app and package connect
- Rigorous directions for how to customize all of the above (maybe in the wiki?)

I might also include a Bokeh plot in the template/view, since our method for embedding Bokeh is all but straightforward (and frequently changing!).

Any new contributors could then pull/copy this branch as a starting point to make their own monitors and web pages.

Since we hope to have many different developers from different instrument teams contributing to monitors, all with different levels of experience and comfort with Python and web development, this should hopefully be helpful beyond just Daniel's case.


Discussion:

Resolving patch:
diff --git a/jwql/website/apps/jwql/data_containers.py b/jwql/website/apps/jwql/data_containers.py
--- a/jwql/website/apps/jwql/data_containers.py
+++ b/jwql/website/apps/jwql/data_containers.py
@@ -27,6 +27,8 @@
 from astropy.io import fits
 from astropy.time import Time
 from astroquery.mast import Mast
+from bokeh.embed import components
+from bokeh.plotting import figure
 import numpy as np
 
 from .forms import MnemonicSearchForm, MnemonicQueryForm
@@ -44,6 +46,46 @@
 REPO_DIR = os.path.split(PACKAGE_DIR)[0]
 
 
+def webpage_template_data():
+    """An example data container function for the webpage template.
+
+    Define variables to pass to the webpage_template view, including
+    the output of a Bokeh plot to embed.
+
+    Returns
+    -------
+    jwst_launch_date : int
+        The current expected JWST launch date
+    plot_data : list
+        A list containing the JavaScript and HTML content for the
+        Bokeh plot
+    """
+    # Define a single variable to pass
+    jwst_launch_date = 2021
+
+    # Define a basic bokeh plot showing value as a function of time.
+    # Start by defining the data for the plot.
+    list_of_dates = ['2018-02-11 00:00:00.000', '2018-02-12 00:00:00.000',
+                     '2018-02-13 00:00:00.000', '2018-02-14 00:00:00.000',
+                     '2018-02-15 00:00:00.000', '2018-02-16 00:00:00.000',
+                     '2018-02-17 00:00:00.000']
+    date = Time(list_of_dates, format='iso').datetime
+    avg_temp = [33, 36, 42, 43, 56, 44, 34]
+
+    # Build the plot with Bokeh
+    p1 = figure(tools='pan,box_zoom,reset,wheel_zoom,save', x_axis_type='datetime',
+                title='Baltimore Winter Temperatures', x_axis_label='Date',
+                y_axis_label='Average Temperature (Degrees F)')
+    p1.line(date, avg_temp, line_width=1, line_color='blue', line_dash='dashed')
+    p1.circle(date, avg_temp, color='blue')
+
+    # Save out the JavaScript and HTML
+    script, div = components(p1)
+    plot_data = [div, script]
+
+    return jwst_launch_date, plot_data
+
+
 def get_acknowledgements():
     """Returns a list of individuals who are acknowledged on the
     ``about`` page.
diff --git a/jwql/website/apps/jwql/urls.py b/jwql/website/apps/jwql/urls.py
--- a/jwql/website/apps/jwql/urls.py
+++ b/jwql/website/apps/jwql/urls.py
@@ -55,6 +55,9 @@
     # Home
     path('', views.home, name='home'),
 
+    # WEBPAGE TEMPLATE
+    path('webpage_template', views.webpage_template, name='webpage_template'),
+
     # Authentication
     path('login/', oauth.login, name='login'),
     path('logout/', oauth.logout, name='logout'),
diff --git a/jwql/website/apps/jwql/views.py b/jwql/website/apps/jwql/views.py
--- a/jwql/website/apps/jwql/views.py
+++ b/jwql/website/apps/jwql/views.py
@@ -48,6 +48,7 @@
 from .data_containers import get_proposal_info
 from .data_containers import thumbnails
 from .data_containers import thumbnails_ajax
+from .data_containers import webpage_template_data
 from .forms import FileSearchForm
 from .oauth import auth_info
 from jwql.utils.constants import JWST_INSTRUMENT_NAMES, MONITORS, JWST_INSTRUMENT_NAMES_MIXEDCASE
@@ -56,6 +57,39 @@
 FILESYSTEM_DIR = os.path.join(get_config()['jwql_dir'], 'filesystem')
 
 
+def webpage_template(request):
+    """Generate the ``WEBPAGE_TEMPLATE`` page
+
+    Parameters
+    ----------
+    request : HttpRequest object
+        Incoming request from the webpage
+
+    Returns
+    -------
+    HttpResponse object
+        Outgoing response sent to the webpage
+    """
+    # Define which HTML template to render
+    template = 'WEBPAGE_TEMPLATE.html'
+
+    # Define variables with data from data_containers.py
+    launch, plot_data = webpage_template_data()
+
+    # Pack all needed variables into a Python dictionary
+    context = {
+        'launch_date': launch,
+        'plot_data': plot_data,
+        'inst': '',  # Leave as empty string or instrument name; Required for navigation bar
+        'inst_list': JWST_INSTRUMENT_NAMES,  # Do not edit; Required for navigation bar
+        'tools': MONITORS,  # Do not edit; Required for navigation bar
+        'user': None  # Do not edit; Required for authentication
+    }
+
+    # Return a HTTP response with the template and dictionary of variables
+    return render(request, template, context)
+
+
 @auth_info
 def about(request, user):
     """Generate the ``about`` page


Test patch: