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/09/17 18:31:56 UTC

[airavata-django-portal] branch master updated: tutorial: adding copy to clipboard buttons

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


The following commit(s) were added to refs/heads/master by this push:
     new dd523d2  tutorial: adding copy to clipboard buttons
dd523d2 is described below

commit dd523d243718f360ba4cf158b31b5d0528ac4840
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Fri Sep 17 14:31:35 2021 -0400

    tutorial: adding copy to clipboard buttons
---
 docs/tutorial/custom_ui_tutorial.md | 191 +++++++++++++++++++++++++++++++-----
 1 file changed, 167 insertions(+), 24 deletions(-)

diff --git a/docs/tutorial/custom_ui_tutorial.md b/docs/tutorial/custom_ui_tutorial.md
index b2a9f22..6c5290a 100644
--- a/docs/tutorial/custom_ui_tutorial.md
+++ b/docs/tutorial/custom_ui_tutorial.md
@@ -341,6 +341,11 @@ the application inputs' user interface. What we'll do:
 3. For _Target ID_ (input #1), in the _Advanced Input Field Modification
    Metadata_ box, add the following JSON configuration:
 
+<button class="btn" data-clipboard-target="#target_id">
+    Copy to clipboard
+</button>
+
+<div id="target_id">
 ```json
 {
     "editor": {
@@ -363,6 +368,7 @@ the application inputs' user interface. What we'll do:
     }
 }
 ```
+</div>
 
 It should look something like this:
 
@@ -378,6 +384,11 @@ This JSON configuration customizes the input editor in two ways:
    Libraries_** (input #3), set the _Advanced Input Field Modification Metadata_
    to:
 
+<button class="btn" data-clipboard-target="#screening_libraries">
+    Copy to clipboard
+</button>
+
+<div id="screening_libraries">
 ```json
 {
     "editor": {
@@ -421,6 +432,7 @@ This JSON configuration customizes the input editor in two ways:
     }
 }
 ```
+</div>
 
 This JSON configuration specifies a different UI component to use as the input
 editor, the `checkbox-input-editor`. It also provides a list of text/value pairs
@@ -430,6 +442,10 @@ command line arguments.
 5. Similarly for the _Visualization scripts_ (input #4), provide the following
    JSON configuration:
 
+<button class="btn" data-clipboard-target="#visualization_scripts">
+    Copy to clipboard
+</button>
+<div id="visualization_scripts">
 ```json
 {
     "editor": {
@@ -453,6 +469,7 @@ command line arguments.
     }
 }
 ```
+</div>
 
 6. Click **Save** at the bottom of the page.
 7. Now, go back to the **Workspace** and on the Dashboard click on your
@@ -912,7 +929,11 @@ which the `GaussianEigenvaluesViewProvider` output view provider class is found.
    dependencies. Under `install_requires` add _cclib_, _numpy_ and _matplotlib_,
    so that it looks like:
 
-```ini
+<button class="btn" data-clipboard-target="#install_requires">
+    Copy to clipboard
+</button>
+<div id="install_requires">
+```
 install_requires =
     django >= 2.2
     airavata-django-portal-sdk
@@ -920,6 +941,7 @@ install_requires =
     numpy
     matplotlib
 ```
+</div>
 
 10. Now we need to install the _custom_ui_tutorial_app_ package into the Django
     portal's virtual environment.
@@ -1093,18 +1115,26 @@ get it properly registered with the local Django Portal instance.
 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:
 
+<button class="btn" data-clipboard-target="#hello_world">
+    Copy to clipboard
+</button>
+<div id="hello_world">
 ```python
-
 @login_required
 def hello_world(request):
     return render(request, "custom_ui_tutorial_app/hello.html")
 ```
+</div>
 
 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:
 
+<button class="btn" data-clipboard-target="#urlspy">
+    Copy to clipboard
+</button>
+<div id="urlspy">
 ```python
 from django.urls import path
 
@@ -1115,8 +1145,8 @@ urlpatterns = [
     path('home/', views.home, name='home'),
     path('hello/', views.hello_world, name='hello_world'),
 ]
-
 ```
+</div>
 
 This maps the `/hello/` URL to the `hello_world` view.
 
@@ -1124,6 +1154,10 @@ This maps the `/hello/` URL to the `hello_world` view.
    and update the `fa_icon_class` attribute and the `url_home` attribute to the
    `CustomUiTutorialAppConfig` class:
 
+<button class="btn" data-clipboard-target="#appspy">
+    Copy to clipboard
+</button>
+<div id="appspy">
 ```python
 from django.apps import AppConfig
 
@@ -1135,6 +1169,7 @@ class CustomUiTutorialAppConfig(AppConfig):
     fa_icon_class = "fa-comment"
     url_home = "custom_ui_tutorial_app:hello_world"
 ```
+</div>
 
 This the main metadata for this custom Django app. Besides the normal metadata
 that the Django framework expects, this also defines a display name
@@ -1158,12 +1193,21 @@ greetings in several languages.
 1. In the `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/views.py` file,
    we add the following import:
 
+<button class="btn" data-clipboard-target="#jsonresponse">
+    Copy to clipboard
+</button>
+<div id="jsonresponse">
 ```python
 from django.http import JsonResponse
 ```
+</div>
 
 2. Also we add the following view:
 
+<button class="btn" data-clipboard-target="#languages">
+    Copy to clipboard
+</button>
+<div id="languages">
 ```python
 @login_required
 def languages(request):
@@ -1187,17 +1231,28 @@ def languages(request):
         'greeting': 'merhaba'
     }]})
 ```
+</div>
 
 3. In `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/urls.py` we add a url
    mapping for the `languages` view:
 
+<button class="btn" data-clipboard-target="#urls_languages">
+    Copy to clipboard
+</button>
+<div id="urls_languages">
 ```python
+from django.urls import path
+
+from . import views
+
+app_name = 'custom_ui_tutorial_app'
 urlpatterns = [
     path('home/', views.home, name='home'),
-    path('hello/', views.hello_world, name="home"),
+    path('hello/', views.hello_world, name="hello_world"),
     path('languages/', views.languages, name="languages"),
 ]
 ```
+</div>
 
 4. In
    `$HOME/custom_ui_tutorial_app/custom_ui_tutorial_app/templates/custom_ui_tutorial_app/hello.html`,
@@ -1229,6 +1284,23 @@ urlpatterns = [
 ...
 ```
 
+<button class="btn" data-clipboard-target="#greeting-select">
+    Copy to clipboard
+</button>
+<div id="greeting-select">
+```html
+            <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>
+```
+</div>
+
 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
@@ -1239,6 +1311,7 @@ urlpatterns = [
     Add to `hello.html` the code between the **STARTING HERE** and **ENDING
     HERE** comments.
 
+
 ```html
 {% block scripts %}
 <script src="{% static 'django_airavata_api/dist/airavata-api.js' %}"></script>
@@ -1260,6 +1333,23 @@ urlpatterns = [
 {% endblock scripts %}
 ```
 
+<button class="btn" data-clipboard-target="#fetch_languages">
+    Copy to clipboard
+</button>
+<div id="fetch_languages">
+```javascript
+    utils.FetchUtils.get("/custom_ui_tutorial_app/languages/").then((data) => {
+        data.languages.forEach((language) => {
+            $("#greeting-select").append(
+                `<option value="${language.greeting}">
+                    ${language.lang} - "${language.greeting}"
+                 </option>`
+            );
+        });
+    });
+```
+</div>
+
 Now when you view the custom app at
 [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:
@@ -1318,13 +1408,44 @@ Now we'll use the `AiravataAPI` library to load the user's recent experiments.
 {% endblock content %}
 ```
 
+<button class="btn" data-clipboard-target="#experiments-table">
+    Copy to clipboard
+</button>
+<div id="experiments-table">
+```html
+            <div class="card">
+                <div class="card-header">
+                    Experiments
+                </div>
+                <div class="card-body">
+                    <button id="refresh-button" class="btn btn-secondary">Refresh</button>
+                    <table class="table">
+                        <thead>
+                            <tr>
+                                <th scope="col">Name</th>
+                                <th scope="col">Application</th>
+                                <th scope="col">Creation Time</th>
+                                <th scope="col">Status</th>
+                                <th scope="col">Output</th>
+                            </tr>
+                        </thead>
+                        <tbody id="experiment-list">
+                        </tbody>
+                    </table>
+                </div>
+            </div>
+```
+</div>
+
 2. Now we'll use the ExperimentSearchService to load the user's most recent 5
    _Echo_ experiments and display them in the table. We add the following to the
    end of the _scripts_ block in `hello.html`:
 
+<button class="btn" data-clipboard-target="#loadExperiments">
+    Copy to clipboard
+</button>
+<div id="loadExperiments">
 ```javascript
-    // ...
-    // STARTING HERE
     const appInterfaceId = "Echo_23d67491-1bef-47bd-a0f5-faf069e09773";
 
     async function loadExperiments() {
@@ -1351,12 +1472,8 @@ Now we'll use the `AiravataAPI` library to load the user's recent experiments.
 
     loadExperiments();
     $("#refresh-button").click(loadExperiments);
-    // ENDING HERE
-
-</script>
-
-{% endblock scripts %}
 ```
+</div>
 
 The user interface should now look something like:
 
@@ -1369,10 +1486,11 @@ then examine it line by line to see what it is doing.
 
 1. Add the following to the end of the _scripts_ block in `hello.html`:
 
+<button class="btn" data-clipboard-target="#submitExperiment">
+    Copy to clipboard
+</button>
+<div id="submitExperiment">
 ```javascript
-// ...
-
-// STARTING HERE
     async function submitExperiment(greeting) {
         // Construct experiment object
         const experimentData = await utils.ExperimentUtils.createExperiment({
@@ -1397,13 +1515,8 @@ then examine it line by line to see what it is doing.
     }
 
     $("#run-button").click(runClickHandler);
-
-// ENDING HERE
-
-</script>
-
-{% endblock scripts %}
 ```
+</div>
 
 2. Going line by line we'll now take a look at this code. We added a click
    handler to the _Run_ button that gets the selected greeting value:
@@ -1575,10 +1688,13 @@ async function loadExperiments() {
             const stdoutInput = experiment.getExperimentOutput("Echo-STDOUT");
             const dataProductURI = stdoutInput.value;
             try {
-                const stdout = await utils.ExperimentUtils.readDataProduct(
-                    dataProductURI
-                );
-                $(`#output_${index}`).text(stdout);
+                const stdout = await utils.ExperimentUtils.readDataProduct(dataProductURI);
+                // if stdout is null, it means the file wasn't found
+                if (stdout !== null) {
+                    $(`#output_${index}`).text(stdout);
+                } else {
+                    $(`#output_${index}`).text("N/A");
+                }
             } catch (error) {
                 $(`#output_${index}`).text("N/A");
             }
@@ -1588,6 +1704,33 @@ async function loadExperiments() {
 }
 ```
 
+<button class="btn" data-clipboard-target="#readDataProduct">
+    Copy to clipboard
+</button>
+<div id="readDataProduct">
+```javascript
+        // If experiment has finished, download and display the stdout file contents
+        if (expSummary.experimentStatus === models.ExperimentState.COMPLETED) {
+            const experiment = await services.ExperimentService.retrieve({
+                lookup: expSummary.experimentId,
+            });
+            const stdoutInput = experiment.getExperimentOutput("Echo-STDOUT");
+            const dataProductURI = stdoutInput.value;
+            try {
+                const stdout = await utils.ExperimentUtils.readDataProduct(dataProductURI);
+                // if stdout is null, it means the file wasn't found
+                if (stdout !== null) {
+                    $(`#output_${index}`).text(stdout);
+                } else {
+                    $(`#output_${index}`).text("N/A");
+                }
+            } catch (error) {
+                $(`#output_${index}`).text("N/A");
+            }
+        }
+```
+</div>
+
 ## Resources
 
 You can browser the final version of the code at