You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2021/06/16 18:39:16 UTC

[airavata-django-portal] branch master updated (722fa98 -> 564a8b1)

This is an automated email from the ASF dual-hosted git repository.

machristie pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git.


    from 722fa98  Merge pull request #63 from apache/airavata-3465
     new c722afa  Updated output view provider portion of tutorial to use cookiecutter
     new 61de74e  Updated custom django app portion of tutorial to use cookiecutter
     new 5219107  updating notes on viewing final solution
     new 5f0ee98  tutorial instructions on installing Python and creating venv on all OSes
     new 8a22eec  tutorial: minor fixes
     new f63d5c8  tutorial: rename to "custom ui tutorial"
     new 3b11429  tutorial: updated screenshots
     new 31b34c3  Compatibility for building JS on Windows
     new 0236c1f  tutorial: Python on Windows instructions
     new 564a8b1  Merge branch 'master' of https://github.com/apache/airavata-django-portal

The 10 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 Dockerfile                                         |   2 +-
 build_js.bat                                       |  36 ++
 django_airavata/static/common/package.json         |   3 +-
 django_airavata/static/common/yarn.lock            | 387 ++++++++------
 ...{gateways_tutorial.md => custom_ui_tutorial.md} | 559 ++++++++++++++-------
 .../screenshots/custom-ui/custom-app-menu.png      | Bin 0 -> 177809 bytes
 .../gaussian-output-view-providers-json.png        | Bin 0 -> 31419 bytes
 .../screenshots/custom-ui/settings_menu.png        | Bin 0 -> 181704 bytes
 mkdocs.yml                                         |   2 +-
 requirements.txt                                   |   2 +-
 10 files changed, 654 insertions(+), 337 deletions(-)
 create mode 100644 build_js.bat
 rename docs/tutorial/{gateways_tutorial.md => custom_ui_tutorial.md} (75%)
 create mode 100644 docs/tutorial/screenshots/custom-ui/custom-app-menu.png
 create mode 100644 docs/tutorial/screenshots/custom-ui/gaussian-output-view-providers-json.png
 create mode 100644 docs/tutorial/screenshots/custom-ui/settings_menu.png

[airavata-django-portal] 10/10: Merge branch 'master' of https://github.com/apache/airavata-django-portal

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit 564a8b12dd5cf7d436b7fe3210f72c60a2fe1b35
Merge: 0236c1f 722fa98
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Wed Jun 16 14:38:57 2021 -0400

    Merge branch 'master' of https://github.com/apache/airavata-django-portal

 .travis.yml                                                      | 2 ++
 Dockerfile                                                       | 9 +++++----
 README.md                                                        | 6 +++---
 django_airavata/settings.py                                      | 2 +-
 django_airavata/templates/blocks/heading_block.html              | 8 ++++----
 django_airavata/wagtailapps/base/templatetags/navigation_tags.py | 4 ++--
 requirements.txt                                                 | 7 ++++---
 tox.ini                                                          | 4 ++--
 8 files changed, 23 insertions(+), 19 deletions(-)

diff --cc Dockerfile
index 988ee3c,286acfd..b28ed85
--- a/Dockerfile
+++ b/Dockerfile
@@@ -65,9 -65,10 +65,10 @@@ WORKDIR /cod
  COPY requirements.txt requirements-mysql.txt ./
  COPY setup.* ./
  COPY README.md .
- RUN pip install --upgrade pip setuptools wheel
- RUN pip install -r requirements.txt
- RUN pip install -r requirements-mysql.txt
+ RUN apt-get update && apt-get install -y git gcc zlib1g-dev libjpeg-dev default-libmysqlclient-dev
 -RUN pip install --upgrade pip --no-cache
++RUN pip install --upgrade pip setuptools wheel --no-cache
+ RUN pip install -r requirements.txt --no-cache
+ RUN pip install -r requirements-mysql.txt --no-cache
  
  # Copy in a default settings_local.py file
  COPY ./django_airavata/settings_local.py.sample ./django_airavata/settings_local.py
diff --cc requirements.txt
index 5367544,b4192f5..a085d39
--- a/requirements.txt
+++ b/requirements.txt
@@@ -1,6 -1,6 +1,6 @@@
  # Pin these dependencies
- Django>=2.2,<2.3
+ Django==2.2.23
 -requests==2.13.0
 +requests==2.23.0
  requests-oauthlib==0.7.0
  thrift==0.10.0
  thrift_connector==0.24

[airavata-django-portal] 03/10: updating notes on viewing final solution

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit 5219107c0f76f7670da4617565e00d95e130fa54
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Thu Jun 10 11:29:50 2021 -0400

    updating notes on viewing final solution
---
 docs/tutorial/gateways_tutorial.md | 20 ++++++--------------
 1 file changed, 6 insertions(+), 14 deletions(-)

diff --git a/docs/tutorial/gateways_tutorial.md b/docs/tutorial/gateways_tutorial.md
index dd985f6..b5155bf 100644
--- a/docs/tutorial/gateways_tutorial.md
+++ b/docs/tutorial/gateways_tutorial.md
@@ -396,9 +396,9 @@ if you are interested).
 
 ```
 cd $HOME
-git clone https://github.com/machristie/gateways19-tutorial.git gateways19-tutorial-final
+git clone https://github.com/machristie/gateways_tutorial_app.git gateways_tutorial_app-final
 cd gateways_tutorial_app
-docker run -d --name gateways19-tutorial -p 8000:8000 -v "$PWD:/extensions" -v "$PWD/../gateways19-tutorial-final/settings_local.py:/code/django_airavata/settings_local.py" machristie/airavata-django-portal
+docker run -d --name gateways19-tutorial -p 8000:8000 -v "$PWD:/extensions" -v "$PWD/../gateways_tutorial_app-final/settings_local.py:/code/django_airavata/settings_local.py" machristie/airavata-django-portal
 ```
 
 !!! note "For remote Docker host users"
@@ -484,7 +484,7 @@ Choose from 1, 2 [1]:
 
 3. This creates a custom output view provider, called
    GaussianEigenvaluesViewProvider, in `gateways-tutorialoutput_views/`. Open
-   `$HOME/gateways19-tutorial/gateways_tutorial_app/gateways_tutorial_app/output_views/gaussian_eigenvalues_view.py`
+   `$HOME/gateways_tutorial_app/gateways_tutorial_app/output_views/gaussian_eigenvalues_view.py`
    in your editor and we'll look at the generated code. The cookiecutter
    template has generated a GaussianEigenvaluesViewProvider class with a method
    called `generate_data`. The generate_data method has some commented out code
@@ -638,7 +638,7 @@ class GaussianEigenvaluesViewProvider:
    template already created this when it generated the
    gaussian_eigenvalues_view.py code. We can take a look and make sure it added
    an `airavata.output_view_providers` entry to the `[options.entry_points]`
-   section in the `$HOME/gateways19-tutorial/gateways_tutorial_app/setup.cfg`
+   section in the `$HOME/gateways_tutorial_app/setup.cfg`
    file:
 
 ```ini
@@ -1329,7 +1329,6 @@ function loadExperiments() {
                     });
             }
             // ENDING HERE
-
         });
     });
 }
@@ -1337,15 +1336,8 @@ function loadExperiments() {
 
 ## Resources
 
-You can browser the final version of the _gateways19-tutorial_ code at
-<https://github.com/machristie/gateways19-tutorial/tree/solution>. If you get
-stuck at some point with the tutorial you can skip to the solution by running
-the following git command in your _gateways19-tutorial_ repo:
-
-```bash
-cd $HOME/gateways19-tutorial
-git reset --hard origin/solution
-```
+You can browser the final version of the code at
+<https://github.com/machristie/gateways_tutorial_app>.
 
 ### Airavata API
 

[airavata-django-portal] 01/10: Updated output view provider portion of tutorial to use cookiecutter

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit c722afab543e99084d359293ac2ffe4126764da6
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Tue Jun 8 11:50:30 2021 -0400

    Updated output view provider portion of tutorial to use cookiecutter
---
 Dockerfile                         |   2 +-
 docs/tutorial/gateways_tutorial.md | 219 ++++++++++++++++++++++++++-----------
 2 files changed, 156 insertions(+), 65 deletions(-)

diff --git a/Dockerfile b/Dockerfile
index 8e4fd4e..988ee3c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -65,7 +65,7 @@ WORKDIR /code
 COPY requirements.txt requirements-mysql.txt ./
 COPY setup.* ./
 COPY README.md .
-RUN pip install --upgrade pip
+RUN pip install --upgrade pip setuptools wheel
 RUN pip install -r requirements.txt
 RUN pip install -r requirements-mysql.txt
 
diff --git a/docs/tutorial/gateways_tutorial.md b/docs/tutorial/gateways_tutorial.md
index 9a6ef1b..1ebef32 100644
--- a/docs/tutorial/gateways_tutorial.md
+++ b/docs/tutorial/gateways_tutorial.md
@@ -347,8 +347,39 @@ possible to provide additional custom views for output files. Examples include:
 -   parameterized notebook
 
 To be able to create a custom output viewer we'll need to write some Python
-code. First, we'll get a local version of the Django portal running which we'll
-use as a development environment.
+code. First we'll generate the custom Django app code.
+
+### Generate a custom Django app
+
+We have a local develop environment created. Now we can start adding custom
+code. First, we'll create a custom Django app, which is the standard way to
+package a Django extension.
+
+1. Install the latest version of cookiecutter. Cookiecutter is a tool for
+   generating project source code from a template.
+
+```sh
+pip install --user -U cookiecutter
+```
+
+2. Use cookiecutter to run the Airavata Django app template.
+
+```sh
+cd $HOME
+cookiecutter https://github.com/machristie/cookiecutter-airavata-django-app.git
+```
+
+You'll need to answer some questions. You can name it whatever you want, but to
+follow along with the tutorial, for `project_name` give **Gateways Tutorial
+App**. For the rest of the questions, you can simply accept the defaults:
+
+```
+project_name [My Custom Django App]: Gateways Tutorial App
+project_slug [gateways_tutorial_app]:
+project_short_description [Custom Django app with everything needed to be installed in the airavata-django-portal]:
+app_config_class_name [GatewaysTutorialAppConfig]:
+version [0.1.0]:
+```
 
 ### Setup local Django portal development environment
 
@@ -365,9 +396,9 @@ if you are interested).
 
 ```
 cd $HOME
-git clone https://github.com/machristie/gateways19-tutorial.git
-cd gateways19-tutorial
-docker run -d --name gateways19-tutorial -p 8000:8000 -v "$PWD:/extensions" -v "$PWD/settings_local.py:/code/django_airavata/settings_local.py" machristie/airavata-django-portal
+git clone https://github.com/machristie/gateways19-tutorial.git gateways19-tutorial-final
+cd gateways_tutorial_app
+docker run -d --name gateways19-tutorial -p 8000:8000 -v "$PWD:/extensions" -v "$PWD/../gateways19-tutorial-final/settings_local.py:/code/django_airavata/settings_local.py" machristie/airavata-django-portal
 ```
 
 !!! note "For remote Docker host users"
@@ -408,36 +439,74 @@ Go to [http://localhost:8000](http://localhost:8000), click on **Login in**,
 enter your username and password. On the dashboard you should see the your
 experiments listed on the right hand side.
 
-### Setup the custom output viewer package
+### Create the custom output viewer
 
-1. We've defined a custom output view provider, called
-   GaussianEigenvaluesViewProvider, in `output_views.py`. Open
-   `$HOME/gateways19-tutorial/gateways19_tutorial/output_views.py` in your
-   editor and we'll look at how it is implemented. First we add some imports
+Now we'll also generate and implement a **Gaussian Eigenvalues View** provider.
 
-```python
-import io
-import os
+1. We'll run another cookiecutter template to generate the output view provider
+   code. First, change into the `gateways_tutorial_app` generated in the
+   previous step:
 
-import numpy as np
-from matplotlib.figure import Figure
+```sh
+cd $HOME/gateways_tutorial_app
+```
 
-from cclib.parser import ccopen
+2. Run the following cookiecutter template:
+
+```sh
+cookiecutter https://github.com/machristie/cookiecutter-airavata-django-output-view.git -f
+```
+
+You'll need to answer some questions again. For `project_name` give **Gaussian
+Eigenvalues View**. For `custom_django_app_module_name`, you need to provide the
+name of the Python module that was generated by
+cookiecutter-airavata-django-app, which for this tutorial is
+**gateways_tutorial_app**. For all of the other questions you can accept the
+default.
 
-BASE_DIR = os.path.dirname(os.path.abspath(__file__))
+```
+project_name [My Custom Output View]: Gaussian Eigenvalues View
+project_slug [gaussian_eigenvalues_view]:
+project_short_description [Gaussian Eigenvalues View generates data for an output view in the Airavata Django Portal]:
+output_view_provider_class_name [GaussianEigenvaluesViewProvider]:
+custom_django_app_module_name []: gateways_tutorial_app
+output_views_directory_name [output_views]:
+Select output_view_display_type:
+1 - image
+2 - link
+3 - html
+Choose from 1, 2, 3 [1]:
+Select number_of_output_files:
+1 - single (URI)
+2 - multiple (URI_COLLECTION)
+Choose from 1, 2 [1]:
 ```
 
-2. Next we define the GaussianEigenvaluesViewProvider class, set some metadata
-   attributes on the class. We set it's `display_type` to _image_ and give it a
-   _name_:
+3. This creates a custom output view provider, called
+   GaussianEigenvaluesViewProvider, in `gateways-tutorialoutput_views/`. Open
+   `$HOME/gateways19-tutorial/gateways_tutorial_app/gateways_tutorial_app/output_views/gaussian_eigenvalues_view.py`
+   in your editor and we'll look at the generated code. The cookiecutter
+   template has generated a GaussianEigenvaluesViewProvider class with a method
+   called `generate_data`. The generate_data method has some commented out code
+   samples and links to further information. There is also guidance at the end
+   for how to prepare the values expected in the returned dictionary. Let's
+   start filling in the implementation.
+
+4. First we'll add some imports at the top. Replace the existing imports with these:
 
 ```python
-class GaussianEigenvaluesViewProvider:
-    display_type = 'image'
-    name = "Gaussian Eigenvalues"
+import io
+import os
+
+import numpy as np
+from cclib.parser import ccopen
+from django.conf import settings
+from matplotlib.figure import Figure
+
+from airavata_django_portal_sdk import user_storage
 ```
 
-3. Now we implement the
+5. Now we implement the
    [`generate_data` function](../dev/custom_output_view_provider.md#output-view-provider-interface).
    This function should return a dictionary with values that are expected for
    this `display_type`. For a display type of _image_, the required return
@@ -497,18 +566,20 @@ molecular orbital energies. Then `matplotlib` is used to create two plots of
 these values. Finally, the plots are exported as a PNG image that is returns as
 a buffer of bytes.
 
-4. Altogether, the output_views.py file should have the following contents:
+7. Altogether, the output_views/gaussian_eigenvalues_view.py file should have
+   the following contents:
 
 ```python
 import io
 import os
 
 import numpy as np
+from cclib.parser import ccopen
+from django.conf import settings
 from matplotlib.figure import Figure
 
-from cclib.parser import ccopen
+from airavata_django_portal_sdk import user_storage
 
-BASE_DIR = os.path.dirname(os.path.abspath(__file__))
 
 class GaussianEigenvaluesViewProvider:
     display_type = 'image'
@@ -561,31 +632,44 @@ class GaussianEigenvaluesViewProvider:
 
 ```
 
-5. Now we need to register our _output view provider_ with the package metadata
-   so that the Django Portal will be able to discover it. We add the following
-   lines to the `entry_points` parameter in the
-   `$HOME/gateways19-tutorial/setup.py` file:
-
-```python
-setuptools.setup(
-# ...
-    entry_points="""
-[airavata.output_view_providers]
-gaussian-eigenvalues-plot = gateways19_tutorial.output_views:GaussianEigenvaluesViewProvider
-""",
-)
+8. Now we need to register our _output view provider_ with the package metadata
+   so that the Django Portal will be able to discover it. The cookiecutter
+   template already created this when it generated the
+   gaussian_eigenvalues_view.py code. We can take a look and make sure it added
+   an `airavata.output_view_providers` entry to the `[options.entry_points]`
+   section in the `$HOME/gateways19-tutorial/gateways_tutorial_app/setup.cfg`
+   file:
+
+```ini
+[options.entry_points]
+airavata.djangoapp =
+    gateways_tutorial_app = gateways_tutorial_app.apps:GatewaysTutorialAppConfig
+airavata.output_view_providers =
+    gaussian_eigenvalues_view = gateways_tutorial_app.output_views.gaussian_eigenvalues_view:GaussianEigenvaluesViewProvider
 ```
 
-`gaussian-eigenvalues-plot` is the output view provider id.
-`gateways19_tutorial.output_views` is the module in which the
-`GaussianEigenvaluesViewProvider` output view provider class is found.
+`gaussian_eigenvalues_view` is the output view provider id.
+`gateways_tutorial_app.output_views.gaussian_eigenvalues_view` is the module in
+which the `GaussianEigenvaluesViewProvider` output view provider class is found.
+
+9. While we're looking at setup.cfg, let's add our output view providers Python
+   dependencies. Under `install_requires` add _cclib_, _numpy_ and _matplotlib_,
+   so that it looks like:
+
+```ini
+install_requires =
+    django >= 2.2
+    airavata-django-portal-sdk
+    cclib
+    numpy
+    matplotlib
+```
 
-6. Now we need to install the _gateways19-tutorial_ package into the Django
-   portal's virtual environment.
+10. Now we need to install the _gateways_tutorial_app_ package into the Django
+    portal's virtual environment.
 
 ```bash
-docker exec -w /extensions gateways19-tutorial pip install -r requirements.txt
-docker exec -w /extensions gateways19-tutorial python setup.py develop
+docker exec -w /extensions gateways19-tutorial pip install -e .
 docker exec gateways19-tutorial touch /code/django_airavata/wsgi.py
 ```
 
@@ -610,7 +694,7 @@ additional output view of the file.
 
 ```json
 {
-    "output-view-providers": ["gaussian-eigenvalues-plot"]
+    "output-view-providers": ["gaussian_eigenvalues_view"]
 }
 ```
 
@@ -633,7 +717,7 @@ declare interactive parameters that can be manipulated by the user. We can add a
 simple boolean interactive parameter to toggle the display of the matplotlib
 grid as an example.
 
-1. Open `$HOME/gateways19-tutorial/gateways19_tutorial/output_views.py`. Change
+1. Open `$HOME/gateways_tutorial_app/gateways_tutorial_app/output_views/gaussian_eigenvalues_view.py`. Change
    the `generate_data` function so that it has an additional `show_grid`
    parameter with a default value of `False`:
 
@@ -1102,15 +1186,18 @@ $("#run-button").click((e) => {
             experiment.experimentName = "Echo " + greeting;
             experiment.projectId = workspacePrefs.most_recent_project_id;
             const cloudQueue = queues.find((q) => q.queueName === queueName);
-            experiment.userConfigurationData.groupResourceProfileId = groupResourceProfileId;
-            experiment.userConfigurationData.computationalResourceScheduling.resourceHostId = resourceHostId;
+            experiment.userConfigurationData.groupResourceProfileId =
+                groupResourceProfileId;
+            experiment.userConfigurationData.computationalResourceScheduling.resourceHostId =
+                resourceHostId;
             experiment.userConfigurationData.computationalResourceScheduling.totalCPUCount =
                 cloudQueue.defaultCPUCount;
             experiment.userConfigurationData.computationalResourceScheduling.nodeCount =
                 cloudQueue.defaultNodeCount;
             experiment.userConfigurationData.computationalResourceScheduling.wallTimeLimit =
                 cloudQueue.defaultWalltime;
-            experiment.userConfigurationData.computationalResourceScheduling.queueName = queueName;
+            experiment.userConfigurationData.computationalResourceScheduling.queueName =
+                queueName;
             // Copy the selected greeting to the value of the first input
             experiment.experimentInputs[0].value = greeting;
 
@@ -1151,9 +1238,10 @@ We'll read the STDOUT file and display that in our experiment listing table.
 if (exp.experimentStatus === models.ExperimentState.COMPLETED) {
     services.FullExperimentService.retrieve({ lookup: exp.experimentId }).then(
         (fullDetails) => {
-            const stdoutDataProductId = fullDetails.experiment.experimentOutputs.find(
-                (o) => o.name === "Echo-STDOUT"
-            ).value;
+            const stdoutDataProductId =
+                fullDetails.experiment.experimentOutputs.find(
+                    (o) => o.name === "Echo-STDOUT"
+                ).value;
             const stdoutDataProduct = fullDetails.outputDataProducts.find(
                 (dp) => dp.productUri === stdoutDataProductId
             );
@@ -1173,9 +1261,10 @@ if (exp.experimentStatus === models.ExperimentState.COMPLETED) {
 if (exp.experimentStatus === models.ExperimentState.COMPLETED) {
     services.FullExperimentService.retrieve({ lookup: exp.experimentId })
         .then((fullDetails) => {
-            const stdoutDataProductId = fullDetails.experiment.experimentOutputs.find(
-                (o) => o.name === "Echo-STDOUT"
-            ).value;
+            const stdoutDataProductId =
+                fullDetails.experiment.experimentOutputs.find(
+                    (o) => o.name === "Echo-STDOUT"
+                ).value;
             const stdoutDataProduct = fullDetails.outputDataProducts.find(
                 (dp) => dp.productUri === stdoutDataProductId
             );
@@ -1220,12 +1309,14 @@ function loadExperiments() {
                     lookup: exp.experimentId,
                 })
                     .then((fullDetails) => {
-                        const stdoutDataProductId = fullDetails.experiment.experimentOutputs.find(
-                            (o) => o.name === "Echo-STDOUT"
-                        ).value;
-                        const stdoutDataProduct = fullDetails.outputDataProducts.find(
-                            (dp) => dp.productUri === stdoutDataProductId
-                        );
+                        const stdoutDataProductId =
+                            fullDetails.experiment.experimentOutputs.find(
+                                (o) => o.name === "Echo-STDOUT"
+                            ).value;
+                        const stdoutDataProduct =
+                            fullDetails.outputDataProducts.find(
+                                (dp) => dp.productUri === stdoutDataProductId
+                            );
                         if (
                             stdoutDataProduct &&
                             stdoutDataProduct.downloadURL

[airavata-django-portal] 02/10: Updated custom django app portion of tutorial to use cookiecutter

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit 61de74eb359a328dd8c3e2fc317f76e1d83087e7
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Wed Jun 9 10:03:30 2021 -0400

    Updated custom django app portion of tutorial to use cookiecutter
---
 docs/tutorial/gateways_tutorial.md | 170 ++++++++++++++++++-------------------
 1 file changed, 85 insertions(+), 85 deletions(-)

diff --git a/docs/tutorial/gateways_tutorial.md b/docs/tutorial/gateways_tutorial.md
index 1ebef32..dd985f6 100644
--- a/docs/tutorial/gateways_tutorial.md
+++ b/docs/tutorial/gateways_tutorial.md
@@ -492,7 +492,8 @@ Choose from 1, 2 [1]:
    for how to prepare the values expected in the returned dictionary. Let's
    start filling in the implementation.
 
-4. First we'll add some imports at the top. Replace the existing imports with these:
+4. First we'll add some imports at the top. Replace the existing imports with
+   these:
 
 ```python
 import io
@@ -717,8 +718,9 @@ declare interactive parameters that can be manipulated by the user. We can add a
 simple boolean interactive parameter to toggle the display of the matplotlib
 grid as an example.
 
-1. Open `$HOME/gateways_tutorial_app/gateways_tutorial_app/output_views/gaussian_eigenvalues_view.py`. Change
-   the `generate_data` function so that it has an additional `show_grid`
+1. Open
+   `$HOME/gateways_tutorial_app/gateways_tutorial_app/output_views/gaussian_eigenvalues_view.py`.
+   Change the `generate_data` function so that it has an additional `show_grid`
    parameter with a default value of `False`:
 
 ```python
@@ -798,10 +800,12 @@ Django framework as well as the Airavata Django Portal REST APIs and JS library.
 To start, we'll just create a simple "Hello World" page for the Django app and
 get it properly registered with the local Django Portal instance.
 
-1. In the `gateways19-tutorial` directory, open
-   `$HOME/gateways19-tutorial/gateways19_tutorial/templates/gateways19_tutorial/hello.html`.
-   Some of the HTML view is commented out. The following is the uncommented
-   content:
+1. In the `gateways_tutorial_app` directory, open
+   `$HOME/gateways_tutorial_app/gateways_tutorial_app/templates/gateways_tutorial_app/home.html`.
+   Copy this file to `hello.html` in the same directory.
+
+2. Change the title of the page, in the `<h1>` tag, to **Hello World** and save
+   the file.
 
 ```xml
 {% extends 'base.html' %}
@@ -817,74 +821,62 @@ get it properly registered with the local Django Portal instance.
 {% endblock content %}
 ```
 
-2. Open the file `$HOME/gateways19-tutorial/gateways19_tutorial/apps.py`:
+3. Open the file `$HOME/gateways_tutorial_app/gateways_tutorial_app/views.py`
+   and add the following `hello_world` view function at the end of the file:
 
 ```python
-from django.apps import AppConfig
-
-
-class Gateways19TutorialAppConfig(AppConfig):
-    name = 'gateways19_tutorial'
-    label = name
-    verbose_name = "Gateways Tutorial"
-    fa_icon_class = "fa-comment"
-```
-
-This the main metadata for this custom Django app. Besides the normal metadata
-that the Django framework expects, this also defines a display name
-(`verbose_name`) and an icon (`fa_icon_class`) to use for this custom app.
-
-3. Open the file `$HOME/gateways19-tutorial/gateways19_tutorial/views.py`:
-
-```python
-from django.shortcuts import render
-from django.contrib.auth.decorators import login_required
-
 
 @login_required
 def hello_world(request):
-    return render(request, "gateways19_tutorial/hello.html")
+    return render(request, "gateways_tutorial_app/hello.html")
 ```
 
 This view will simply display the template created in the previous step.
 
-4. Open the file `$HOME/gateways19-tutorial/gateways19_tutorial/urls.py`:
+4. Open the file `$HOME/gateways_tutorial_app/gateways_tutorial_app/urls.py` and
+   add a URL mapping for of `hello/` to the `hello_world` view function:
 
 ```python
-from django.conf.urls import url, include
+from django.urls import path
 
 from . import views
 
-app_name = 'gateways19_tutorial'
+app_name = 'gateways_tutorial_app'
 urlpatterns = [
-    url(r'^hello/', views.hello_world, name="home"),
+    path('home/', views.home, name='home'),
+    path('hello/', views.hello_world, name='hello_world'),
 ]
+
 ```
 
 This maps the `/hello/` URL to the `hello_world` view.
 
-5. We've created the necessary code for our Django app to display the hello
-   world page, but now we need to add some metadata to this Python package so
-   that the Django Portal knows about this Django app. In
-   `$HOME/gateways19-tutorial/setup.py`, we add the following
-   `[airavata.djangoapp]` metadata to the entry_points section:
+5. Open the file `$HOME/gateways_tutorial_app/gateways_tutorial_app/apps.py` and
+   add the `fa_icon_class` attribute and the `url_home` attribute to the
+   `GatewaysTutorialAppConfig` class:
 
 ```python
-setuptools.setup(
-# ...
-    entry_points="""
-[airavata.output_view_providers]
-gaussian-eigenvalues-plot = gateways19_tutorial.output_views:GaussianEigenvaluesViewProvider
-[airavata.djangoapp]
-gateways19_tutorial = gateways19_tutorial.apps:Gateways19TutorialAppConfig
-""",
-)
+from django.apps import AppConfig
+
+
+class GatewaysTutorialAppConfig(AppConfig):
+    name = 'gateways_tutorial_app'
+    label = name
+    verbose_name = "Gateways Tutorial App"
+    fa_icon_class = "fa-comment"
+    url_home = "gateways_tutorial_app:hello_world"
 ```
 
+This the main metadata for this custom Django app. Besides the normal metadata
+that the Django framework expects, this also defines a display name
+(`verbose_name`) and an icon (`fa_icon_class`) to use for this custom app. The
+`url_home` attribute specifies the initial view that should be rendered when
+navigating to this app.
+
 ---
 
 Now you should be able to [log into the portal locally](http://localhost:8000)
-and see **Gateways Tutorial** in the drop down menu in the header (click on
+and see **Gateways Tutorial App** in the drop down menu in the header (click on
 **Workspace** then you should see it in that menu).
 
 ![Screenshot of custom app in menu](./screenshots/gateways19/custom-app-menu.png)
@@ -894,8 +886,8 @@ and see **Gateways Tutorial** in the drop down menu in the header (click on
 Now we'll create a REST endpoint in our custom Django app that will return
 greetings in several languages.
 
-1. In the `$HOME/gateways19-tutorial/gateways19_tutorial/views.py` file, we add
-   the following import:
+1. In the `$HOME/gateways_tutorial_app/gateways_tutorial_app/views.py` file, we
+   add the following import:
 
 ```python
 from django.http import JsonResponse
@@ -927,27 +919,28 @@ def languages(request):
     }]})
 ```
 
-3. In `$HOME/gateways19-tutorial/gateways19_tutorial/urls.py` we add a url
+3. In `$HOME/gateways_tutorial_app/gateways_tutorial_app/urls.py` we add a url
    mapping for the `languages` view:
 
 ```python
 urlpatterns = [
-    url(r'^hello/', views.hello_world, name="home"),
-    url(r'^languages/', views.languages, name="languages"),
+    path('home/', views.home, name='home'),
+    path('hello/', views.hello_world, name="home"),
+    path('languages/', views.languages, name="languages"),
 ]
 ```
 
 4. In
-   `$HOME/gateways19-tutorial/gateways19_tutorial/templates/gateways19_tutorial/hello.html`,
-   uncomment the comment that starts `<!-- Adding a list of "Hello" greetings`
-   on line 11 and ends on line 21. That is, just delete lines 11 and 21. This
-   adds a `<select>` element to the template which will be used to display the
-   greeting options:
+   `$HOME/gateways_tutorial_app/gateways_tutorial_app/templates/gateways_tutorial_app/hello.html`,
+   add the lines between the **STARTING HERE** and **ENDING HERE** comments.
+   This adds a `<select>` element to the template which will be used to display
+   the greeting options:
 
 ```html
 ...
 <h1>Hello World</h1>
 
+<!-- STARTING HERE -->
 <div class="card">
     <div class="card-header">Run "echo" for different languages</div>
     <div class="card-body">
@@ -955,31 +948,30 @@ urlpatterns = [
         <button id="run-button" class="btn btn-primary">Run</button>
     </div>
 </div>
+<!-- ENDING HERE -->
 ...
 ```
 
-5. We also add the `{% load static %}` directive and then a `scripts` block to
-   the end of `hello.html`. This will load the AiravataAPI JavaScript library
+5. The `hello.html` template already has the `{% load static %}` directive and a
+   `scripts` block at the end. This will load the AiravataAPI JavaScript library
    which has utilities for interacting with the Django portal's REST API (which
    can also be used for custom developed REST endpoints) and model classes for
    Airavata's data models. The `utils.FetchUtils` is used to load the languages
    REST endpoint.
 
-```xml
-{% extends 'base.html' %}
-
-{% load static %}
-
-...
-{% endblock content %}
+    Add to `hello.html` the code between the **STARTING HERE** and **ENDING
+    HERE** comments.
 
-{% block scripts %}
+```html
+{% extends 'base.html' %} {% load static %} ... {% endblock content %} {% block
+scripts %}
 <script src="{% static 'django_airavata_api/dist/airavata-api.js' %}"></script>
 <script>
     const { models, services, session, utils } = AiravataAPI;
 
-    utils.FetchUtils.get("/gateways19_tutorial/languages/").then(data => {
-        data.languages.forEach(language => {
+    // STARTING HERE
+    utils.FetchUtils.get("/gateways_tutorial_app/languages/").then((data) => {
+        data.languages.forEach((language) => {
             $("#greeting-select").append(
                 `<option value="${language.greeting}">
                     ${language.lang} - "${language.greeting}"
@@ -987,12 +979,13 @@ urlpatterns = [
             );
         });
     });
+    // ENDING HERE
 </script>
 {% endblock scripts %}
 ```
 
 Now when you view the custom app at
-[http://localhost:8000/gateways19_tutorial/hello/](http://localhost:8000/gateways19_tutorial/hello/)
+[http://localhost:8000/gateways_tutorial_app/hello/](http://localhost:8000/gateways_tutorial_app/hello/)
 you should see a dropdown of greetings in several languages, like so:
 
 ![Screenshot of custom app with languages list](./screenshots/gateways19/custom-app-languages-list.png)
@@ -1002,13 +995,12 @@ you should see a dropdown of greetings in several languages, like so:
 Now we'll use the `AiravataAPI` library to load the user's recent experiments.
 
 1. In
-   `$HOME/gateways19-tutorial/gateways19_tutorial/templates/gateways19_tutorial/hello.html`,
-   uncomment the comment that begins with
-   `<!-- Displaying a list of recent experiments` on line 21 or so and ends on
-   line 45. This adds table to display recent experiments to the bottom of
+   `$HOME/gateways_tutorial_app/gateways_tutorial_app/templates/gateways_tutorial_app/hello.html`,
+   add the following lines between the **STARTING HERE** and **ENDING HERE**
+   comments. This adds table to display recent experiments to the bottom of
    `hello.html`:
 
-```xml
+```html
 ...
             <div class="card">
                 <div class="card-header">
@@ -1019,6 +1011,8 @@ Now we'll use the `AiravataAPI` library to load the user's recent experiments.
                     <button id="run-button" class="btn btn-primary">Run</button>
                 </div>
             </div>
+
+            <!-- STARTING HERE -->
             <div class="card">
                 <div class="card-header">
                     Experiments
@@ -1040,6 +1034,8 @@ Now we'll use the `AiravataAPI` library to load the user's recent experiments.
                     </table>
                 </div>
             </div>
+            <!-- ENDING HERE -->
+
         </div>
     </main>
 </div>
@@ -1090,12 +1086,11 @@ The user interface should now look something like:
 
 ### Submitting an Echo job
 
-Now we'll use `AiravataAPI` to submit an Echo job.
+Now we'll use `AiravataAPI` to submit an Echo job. Let's take a look at what
+we'll need to do make this work.
 
-1. In
-   `$HOME/gateways19-tutorial/gateways19_tutorial/templates/gateways19_tutorial/hello.html`
-   we add a click handler to the _Run_ button that gets the selected greeting
-   value:
+1. We'll need to add a click handler to the _Run_ button that gets the selected
+   greeting value:
 
 ```javascript
 $("#run-button").click((e) => {
@@ -1162,7 +1157,8 @@ const loadWorkspacePrefs = services.WorkspacePreferencesService.get();
 ```
 
 5. Once we have all of this information we can then create an `Experiment`
-   object then _save_ and _launch_ it. Here's the complete click handler:
+   object then _save_ and _launch_ it. Here's the complete click handler. We add
+   the following to the end of the _scripts_ block in `hello.html`:
 
 ```javascript
 $("#run-button").click((e) => {
@@ -1280,9 +1276,9 @@ if (exp.experimentStatus === models.ExperimentState.COMPLETED) {
 }
 ```
 
-3. To enable this, remove the comment starting with
-   `/* Displaying the experiment output` on line 88 and ending on line 113.
-   Here's the update to the `loadExperiments` function:
+3. To enable this, add the lines between the **STARTING HERE** and **ENDING
+   HERE** comments to the `loadExperiments` function. Here's the update to the
+   `loadExperiments` function:
 
 ```javascript
 function loadExperiments() {
@@ -1303,6 +1299,8 @@ function loadExperiments() {
                             <td id="output_${index}"></td>
                         </tr>`
             );
+
+            // STARTING HERE
             // If experiment has finished, load full details, then parse the stdout file
             if (exp.experimentStatus === models.ExperimentState.COMPLETED) {
                 services.FullExperimentService.retrieve({
@@ -1330,6 +1328,8 @@ function loadExperiments() {
                         $(`#output_${index}`).text(text);
                     });
             }
+            // ENDING HERE
+
         });
     });
 }

[airavata-django-portal] 09/10: tutorial: Python on Windows instructions

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit 0236c1f523c3335e5102e364cd5459813ecf4c69
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Wed Jun 16 14:37:18 2021 -0400

    tutorial: Python on Windows instructions
---
 docs/tutorial/custom_ui_tutorial.md | 97 ++++++++++++++++++++++++++++++++-----
 requirements.txt                    |  2 +-
 2 files changed, 85 insertions(+), 14 deletions(-)

diff --git a/docs/tutorial/custom_ui_tutorial.md b/docs/tutorial/custom_ui_tutorial.md
index dedf9c7..1f3422c 100644
--- a/docs/tutorial/custom_ui_tutorial.md
+++ b/docs/tutorial/custom_ui_tutorial.md
@@ -8,11 +8,14 @@ both simple and complex customizations to the user interface.
 Tutorial attendees should have:
 
 -   a laptop on which to write Python code
--   Python
+-   Python 3.9
 -   Git client
--   [Docker desktop for Windows and macOS](https://www.docker.com/products/docker-desktop)
-    or
-    [Docker Engine for Linux](https://hub.docker.com/search?q=&type=edition&offering=community)
+-   For running the Airavata Django Portal locally, either:
+    -   [Docker desktop for Windows and macOS](https://www.docker.com/products/docker-desktop)
+        or
+        [Docker Engine for Linux](https://hub.docker.com/search?q=&type=edition&offering=community)
+    -   Or, Python 3.9 and [Node LTS](https://nodejs.org/en/download/) and
+        [Yarn package manager](https://yarnpkg.com/getting-started/install).
 
 !!! note "Special note for Windows Home users"
 
@@ -436,8 +439,7 @@ if you are interested).
 
 1. Make sure you have
    [Docker installed](https://www.docker.com/products/docker-desktop).
-2. Run the following to create a Docker container called
-   **custom-ui-tutorial**.
+2. Run the following to create a Docker container called **custom-ui-tutorial**.
 
 ```
 cd $HOME
@@ -478,6 +480,62 @@ docker run -d --name custom-ui-tutorial -p 8000:8000 -v "$PWD:/extensions" -v "$
 docker exec custom-ui-tutorial python manage.py load_cms_data new_default_theme
 ```
 
+#### Python/Windows instructions
+
+Verify that you have the following installled
+
+-   Python 3.9
+-   Node LTS
+-   Yarn
+-   Git
+
+The following instructions assume that you start in your home directory, but you
+could technically checkout and build the code anywhere.
+
+1. Clone the custom_ui_tutorial_app and airavata-django-portal repositories.
+
+```text
+(tutorial-env) C:\Users\machrist>cd %HOMEDRIVE%%HOMEPATH%
+
+(tutorial-env) C:\Users\machrist>git clone https://github.com/machristie/custom_ui_tutorial_app.git custom_ui_tutorial_app-final
+
+(tutorial-env) C:\Users\machrist>git clone https://github.com/apache/airavata-django-portal.git
+```
+
+2. Install the airavata-django-portal dependencies.
+
+```text
+(tutorial-env) C:\Users\machrist>cd airavata-django-portal
+
+(tutorial-env) C:\Users\machrist\airavata-django-portal>pip install -U pip
+
+(tutorial-env) C:\Users\machrist\airavata-django-portal>pip install -r requirements.txt
+```
+
+3. Copy in the settings_local.py file.
+
+```text
+(tutorial-env) C:\Users\machrist\airavata-django-portal>copy ..\custom_ui_tutorial_app-final\settings_local.py django_airavata\
+```
+
+4. Run Django database migrations
+
+```text
+(tutorial-env) C:\Users\machrist\airavata-django-portal>python manage.py migrate
+```
+
+5. Load the default Wagtail CMS pages.
+
+```text
+(tutorial-env) C:\Users\machrist\airavata-django-portal>python manage.py load_cms_data new_default_theme
+```
+
+6. Build the JavaScript frontend code.
+
+```text
+(tutorial-env) C:\Users\machrist\airavata-django-portal>build_js.bat
+```
+
 ---
 
 Go to [http://localhost:8000](http://localhost:8000), click on **Login in**,
@@ -528,7 +586,8 @@ Choose from 1, 2 [1]:
 ```
 
 3. This creates a custom output view provider, called
-   GaussianEigenvaluesViewProvider, in `custom_ui_tutorial_app/output_views/`. Open
+   GaussianEigenvaluesViewProvider, in `custom_ui_tutorial_app/output_views/`.
+   Open
    `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/output_views/gaussian_eigenvalues_view.py`
    in your editor and we'll look at the generated code. The cookiecutter
    template has generated a GaussianEigenvaluesViewProvider class with a method
@@ -713,6 +772,8 @@ install_requires =
 10. Now we need to install the _custom_ui_tutorial_app_ package into the Django
     portal's virtual environment.
 
+Docker instructions:
+
 ```bash
 docker exec -w /extensions custom-ui-tutorial pip install -e .
 docker exec custom-ui-tutorial touch /code/django_airavata/wsgi.py
@@ -724,6 +785,16 @@ These commands:
    container's Python environment, and
 2. touches the wsgi.py to trigger a reload of the Django portal dev server.
 
+Python/Windows instructions:
+
+```text
+(tutorial-env) C:\Users\machrist\airavata-django-portal>cd ..\custom_ui_tutorial_app
+
+(tutorial-env) C:\Users\machrist\custom_ui_tutorial_app>pip install -e .
+
+(tutorial-env) C:\Users\machrist\airavata-django-portal>python manage.py runserver
+```
+
 ### Use the GaussianEigenvaluesViewProvider with the Gaussian log output file
 
 Back in the Django Portal, we'll make sure the application interface for
@@ -877,8 +948,8 @@ def hello_world(request):
 
 This view will simply display the template created in the previous step.
 
-4. Open the file `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/urls.py` and
-   add a URL mapping for of `hello/` to the `hello_world` view function:
+4. Open the file `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/urls.py`
+   and add a URL mapping for of `hello/` to the `hello_world` view function:
 
 ```python
 from django.urls import path
@@ -895,8 +966,8 @@ urlpatterns = [
 
 This maps the `/hello/` URL to the `hello_world` view.
 
-5. Open the file `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/apps.py` and
-   add the `fa_icon_class` attribute and the `url_home` attribute to the
+5. Open the file `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/apps.py`
+   and add the `fa_icon_class` attribute and the `url_home` attribute to the
    `CustomUiTutorialAppConfig` class:
 
 ```python
@@ -930,8 +1001,8 @@ and see **Custom UI Tutorial App** in the drop down menu in the header (click on
 Now we'll create a REST endpoint in our custom Django app that will return
 greetings in several languages.
 
-1. In the `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/views.py` file, we
-   add the following import:
+1. In the `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/views.py` file,
+   we add the following import:
 
 ```python
 from django.http import JsonResponse
diff --git a/requirements.txt b/requirements.txt
index 1d50ed9..5367544 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,6 +1,6 @@
 # Pin these dependencies
 Django>=2.2,<2.3
-requests==2.13.0
+requests==2.23.0
 requests-oauthlib==0.7.0
 thrift==0.10.0
 thrift_connector==0.24

[airavata-django-portal] 07/10: tutorial: updated screenshots

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit 3b1142986410f65183a8c03387a043153c93fc62
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Tue Jun 15 10:29:43 2021 -0400

    tutorial: updated screenshots
---
 docs/tutorial/custom_ui_tutorial.md                    |   6 +++---
 .../tutorial/screenshots/custom-ui/custom-app-menu.png | Bin 0 -> 177809 bytes
 .../custom-ui/gaussian-output-view-providers-json.png  | Bin 0 -> 31419 bytes
 docs/tutorial/screenshots/custom-ui/settings_menu.png  | Bin 0 -> 181704 bytes
 4 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/docs/tutorial/custom_ui_tutorial.md b/docs/tutorial/custom_ui_tutorial.md
index 2eb5afd..dedf9c7 100644
--- a/docs/tutorial/custom_ui_tutorial.md
+++ b/docs/tutorial/custom_ui_tutorial.md
@@ -137,7 +137,7 @@ customize the user interface used for application inputs.
 1. In the portal, click on the dropdown menu at the top right (currently
    **Workspace** is likely selected) and select **Settings**.
 
-![Screenshot of Settings menu](./screenshots/gateways19/settings_menu.png)
+![Screenshot of Settings menu](./screenshots/custom-ui/settings_menu.png)
 
 2. You should see the _Application Catalog_. Click on the **New Application**
    button.
@@ -745,7 +745,7 @@ additional output view of the file.
 
 It should look something like this:
 
-![Screenshot of Gaussian log output-view-providers json](./screenshots/gateways19/gaussian-output-view-providers-json.png)
+![Screenshot of Gaussian log output-view-providers json](./screenshots/custom-ui/gaussian-output-view-providers-json.png)
 
 7. Go back to the **Workspace** using the menu at the top.
 8. Select your Gaussian16 experiment from the right sidebar.
@@ -923,7 +923,7 @@ Now you should be able to [log into the portal locally](http://localhost:8000)
 and see **Custom UI Tutorial App** in the drop down menu in the header (click on
 **Workspace** then you should see it in that menu).
 
-![Screenshot of custom app in menu](./screenshots/gateways19/custom-app-menu.png)
+![Screenshot of custom app in menu](./screenshots/custom-ui/custom-app-menu.png)
 
 ### Adding a list of "Hello" greetings
 
diff --git a/docs/tutorial/screenshots/custom-ui/custom-app-menu.png b/docs/tutorial/screenshots/custom-ui/custom-app-menu.png
new file mode 100644
index 0000000..8a3374b
Binary files /dev/null and b/docs/tutorial/screenshots/custom-ui/custom-app-menu.png differ
diff --git a/docs/tutorial/screenshots/custom-ui/gaussian-output-view-providers-json.png b/docs/tutorial/screenshots/custom-ui/gaussian-output-view-providers-json.png
new file mode 100644
index 0000000..1211bb8
Binary files /dev/null and b/docs/tutorial/screenshots/custom-ui/gaussian-output-view-providers-json.png differ
diff --git a/docs/tutorial/screenshots/custom-ui/settings_menu.png b/docs/tutorial/screenshots/custom-ui/settings_menu.png
new file mode 100644
index 0000000..af57532
Binary files /dev/null and b/docs/tutorial/screenshots/custom-ui/settings_menu.png differ

[airavata-django-portal] 05/10: tutorial: minor fixes

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit 8a22eecb9f8c414cc7873fd1cfaf9175ef754d91
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Fri Jun 11 13:29:28 2021 -0400

    tutorial: minor fixes
---
 docs/tutorial/gateways_tutorial.md | 44 ++++++++++++++++++++++----------------
 1 file changed, 26 insertions(+), 18 deletions(-)

diff --git a/docs/tutorial/gateways_tutorial.md b/docs/tutorial/gateways_tutorial.md
index 1f31c17..863dbc8 100644
--- a/docs/tutorial/gateways_tutorial.md
+++ b/docs/tutorial/gateways_tutorial.md
@@ -22,21 +22,22 @@ Python 3.6-3.9 are supported, but I highly recommend you download and use
 1. Download and install Python 3.9.
     - (macOS/Windows): Download from https://www.python.org/downloads/
     - (Linux): use your distribution's package manager to install Python 3.9
-2. (macOS/Linux) Verify you have installed Python 3.9. Open a terminal and run `python3.9 --version`.
+2. (macOS/Linux) Verify you have installed Python 3.9. Open a terminal and run
+   `python3.9 --version`.
 
 ```
 $ python3.9 --version
 Python 3.9.5
 ```
 
-3. (Windows) Verify you have installed Python 3.9. Open `cmd` and run `py --version`:
+3. (Windows) Verify you have installed Python 3.9. Open `cmd` and run
+   `py --version`:
 
 ```text
 C:\Users\machrist>py --version
 Python 3.9.5
 ```
 
-
 !!! note "Special note for Windows Home users"
 
     If you have Windows Home installed, you'll need to either use a **remote
@@ -719,9 +720,9 @@ docker exec gateways19-tutorial touch /code/django_airavata/wsgi.py
 
 These commands:
 
-1. install our package's dependencies,
-2. install the package into the container's Python environment, and
-3. touches the wsgi.py to trigger a reload of the Django portal dev server.
+1. install our custom django app package and its dependencies into the
+   container's Python environment, and
+2. touches the wsgi.py to trigger a reload of the Django portal dev server.
 
 ### Use the GaussianEigenvaluesViewProvider with the Gaussian log output file
 
@@ -981,17 +982,25 @@ urlpatterns = [
 
 ```html
 ...
-<h1>Hello World</h1>
-
-<!-- STARTING HERE -->
-<div class="card">
-    <div class="card-header">Run "echo" for different languages</div>
-    <div class="card-body">
-        <select id="greeting-select"></select>
-        <button id="run-button" class="btn btn-primary">Run</button>
-    </div>
+<div class="main-content-wrapper">
+    <main class="main-content">
+        <div class="container-fluid">
+            <h1>Hello World</h1>
+
+            <!-- STARTING HERE -->
+            <div class="card">
+                <div class="card-header">
+                    Run "echo" for different languages
+                </div>
+                <div class="card-body">
+                    <select id="greeting-select"></select>
+                    <button id="run-button" class="btn btn-primary">Run</button>
+                </div>
+            </div>
+            <!-- ENDING HERE -->
+        </div>
+    </main>
 </div>
-<!-- ENDING HERE -->
 ...
 ```
 
@@ -1006,8 +1015,7 @@ urlpatterns = [
     HERE** comments.
 
 ```html
-{% extends 'base.html' %} {% load static %} ... {% endblock content %} {% block
-scripts %}
+{% block scripts %}
 <script src="{% static 'django_airavata_api/dist/airavata-api.js' %}"></script>
 <script>
     const { models, services, session, utils } = AiravataAPI;

[airavata-django-portal] 04/10: tutorial instructions on installing Python and creating venv on all OSes

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit 5f0ee98814d34fba77afca5413d21fc6bf5fda9e
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Fri Jun 11 12:56:48 2021 -0400

    tutorial instructions on installing Python and creating venv on all OSes
---
 docs/tutorial/gateways_tutorial.md | 55 +++++++++++++++++++++++++++++++++-----
 1 file changed, 49 insertions(+), 6 deletions(-)

diff --git a/docs/tutorial/gateways_tutorial.md b/docs/tutorial/gateways_tutorial.md
index b5155bf..1f31c17 100644
--- a/docs/tutorial/gateways_tutorial.md
+++ b/docs/tutorial/gateways_tutorial.md
@@ -8,11 +8,35 @@ both simple and complex customizations to the user interface.
 Tutorial attendees should have:
 
 -   a laptop on which to write Python code
+-   Python
 -   Git client
 -   [Docker desktop for Windows and macOS](https://www.docker.com/products/docker-desktop)
     or
     [Docker Engine for Linux](https://hub.docker.com/search?q=&type=edition&offering=community)
 
+### Installing Python
+
+Python 3.6-3.9 are supported, but I highly recommend you download and use
+**Python 3.9**
+
+1. Download and install Python 3.9.
+    - (macOS/Windows): Download from https://www.python.org/downloads/
+    - (Linux): use your distribution's package manager to install Python 3.9
+2. (macOS/Linux) Verify you have installed Python 3.9. Open a terminal and run `python3.9 --version`.
+
+```
+$ python3.9 --version
+Python 3.9.5
+```
+
+3. (Windows) Verify you have installed Python 3.9. Open `cmd` and run `py --version`:
+
+```text
+C:\Users\machrist>py --version
+Python 3.9.5
+```
+
+
 !!! note "Special note for Windows Home users"
 
     If you have Windows Home installed, you'll need to either use a **remote
@@ -355,17 +379,37 @@ We have a local develop environment created. Now we can start adding custom
 code. First, we'll create a custom Django app, which is the standard way to
 package a Django extension.
 
-1. Install the latest version of cookiecutter. Cookiecutter is a tool for
+1. (macOS/Linux) Create and activate a Python virtual environment
+
+```bash
+$ cd $HOME
+$ python3.9 -m venv tutorial-env
+$ source tutorial-env/bin/activate
+(tutorial-env) $
+```
+
+2. (Windows) Create and activate a Python virtual environment
+
+```text
+C:\Users\machrist>cd %HOMEDRIVE%%HOMEPATH%
+
+C:\Users\machrist>py -m venv tutorial-env
+
+C:\Users\machrist>tutorial-env\Scripts\activate.bat
+
+(tutorial-env) C:\Users\machrist>
+```
+
+3. Install the latest version of cookiecutter. Cookiecutter is a tool for
    generating project source code from a template.
 
 ```sh
-pip install --user -U cookiecutter
+pip install -U cookiecutter
 ```
 
-2. Use cookiecutter to run the Airavata Django app template.
+4. Use cookiecutter to run the Airavata Django app template.
 
 ```sh
-cd $HOME
 cookiecutter https://github.com/machristie/cookiecutter-airavata-django-app.git
 ```
 
@@ -638,8 +682,7 @@ class GaussianEigenvaluesViewProvider:
    template already created this when it generated the
    gaussian_eigenvalues_view.py code. We can take a look and make sure it added
    an `airavata.output_view_providers` entry to the `[options.entry_points]`
-   section in the `$HOME/gateways_tutorial_app/setup.cfg`
-   file:
+   section in the `$HOME/gateways_tutorial_app/setup.cfg` file:
 
 ```ini
 [options.entry_points]

[airavata-django-portal] 06/10: tutorial: rename to "custom ui tutorial"

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit f63d5c8931b788d8e2c2f10eb6fba6b4ebd89bba
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Mon Jun 14 10:32:41 2021 -0400

    tutorial: rename to "custom ui tutorial"
---
 ...{gateways_tutorial.md => custom_ui_tutorial.md} | 122 ++++++++++-----------
 mkdocs.yml                                         |   2 +-
 2 files changed, 62 insertions(+), 62 deletions(-)

diff --git a/docs/tutorial/gateways_tutorial.md b/docs/tutorial/custom_ui_tutorial.md
similarity index 94%
rename from docs/tutorial/gateways_tutorial.md
rename to docs/tutorial/custom_ui_tutorial.md
index 863dbc8..2eb5afd 100644
--- a/docs/tutorial/gateways_tutorial.md
+++ b/docs/tutorial/custom_ui_tutorial.md
@@ -1,4 +1,4 @@
-# Gateways Tutorial
+# Custom UI Tutorial
 
 Objective: learn the basics of the Apache Airavata Django Portal and how to make
 both simple and complex customizations to the user interface.
@@ -14,6 +14,22 @@ Tutorial attendees should have:
     or
     [Docker Engine for Linux](https://hub.docker.com/search?q=&type=edition&offering=community)
 
+!!! note "Special note for Windows Home users"
+
+    If you have Windows Home installed, you'll need to either use a **remote
+    Docker host** (recommended) or take some extra steps to setup WSL2
+    (Windows Subsystem for Linux 2). The following are some special
+    instructions to help you with these options:
+
+    1. (**Recommended**) For the in person session of the tutorial, you will
+    have the option of using a **remote Docker host** provided to you. See
+    [Appendix: Setting up Windows Home for a remote Docker
+    host](#appendix-setting-up-windows-for-a-remote-docker-host) for more
+    details.
+    2. (**Advanced**) [Install Docker Desktop on Windows Home with WSL2
+    enabled](https://docs.docker.com/docker-for-windows/install-windows-home/).
+    See the link for more information.
+
 ### Installing Python
 
 Python 3.6-3.9 are supported, but I highly recommend you download and use
@@ -38,22 +54,6 @@ C:\Users\machrist>py --version
 Python 3.9.5
 ```
 
-!!! note "Special note for Windows Home users"
-
-    If you have Windows Home installed, you'll need to either use a **remote
-    Docker host** (recommended) or take some extra steps to setup WSL2
-    (Windows Subsystem for Linux 2). The following are some special
-    instructions to help you with these options:
-
-    1. (**Recommended**) For the in person session of the tutorial, you will
-    have the option of using a **remote Docker host** provided to you. See
-    [Appendix: Setting up Windows Home for a remote Docker
-    host](#appendix-setting-up-windows-for-a-remote-docker-host) for more
-    details.
-    2. (**Advanced**) [Install Docker Desktop on Windows Home with WSL2
-    enabled](https://docs.docker.com/docker-for-windows/install-windows-home/).
-    See the link for more information.
-
 ## Outline
 
 -   Introduction
@@ -415,14 +415,14 @@ cookiecutter https://github.com/machristie/cookiecutter-airavata-django-app.git
 ```
 
 You'll need to answer some questions. You can name it whatever you want, but to
-follow along with the tutorial, for `project_name` give **Gateways Tutorial
+follow along with the tutorial, for `project_name` give **Custom UI Tutorial
 App**. For the rest of the questions, you can simply accept the defaults:
 
 ```
-project_name [My Custom Django App]: Gateways Tutorial App
-project_slug [gateways_tutorial_app]:
+project_name [My Custom Django App]: Custom UI Tutorial App
+project_slug [custom_ui_tutorial_app]:
 project_short_description [Custom Django app with everything needed to be installed in the airavata-django-portal]:
-app_config_class_name [GatewaysTutorialAppConfig]:
+app_config_class_name [CustomUiTutorialAppConfig]:
 version [0.1.0]:
 ```
 
@@ -437,13 +437,13 @@ if you are interested).
 1. Make sure you have
    [Docker installed](https://www.docker.com/products/docker-desktop).
 2. Run the following to create a Docker container called
-   **gateways19-tutorial**.
+   **custom-ui-tutorial**.
 
 ```
 cd $HOME
-git clone https://github.com/machristie/gateways_tutorial_app.git gateways_tutorial_app-final
-cd gateways_tutorial_app
-docker run -d --name gateways19-tutorial -p 8000:8000 -v "$PWD:/extensions" -v "$PWD/../gateways_tutorial_app-final/settings_local.py:/code/django_airavata/settings_local.py" machristie/airavata-django-portal
+git clone https://github.com/machristie/custom_ui_tutorial_app.git custom_ui_tutorial_app-final
+cd custom_ui_tutorial_app
+docker run -d --name custom-ui-tutorial -p 8000:8000 -v "$PWD:/extensions" -v "$PWD/../custom_ui_tutorial_app-final/settings_local.py:/code/django_airavata/settings_local.py" machristie/airavata-django-portal
 ```
 
 !!! note "For remote Docker host users"
@@ -475,7 +475,7 @@ docker run -d --name gateways19-tutorial -p 8000:8000 -v "$PWD:/extensions" -v "
 3. Run the following to load the default set of CMS pages:
 
 ```
-docker exec gateways19-tutorial python manage.py load_cms_data new_default_theme
+docker exec custom-ui-tutorial python manage.py load_cms_data new_default_theme
 ```
 
 ---
@@ -489,11 +489,11 @@ experiments listed on the right hand side.
 Now we'll also generate and implement a **Gaussian Eigenvalues View** provider.
 
 1. We'll run another cookiecutter template to generate the output view provider
-   code. First, change into the `gateways_tutorial_app` generated in the
+   code. First, change into the `custom_ui_tutorial_app` generated in the
    previous step:
 
 ```sh
-cd $HOME/gateways_tutorial_app
+cd $HOME/custom_ui_tutorial_app
 ```
 
 2. Run the following cookiecutter template:
@@ -506,7 +506,7 @@ You'll need to answer some questions again. For `project_name` give **Gaussian
 Eigenvalues View**. For `custom_django_app_module_name`, you need to provide the
 name of the Python module that was generated by
 cookiecutter-airavata-django-app, which for this tutorial is
-**gateways_tutorial_app**. For all of the other questions you can accept the
+**custom_ui_tutorial_app**. For all of the other questions you can accept the
 default.
 
 ```
@@ -514,7 +514,7 @@ project_name [My Custom Output View]: Gaussian Eigenvalues View
 project_slug [gaussian_eigenvalues_view]:
 project_short_description [Gaussian Eigenvalues View generates data for an output view in the Airavata Django Portal]:
 output_view_provider_class_name [GaussianEigenvaluesViewProvider]:
-custom_django_app_module_name []: gateways_tutorial_app
+custom_django_app_module_name []: custom_ui_tutorial_app
 output_views_directory_name [output_views]:
 Select output_view_display_type:
 1 - image
@@ -528,8 +528,8 @@ Choose from 1, 2 [1]:
 ```
 
 3. This creates a custom output view provider, called
-   GaussianEigenvaluesViewProvider, in `gateways-tutorialoutput_views/`. Open
-   `$HOME/gateways_tutorial_app/gateways_tutorial_app/output_views/gaussian_eigenvalues_view.py`
+   GaussianEigenvaluesViewProvider, in `custom_ui_tutorial_app/output_views/`. Open
+   `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/output_views/gaussian_eigenvalues_view.py`
    in your editor and we'll look at the generated code. The cookiecutter
    template has generated a GaussianEigenvaluesViewProvider class with a method
    called `generate_data`. The generate_data method has some commented out code
@@ -683,18 +683,18 @@ class GaussianEigenvaluesViewProvider:
    template already created this when it generated the
    gaussian_eigenvalues_view.py code. We can take a look and make sure it added
    an `airavata.output_view_providers` entry to the `[options.entry_points]`
-   section in the `$HOME/gateways_tutorial_app/setup.cfg` file:
+   section in the `$HOME/custom_ui_tutorial_app/setup.cfg` file:
 
 ```ini
 [options.entry_points]
 airavata.djangoapp =
-    gateways_tutorial_app = gateways_tutorial_app.apps:GatewaysTutorialAppConfig
+    custom_ui_tutorial_app = custom_ui_tutorial_app.apps:CustomUiTutorialAppConfig
 airavata.output_view_providers =
-    gaussian_eigenvalues_view = gateways_tutorial_app.output_views.gaussian_eigenvalues_view:GaussianEigenvaluesViewProvider
+    gaussian_eigenvalues_view = custom_ui_tutorial_app.output_views.gaussian_eigenvalues_view:GaussianEigenvaluesViewProvider
 ```
 
 `gaussian_eigenvalues_view` is the output view provider id.
-`gateways_tutorial_app.output_views.gaussian_eigenvalues_view` is the module in
+`custom_ui_tutorial_app.output_views.gaussian_eigenvalues_view` is the module in
 which the `GaussianEigenvaluesViewProvider` output view provider class is found.
 
 9. While we're looking at setup.cfg, let's add our output view providers Python
@@ -710,12 +710,12 @@ install_requires =
     matplotlib
 ```
 
-10. Now we need to install the _gateways_tutorial_app_ package into the Django
+10. Now we need to install the _custom_ui_tutorial_app_ package into the Django
     portal's virtual environment.
 
 ```bash
-docker exec -w /extensions gateways19-tutorial pip install -e .
-docker exec gateways19-tutorial touch /code/django_airavata/wsgi.py
+docker exec -w /extensions custom-ui-tutorial pip install -e .
+docker exec custom-ui-tutorial touch /code/django_airavata/wsgi.py
 ```
 
 These commands:
@@ -763,7 +763,7 @@ simple boolean interactive parameter to toggle the display of the matplotlib
 grid as an example.
 
 1. Open
-   `$HOME/gateways_tutorial_app/gateways_tutorial_app/output_views/gaussian_eigenvalues_view.py`.
+   `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/output_views/gaussian_eigenvalues_view.py`.
    Change the `generate_data` function so that it has an additional `show_grid`
    parameter with a default value of `False`:
 
@@ -844,8 +844,8 @@ Django framework as well as the Airavata Django Portal REST APIs and JS library.
 To start, we'll just create a simple "Hello World" page for the Django app and
 get it properly registered with the local Django Portal instance.
 
-1. In the `gateways_tutorial_app` directory, open
-   `$HOME/gateways_tutorial_app/gateways_tutorial_app/templates/gateways_tutorial_app/home.html`.
+1. In the `custom_ui_tutorial_app` directory, open
+   `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/templates/custom_ui_tutorial_app/home.html`.
    Copy this file to `hello.html` in the same directory.
 
 2. Change the title of the page, in the `<h1>` tag, to **Hello World** and save
@@ -865,19 +865,19 @@ get it properly registered with the local Django Portal instance.
 {% endblock content %}
 ```
 
-3. Open the file `$HOME/gateways_tutorial_app/gateways_tutorial_app/views.py`
+3. Open the file `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/views.py`
    and add the following `hello_world` view function at the end of the file:
 
 ```python
 
 @login_required
 def hello_world(request):
-    return render(request, "gateways_tutorial_app/hello.html")
+    return render(request, "custom_ui_tutorial_app/hello.html")
 ```
 
 This view will simply display the template created in the previous step.
 
-4. Open the file `$HOME/gateways_tutorial_app/gateways_tutorial_app/urls.py` and
+4. Open the file `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/urls.py` and
    add a URL mapping for of `hello/` to the `hello_world` view function:
 
 ```python
@@ -885,7 +885,7 @@ from django.urls import path
 
 from . import views
 
-app_name = 'gateways_tutorial_app'
+app_name = 'custom_ui_tutorial_app'
 urlpatterns = [
     path('home/', views.home, name='home'),
     path('hello/', views.hello_world, name='hello_world'),
@@ -895,20 +895,20 @@ urlpatterns = [
 
 This maps the `/hello/` URL to the `hello_world` view.
 
-5. Open the file `$HOME/gateways_tutorial_app/gateways_tutorial_app/apps.py` and
+5. Open the file `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/apps.py` and
    add the `fa_icon_class` attribute and the `url_home` attribute to the
-   `GatewaysTutorialAppConfig` class:
+   `CustomUiTutorialAppConfig` class:
 
 ```python
 from django.apps import AppConfig
 
 
-class GatewaysTutorialAppConfig(AppConfig):
-    name = 'gateways_tutorial_app'
+class CustomUiTutorialAppConfig(AppConfig):
+    name = 'custom_ui_tutorial_app'
     label = name
-    verbose_name = "Gateways Tutorial App"
+    verbose_name = "Custom UI Tutorial App"
     fa_icon_class = "fa-comment"
-    url_home = "gateways_tutorial_app:hello_world"
+    url_home = "custom_ui_tutorial_app:hello_world"
 ```
 
 This the main metadata for this custom Django app. Besides the normal metadata
@@ -920,7 +920,7 @@ navigating to this app.
 ---
 
 Now you should be able to [log into the portal locally](http://localhost:8000)
-and see **Gateways Tutorial App** in the drop down menu in the header (click on
+and see **Custom UI Tutorial App** in the drop down menu in the header (click on
 **Workspace** then you should see it in that menu).
 
 ![Screenshot of custom app in menu](./screenshots/gateways19/custom-app-menu.png)
@@ -930,7 +930,7 @@ and see **Gateways Tutorial App** in the drop down menu in the header (click on
 Now we'll create a REST endpoint in our custom Django app that will return
 greetings in several languages.
 
-1. In the `$HOME/gateways_tutorial_app/gateways_tutorial_app/views.py` file, we
+1. In the `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/views.py` file, we
    add the following import:
 
 ```python
@@ -963,7 +963,7 @@ def languages(request):
     }]})
 ```
 
-3. In `$HOME/gateways_tutorial_app/gateways_tutorial_app/urls.py` we add a url
+3. In `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/urls.py` we add a url
    mapping for the `languages` view:
 
 ```python
@@ -975,7 +975,7 @@ urlpatterns = [
 ```
 
 4. In
-   `$HOME/gateways_tutorial_app/gateways_tutorial_app/templates/gateways_tutorial_app/hello.html`,
+   `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/templates/custom_ui_tutorial_app/hello.html`,
    add the lines between the **STARTING HERE** and **ENDING HERE** comments.
    This adds a `<select>` element to the template which will be used to display
    the greeting options:
@@ -1021,7 +1021,7 @@ urlpatterns = [
     const { models, services, session, utils } = AiravataAPI;
 
     // STARTING HERE
-    utils.FetchUtils.get("/gateways_tutorial_app/languages/").then((data) => {
+    utils.FetchUtils.get("/custom_ui_tutorial_app/languages/").then((data) => {
         data.languages.forEach((language) => {
             $("#greeting-select").append(
                 `<option value="${language.greeting}">
@@ -1036,7 +1036,7 @@ urlpatterns = [
 ```
 
 Now when you view the custom app at
-[http://localhost:8000/gateways_tutorial_app/hello/](http://localhost:8000/gateways_tutorial_app/hello/)
+[http://localhost:8000/custom_ui_tutorial_app/hello/](http://localhost:8000/custom_ui_tutorial_app/hello/)
 you should see a dropdown of greetings in several languages, like so:
 
 ![Screenshot of custom app with languages list](./screenshots/gateways19/custom-app-languages-list.png)
@@ -1046,7 +1046,7 @@ you should see a dropdown of greetings in several languages, like so:
 Now we'll use the `AiravataAPI` library to load the user's recent experiments.
 
 1. In
-   `$HOME/gateways_tutorial_app/gateways_tutorial_app/templates/gateways_tutorial_app/hello.html`,
+   `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/templates/custom_ui_tutorial_app/hello.html`,
    add the following lines between the **STARTING HERE** and **ENDING HERE**
    comments. This adds table to display recent experiments to the bottom of
    `hello.html`:
@@ -1261,7 +1261,7 @@ $("#run-button").click((e) => {
 Now that we can launch the experiment we can go ahead and give it a try.
 
 You can also try this out in the production deployment at
-<https://testdrive.airavata.org/gateways19_tutorial/hello/>.
+<https://testdrive.airavata.org/custom_ui_tutorial_app/hello/>.
 
 ### Displaying the experiment output
 
@@ -1388,7 +1388,7 @@ function loadExperiments() {
 ## Resources
 
 You can browser the final version of the code at
-<https://github.com/machristie/gateways_tutorial_app>.
+<https://github.com/machristie/custom_ui_tutorial_app>.
 
 ### Airavata API
 
diff --git a/mkdocs.yml b/mkdocs.yml
index a7ae5a0..6b17256 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -13,7 +13,7 @@ nav:
     - Developing the Backend: dev/developing_backend.md
     - Developing a Wagtail Export (theme): dev/wagtail_export.md
   - Customization Guide:
-    - Gateways Tutorial: tutorial/gateways_tutorial.md
+    - Custom UI Tutorial: tutorial/custom_ui_tutorial.md
     - Adding a Custom Django App: dev/custom_django_app.md
     - Adding a Custom Output View Provider: dev/custom_output_view_provider.md
   - Administrator Guide:

[airavata-django-portal] 08/10: Compatibility for building JS on Windows

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit 31b34c360c49d5007b801a72ea3c9c0972f6a9d9
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Wed Jun 16 11:31:57 2021 -0400

    Compatibility for building JS on Windows
---
 build_js.bat                               |  36 +++
 django_airavata/static/common/package.json |   3 +-
 django_airavata/static/common/yarn.lock    | 387 +++++++++++++++++------------
 3 files changed, 269 insertions(+), 157 deletions(-)

diff --git a/build_js.bat b/build_js.bat
new file mode 100644
index 0000000..f6206bc
--- /dev/null
+++ b/build_js.bat
@@ -0,0 +1,36 @@
+
+echo Running production JS builds
+
+set cwd=%cd%
+
+cd %cwd%\django_airavata\apps\api
+call yarn
+call yarn run build
+
+cd %cwd%\django_airavata\static\common
+call yarn
+call yarn run build
+
+cd %cwd%\django_airavata\apps\admin
+call yarn
+call yarn run build
+
+cd %cwd%\django_airavata\apps\groups
+call yarn
+call yarn run build
+
+cd %cwd%\django_airavata\apps\workspace\django-airavata-workspace-plugin-api
+call yarn
+call yarn run build
+
+cd %cwd%\django_airavata\apps\workspace
+call yarn
+call yarn run build
+
+cd %cwd%\django_airavata\apps\dataparsers
+call yarn
+call yarn run build
+
+cd %cwd%
+
+echo All builds finished successfully!
\ No newline at end of file
diff --git a/django_airavata/static/common/package.json b/django_airavata/static/common/package.json
index c2d1bbb..42de7eb 100644
--- a/django_airavata/static/common/package.json
+++ b/django_airavata/static/common/package.json
@@ -10,7 +10,7 @@
     "watch": "vue-cli-service build --watch --mode production",
     "build": "npm run build-app && npm run build-lib",
     "build-app": "vue-cli-service build",
-    "build-lib": "LIBRARY_MODE=true vue-cli-service build --target lib --name CommonUI --no-clean ./js/components.js",
+    "build-lib": "cross-env LIBRARY_MODE=true vue-cli-service build --target lib --name CommonUI --no-clean ./js/components.js",
     "lint": "vue-cli-service lint ./js/",
     "lint:visualstudio": "vue-cli-service lint --format visualstudio ./js/",
     "format": "prettier --check --write ."
@@ -38,6 +38,7 @@
     "@vue/cli-plugin-eslint": "^3.1.1",
     "@vue/cli-service": "^3.1.1",
     "babel-eslint": "^10.0.1",
+    "cross-env": "^7.0.3",
     "eslint": "^5.8.0",
     "eslint-plugin-vue": "^5.0.0-0",
     "file-loader": "^3.0.1",
diff --git a/django_airavata/static/common/yarn.lock b/django_airavata/static/common/yarn.lock
index 1780a2d..8f7b6a7 100644
--- a/django_airavata/static/common/yarn.lock
+++ b/django_airavata/static/common/yarn.lock
@@ -1316,7 +1316,7 @@ ajv@^5.2.3, ajv@^5.3.0:
     fast-json-stable-stringify "^2.0.0"
     json-schema-traverse "^0.3.0"
 
-ajv@^6.1.0, ajv@^6.10.2, ajv@^6.5.5, ajv@^6.9.1:
+ajv@^6.1.0, ajv@^6.10.2, ajv@^6.9.1:
   version "6.10.2"
   resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52"
   integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==
@@ -1326,6 +1326,16 @@ ajv@^6.1.0, ajv@^6.10.2, ajv@^6.5.5, ajv@^6.9.1:
     json-schema-traverse "^0.4.1"
     uri-js "^4.2.2"
 
+ajv@^6.12.3:
+  version "6.12.6"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
+  integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
+  dependencies:
+    fast-deep-equal "^3.1.1"
+    fast-json-stable-stringify "^2.0.0"
+    json-schema-traverse "^0.4.1"
+    uri-js "^4.2.2"
+
 alphanum-sort@^1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3"
@@ -1566,9 +1576,9 @@ aws-sign2@~0.7.0:
   integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
 
 aws4@^1.8.0:
-  version "1.8.0"
-  resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
-  integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==
+  version "1.11.0"
+  resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
+  integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
 
 babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
   version "6.26.0"
@@ -1620,9 +1630,9 @@ babel-plugin-module-resolver@3.2.0:
     resolve "^1.4.0"
 
 balanced-match@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
-  integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+  integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
 
 base64-js@^1.0.2:
   version "1.3.1"
@@ -2014,11 +2024,6 @@ camelcase@^2.0.0:
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
   integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=
 
-camelcase@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
-  integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo=
-
 camelcase@^5.0.0:
   version "5.3.1"
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
@@ -2209,15 +2214,6 @@ clipboardy@^2.0.0:
     arch "^2.1.1"
     execa "^1.0.0"
 
-cliui@^3.2.0:
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
-  integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=
-  dependencies:
-    string-width "^1.0.1"
-    strip-ansi "^3.0.1"
-    wrap-ansi "^2.0.0"
-
 cliui@^4.0.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
@@ -2544,6 +2540,13 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
     safe-buffer "^5.0.1"
     sha.js "^2.4.8"
 
+cross-env@^7.0.3:
+  version "7.0.3"
+  resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf"
+  integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==
+  dependencies:
+    cross-spawn "^7.0.1"
+
 cross-spawn@^3.0.0:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982"
@@ -2581,6 +2584,15 @@ cross-spawn@^7.0.0:
     shebang-command "^2.0.0"
     which "^2.0.1"
 
+cross-spawn@^7.0.1:
+  version "7.0.3"
+  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
+  integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
+  dependencies:
+    path-key "^3.1.0"
+    shebang-command "^2.0.0"
+    which "^2.0.1"
+
 crypto-browserify@^3.11.0:
   version "3.12.0"
   resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
@@ -2831,7 +2843,7 @@ debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
   dependencies:
     ms "^2.1.1"
 
-decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0:
+decamelize@^1.1.2, decamelize@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
   integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
@@ -3649,6 +3661,11 @@ fast-deep-equal@^2.0.1:
   resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
   integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
 
+fast-deep-equal@^3.1.1:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
+  integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
 fast-glob@^2.2.6:
   version "2.2.7"
   resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d"
@@ -3662,9 +3679,9 @@ fast-glob@^2.2.6:
     micromatch "^3.1.10"
 
 fast-json-stable-stringify@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
-  integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
+  integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
 
 fast-levenshtein@~2.0.6:
   version "2.0.6"
@@ -4040,7 +4057,19 @@ glob-to-regexp@^0.3.0:
   resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
   integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=
 
-glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1:
+glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@~7.1.1:
+  version "7.1.7"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
+  integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^3.0.4"
+    once "^1.3.0"
+    path-is-absolute "^1.0.0"
+
+glob@^7.1.4:
   version "7.1.6"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
   integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
@@ -4095,9 +4124,9 @@ globby@^9.2.0:
     slash "^2.0.0"
 
 globule@^1.0.0:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.1.tgz#5dffb1b191f22d20797a9369b49eab4e9839696d"
-  integrity sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.2.tgz#d8bdd9e9e4eef8f96e245999a5dee7eb5d8529c4"
+  integrity sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==
   dependencies:
     glob "~7.1.1"
     lodash "~4.17.10"
@@ -4110,11 +4139,16 @@ good-listener@^1.2.2:
   dependencies:
     delegate "^3.1.2"
 
-graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6:
+graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.6:
   version "4.2.3"
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
   integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
 
+graceful-fs@^4.1.2:
+  version "4.2.6"
+  resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
+  integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
+
 gzip-size@^5.0.0:
   version "5.1.1"
   resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274"
@@ -4133,12 +4167,12 @@ har-schema@^2.0.0:
   resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
   integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
 
-har-validator@~5.1.0:
-  version "5.1.3"
-  resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080"
-  integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==
+har-validator@~5.1.3:
+  version "5.1.5"
+  resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
+  integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==
   dependencies:
-    ajv "^6.5.5"
+    ajv "^6.12.3"
     har-schema "^2.0.0"
 
 has-ansi@^2.0.0:
@@ -4257,9 +4291,9 @@ hoopy@^0.1.4:
   integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==
 
 hosted-git-info@^2.1.4:
-  version "2.8.5"
-  resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c"
-  integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==
+  version "2.8.9"
+  resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
+  integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
 
 hpack.js@^2.1.6:
   version "2.1.6"
@@ -4504,9 +4538,9 @@ imurmurhash@^0.1.4:
   integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
 
 in-publish@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51"
-  integrity sha1-4g/146KvwmkDILbcVSaCqcf631E=
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.1.tgz#948b1a535c8030561cea522f73f78f4be357e00c"
+  integrity sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==
 
 indent-string@^2.1.0:
   version "2.1.0"
@@ -4607,11 +4641,6 @@ invariant@^2.2.2:
   dependencies:
     loose-envify "^1.0.0"
 
-invert-kv@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
-  integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY=
-
 invert-kv@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
@@ -4712,6 +4741,13 @@ is-color-stop@^1.0.0:
     rgb-regex "^1.0.1"
     rgba-regex "^1.0.0"
 
+is-core-module@^2.2.0:
+  version "2.4.0"
+  resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.4.0.tgz#8e9fc8e15027b011418026e98f0e6f4d86305cc1"
+  integrity sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==
+  dependencies:
+    has "^1.0.3"
+
 is-data-descriptor@^0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
@@ -4772,11 +4808,9 @@ is-extglob@^2.1.0, is-extglob@^2.1.1:
   integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
 
 is-finite@^1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
-  integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=
-  dependencies:
-    number-is-nan "^1.0.0"
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3"
+  integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==
 
 is-fullwidth-code-point@^1.0.0:
   version "1.0.0"
@@ -4950,7 +4984,12 @@ jquery@^3.3.1:
   resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2"
   integrity sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==
 
-js-base64@^2.1.8, js-base64@^2.4.9:
+js-base64@^2.1.8:
+  version "2.6.4"
+  resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4"
+  integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==
+
+js-base64@^2.4.9:
   version "2.5.1"
   resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121"
   integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==
@@ -5120,13 +5159,6 @@ launch-editor@^2.2.1:
     chalk "^2.3.0"
     shell-quote "^1.6.1"
 
-lcid@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
-  integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=
-  dependencies:
-    invert-kv "^1.0.0"
-
 lcid@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf"
@@ -5298,7 +5330,12 @@ lodash.uniqby@4.5.0:
     lodash._baseiteratee "~4.7.0"
     lodash._baseuniq "~4.6.0"
 
-lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.3.0, lodash@~4.17.10:
+lodash@^4.0.0, lodash@^4.17.15, lodash@~4.17.10:
+  version "4.17.21"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
+  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
+
+lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.3.0:
   version "4.17.15"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
   integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
@@ -5513,6 +5550,11 @@ mime-db@1.42.0, "mime-db@>= 1.40.0 < 2":
   resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac"
   integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==
 
+mime-db@1.48.0:
+  version "1.48.0"
+  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.48.0.tgz#e35b31045dd7eada3aaad537ed88a33afbef2d1d"
+  integrity sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==
+
 mime-match@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/mime-match/-/mime-match-1.0.2.tgz#3f87c31e9af1a5fd485fb9db134428b23bbb7ba8"
@@ -5520,7 +5562,14 @@ mime-match@^1.0.2:
   dependencies:
     wildcard "^1.1.0"
 
-mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24:
+mime-types@^2.1.12, mime-types@~2.1.19:
+  version "2.1.31"
+  resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.31.tgz#a00d76b74317c61f9c2db2218b8e9f8e9c5c9e6b"
+  integrity sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==
+  dependencies:
+    mime-db "1.48.0"
+
+mime-types@~2.1.17, mime-types@~2.1.24:
   version "2.1.25"
   resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.25.tgz#39772d46621f93e2a80a856c53b86a62156a6437"
   integrity sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==
@@ -5579,7 +5628,12 @@ minimist@0.0.8:
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
   integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
 
-minimist@^1.1.3, minimist@^1.2.0:
+minimist@^1.1.3, minimist@^1.2.5:
+  version "1.2.5"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
+  integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
+
+minimist@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
   integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
@@ -5639,13 +5693,20 @@ mixin-deep@^1.2.0:
     for-in "^1.0.2"
     is-extendable "^1.0.1"
 
-mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1:
+mkdirp@0.5.1, mkdirp@~0.5.1:
   version "0.5.1"
   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
   integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
   dependencies:
     minimist "0.0.8"
 
+"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1:
+  version "0.5.5"
+  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
+  integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
+  dependencies:
+    minimist "^1.2.5"
+
 moment@^2.24.0:
   version "2.24.0"
   resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
@@ -5710,11 +5771,16 @@ namespace-emitter@^2.0.1:
   resolved "https://registry.yarnpkg.com/namespace-emitter/-/namespace-emitter-2.0.1.tgz#978d51361c61313b4e6b8cf6f3853d08dfa2b17c"
   integrity sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==
 
-nan@^2.12.1, nan@^2.13.2:
+nan@^2.12.1:
   version "2.14.0"
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
   integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
 
+nan@^2.13.2:
+  version "2.14.2"
+  resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
+  integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
+
 nanomatch@^1.2.9:
   version "1.2.13"
   resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
@@ -5858,9 +5924,9 @@ node-releases@^1.1.40:
     semver "^6.3.0"
 
 node-sass@^4.11.0:
-  version "4.13.0"
-  resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.13.0.tgz#b647288babdd6a1cb726de4545516b31f90da066"
-  integrity sha512-W1XBrvoJ1dy7VsvTAS5q1V45lREbTlZQqFbiHb3R3OTTCma0XBtuG6xZ6Z4506nR4lmHPTqVRwxT6KgtWC97CA==
+  version "4.14.1"
+  resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.14.1.tgz#99c87ec2efb7047ed638fb4c9db7f3a42e2217b5"
+  integrity sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==
   dependencies:
     async-foreach "^0.1.3"
     chalk "^1.1.1"
@@ -5876,7 +5942,7 @@ node-sass@^4.11.0:
     node-gyp "^3.8.0"
     npmlog "^4.0.0"
     request "^2.88.0"
-    sass-graph "^2.2.4"
+    sass-graph "2.2.5"
     stdout-stream "^1.4.0"
     "true-case-path" "^1.0.2"
 
@@ -6175,13 +6241,6 @@ os-homedir@^1.0.0:
   resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
   integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
 
-os-locale@^1.4.0:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9"
-  integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=
-  dependencies:
-    lcid "^1.0.0"
-
 os-locale@^3.0.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
@@ -6416,9 +6475,9 @@ path-key@^3.0.0, path-key@^3.1.0:
   integrity sha512-8cChqz0RP6SHJkMt48FW0A7+qUOn+OsnOsVtzI59tZ8m+5bCSk7hzwET0pulwOM2YMn9J1efb07KB9l9f30SGg==
 
 path-parse@^1.0.6:
-  version "1.0.6"
-  resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
-  integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
+  integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
 
 path-to-regexp@0.1.7:
   version "0.1.7"
@@ -6968,7 +7027,7 @@ pseudomap@^1.0.2:
   resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
   integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
 
-psl@^1.1.24, psl@^1.1.28:
+psl@^1.1.28:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2"
   integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==
@@ -7015,7 +7074,7 @@ punycode@1.3.2:
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
   integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
 
-punycode@^1.2.4, punycode@^1.4.1:
+punycode@^1.2.4:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
   integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
@@ -7130,7 +7189,7 @@ read-pkg@^5.0.0:
     parse-json "^5.0.0"
     type-fest "^0.6.0"
 
-"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
+"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
   version "2.3.6"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
   integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
@@ -7143,6 +7202,19 @@ read-pkg@^5.0.0:
     string_decoder "~1.1.1"
     util-deprecate "~1.0.1"
 
+readable-stream@^2.0.1, readable-stream@^2.0.6:
+  version "2.3.7"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
+  integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
+  dependencies:
+    core-util-is "~1.0.0"
+    inherits "~2.0.3"
+    isarray "~1.0.0"
+    process-nextick-args "~2.0.0"
+    safe-buffer "~5.1.1"
+    string_decoder "~1.1.1"
+    util-deprecate "~1.0.1"
+
 readable-stream@^3.0.6, readable-stream@^3.1.1:
   version "3.4.0"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc"
@@ -7318,9 +7390,9 @@ request-promise-native@^1.0.7:
     tough-cookie "^2.3.3"
 
 request@^2.87.0, request@^2.88.0:
-  version "2.88.0"
-  resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
-  integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
+  version "2.88.2"
+  resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
+  integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
   dependencies:
     aws-sign2 "~0.7.0"
     aws4 "^1.8.0"
@@ -7329,7 +7401,7 @@ request@^2.87.0, request@^2.88.0:
     extend "~3.0.2"
     forever-agent "~0.6.1"
     form-data "~2.3.2"
-    har-validator "~5.1.0"
+    har-validator "~5.1.3"
     http-signature "~1.2.0"
     is-typedarray "~1.0.0"
     isstream "~0.1.2"
@@ -7339,7 +7411,7 @@ request@^2.87.0, request@^2.88.0:
     performance-now "^2.1.0"
     qs "~6.5.2"
     safe-buffer "^5.1.2"
-    tough-cookie "~2.4.3"
+    tough-cookie "~2.5.0"
     tunnel-agent "^0.6.0"
     uuid "^3.3.2"
 
@@ -7403,7 +7475,15 @@ resolve-url@^0.2.1:
   resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
   integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
 
-resolve@^1.10.0, resolve@^1.12.0, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.8.1:
+resolve@^1.10.0:
+  version "1.20.0"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
+  integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
+  dependencies:
+    is-core-module "^2.2.0"
+    path-parse "^1.0.6"
+
+resolve@^1.12.0, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.8.1:
   version "1.12.0"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6"
   integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==
@@ -7503,11 +7583,16 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
   integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
 
-safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0:
+safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.2.0:
   version "5.2.0"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
   integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==
 
+safe-buffer@^5.0.1, safe-buffer@^5.1.2:
+  version "5.2.1"
+  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+  integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
 safe-regex@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
@@ -7520,15 +7605,15 @@ safe-regex@^1.1.0:
   resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
   integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
 
-sass-graph@^2.2.4:
-  version "2.2.4"
-  resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49"
-  integrity sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=
+sass-graph@2.2.5:
+  version "2.2.5"
+  resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.5.tgz#a981c87446b8319d96dce0671e487879bd24c2e8"
+  integrity sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==
   dependencies:
     glob "^7.0.0"
     lodash "^4.0.0"
     scss-tokenizer "^0.2.3"
-    yargs "^7.0.0"
+    yargs "^13.3.2"
 
 sass-loader@^7.1.0:
   version "7.3.1"
@@ -7716,7 +7801,12 @@ shell-quote@^1.6.1:
   resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2"
   integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==
 
-signal-exit@^3.0.0, signal-exit@^3.0.2:
+signal-exit@^3.0.0:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
+  integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
+
+signal-exit@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
   integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
@@ -7863,30 +7953,30 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
   integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
 
 spdx-correct@^3.0.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4"
-  integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"
+  integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==
   dependencies:
     spdx-expression-parse "^3.0.0"
     spdx-license-ids "^3.0.0"
 
 spdx-exceptions@^2.1.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977"
-  integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d"
+  integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==
 
 spdx-expression-parse@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0"
-  integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
+  integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
   dependencies:
     spdx-exceptions "^2.1.0"
     spdx-license-ids "^3.0.0"
 
 spdx-license-ids@^3.0.0:
-  version "3.0.5"
-  resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654"
-  integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==
+  version "3.0.9"
+  resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz#8a595135def9592bda69709474f1cbeea7c2467f"
+  integrity sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==
 
 spdy-transport@^3.0.0:
   version "3.0.0"
@@ -8048,7 +8138,7 @@ strict-uri-encode@^1.0.0:
   resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
   integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
 
-string-width@^1.0.1, string-width@^1.0.2:
+string-width@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
   integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
@@ -8440,7 +8530,7 @@ toposort@^1.0.0:
   resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029"
   integrity sha1-LmhELZ9k7HILjMieZEOsbKqVACk=
 
-tough-cookie@^2.3.3:
+tough-cookie@^2.3.3, tough-cookie@~2.5.0:
   version "2.5.0"
   resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
   integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
@@ -8448,14 +8538,6 @@ tough-cookie@^2.3.3:
     psl "^1.1.28"
     punycode "^2.1.1"
 
-tough-cookie@~2.4.3:
-  version "2.4.3"
-  resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
-  integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==
-  dependencies:
-    psl "^1.1.24"
-    punycode "^1.4.1"
-
 trim-newlines@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
@@ -8632,9 +8714,9 @@ upper-case@^1.1.1:
   integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=
 
 uri-js@^4.2.2:
-  version "4.2.2"
-  resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
-  integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==
+  version "4.4.1"
+  resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
+  integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
   dependencies:
     punycode "^2.1.0"
 
@@ -8710,11 +8792,16 @@ utils-merge@1.0.1:
   resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
   integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
 
-uuid@^3.0.1, uuid@^3.3.2:
+uuid@^3.0.1:
   version "3.3.3"
   resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866"
   integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==
 
+uuid@^3.3.2:
+  version "3.4.0"
+  resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
+  integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
+
 validate-npm-package-license@^3.0.1:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
@@ -8993,11 +9080,6 @@ websocket-extensions@>=0.1.1:
   resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29"
   integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==
 
-which-module@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
-  integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=
-
 which-module@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
@@ -9098,11 +9180,6 @@ xtend@^4.0.0, xtend@~4.0.1:
   resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
   integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
 
-y18n@^3.2.1:
-  version "3.2.1"
-  resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
-  integrity sha1-bRX7qITAhnnA136I53WegR4H+kE=
-
 "y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
@@ -9126,6 +9203,14 @@ yargs-parser@^11.1.1:
     camelcase "^5.0.0"
     decamelize "^1.2.0"
 
+yargs-parser@^13.1.2:
+  version "13.1.2"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38"
+  integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==
+  dependencies:
+    camelcase "^5.0.0"
+    decamelize "^1.2.0"
+
 yargs-parser@^16.1.0:
   version "16.1.0"
   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-16.1.0.tgz#73747d53ae187e7b8dbe333f95714c76ea00ecf1"
@@ -9134,13 +9219,6 @@ yargs-parser@^16.1.0:
     camelcase "^5.0.0"
     decamelize "^1.2.0"
 
-yargs-parser@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a"
-  integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=
-  dependencies:
-    camelcase "^3.0.0"
-
 yargs@12.0.5:
   version "12.0.5"
   resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13"
@@ -9159,6 +9237,22 @@ yargs@12.0.5:
     y18n "^3.2.1 || ^4.0.0"
     yargs-parser "^11.1.1"
 
+yargs@^13.3.2:
+  version "13.3.2"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
+  integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==
+  dependencies:
+    cliui "^5.0.0"
+    find-up "^3.0.0"
+    get-caller-file "^2.0.1"
+    require-directory "^2.1.1"
+    require-main-filename "^2.0.0"
+    set-blocking "^2.0.0"
+    string-width "^3.0.0"
+    which-module "^2.0.0"
+    y18n "^4.0.0"
+    yargs-parser "^13.1.2"
+
 yargs@^15.0.0:
   version "15.0.2"
   resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.0.2.tgz#4248bf218ef050385c4f7e14ebdf425653d13bd3"
@@ -9176,25 +9270,6 @@ yargs@^15.0.0:
     y18n "^4.0.0"
     yargs-parser "^16.1.0"
 
-yargs@^7.0.0:
-  version "7.1.0"
-  resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8"
-  integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=
-  dependencies:
-    camelcase "^3.0.0"
-    cliui "^3.2.0"
-    decamelize "^1.1.1"
-    get-caller-file "^1.0.1"
-    os-locale "^1.4.0"
-    read-pkg-up "^1.0.1"
-    require-directory "^2.1.1"
-    require-main-filename "^1.0.1"
-    set-blocking "^2.0.0"
-    string-width "^1.0.2"
-    which-module "^1.0.0"
-    y18n "^3.2.1"
-    yargs-parser "^5.0.0"
-
 yorkie@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/yorkie/-/yorkie-2.0.0.tgz#92411912d435214e12c51c2ae1093e54b6bb83d9"