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 2018/01/31 15:13:39 UTC

[airavata-django-portal] branch master updated (550884b -> 9c4d83b)

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 550884b  AIRAVATA-2615 List job details in experiment summary
     new 07a0770  AIRAVATA-2614 Map searchExperiments to ViewSet, Serializer
     new bcdfad1  AIRAVATA-2614 Sort imports
     new 9c4d83b  AIRAVATA-2614 Experiment list view

The 3 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:
 django_airavata/apps/api/serializers.py            | 43 +++++++----
 .../api/static/django_airavata_api/js/index.js     |  2 +
 .../js/models/ExperimentSummary.js                 | 28 ++++++++
 .../js/services/ExperimentSearchService.js         | 21 ++++++
 django_airavata/apps/api/urls.py                   |  1 +
 django_airavata/apps/api/views.py                  | 21 ++++++
 .../js/containers/ExperimentListContainer.vue      | 84 ++++++++++++++++++++++
 .../js/entry-experiment-list.js                    | 25 +++++++
 .../experiments_list.html                          | 13 +++-
 django_airavata/apps/workspace/views.py            | 21 ++++--
 django_airavata/apps/workspace/webpack.config.js   |  1 +
 11 files changed, 237 insertions(+), 23 deletions(-)
 create mode 100644 django_airavata/apps/api/static/django_airavata_api/js/models/ExperimentSummary.js
 create mode 100644 django_airavata/apps/api/static/django_airavata_api/js/services/ExperimentSearchService.js
 create mode 100644 django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/ExperimentListContainer.vue
 create mode 100644 django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-experiment-list.js

-- 
To stop receiving notification emails like this one, please contact
machristie@apache.org.

[airavata-django-portal] 03/03: AIRAVATA-2614 Experiment list view

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 9c4d83ba16f202c842af1cd35c24419bcd5206af
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Wed Jan 31 10:13:31 2018 -0500

    AIRAVATA-2614 Experiment list view
---
 django_airavata/apps/api/serializers.py            |  1 +
 .../api/static/django_airavata_api/js/index.js     |  2 +
 .../js/models/ExperimentSummary.js                 | 28 ++++++++
 .../js/services/ExperimentSearchService.js         | 21 ++++++
 .../js/containers/ExperimentListContainer.vue      | 84 ++++++++++++++++++++++
 .../js/entry-experiment-list.js                    | 25 +++++++
 .../experiments_list.html                          | 13 +++-
 django_airavata/apps/workspace/views.py            | 21 ++++--
 django_airavata/apps/workspace/webpack.config.js   |  1 +
 9 files changed, 188 insertions(+), 8 deletions(-)

diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
index 2d14366..cb6b413 100644
--- a/django_airavata/apps/api/serializers.py
+++ b/django_airavata/apps/api/serializers.py
@@ -315,5 +315,6 @@ class FullExperimentSerializer(serializers.Serializer):
 class ExperimentSummarySerializer(
         thrift_utils.create_serializer_class(ExperimentSummaryModel)):
     creationTime = UTCPosixTimestampDateTimeField()
+    statusUpdateTime = UTCPosixTimestampDateTimeField()
     url = FullyEncodedHyperlinkedIdentityField(view_name='django_airavata_api:experiment-detail', lookup_field='experimentId', lookup_url_kwarg='experiment_id')
     project = FullyEncodedHyperlinkedIdentityField(view_name='django_airavata_api:project-detail', lookup_field='projectId', lookup_url_kwarg='project_id')
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/index.js b/django_airavata/apps/api/static/django_airavata_api/js/index.js
index 6562ed1..0c7f867 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/index.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/index.js
@@ -11,6 +11,7 @@ import ApplicationDeploymentService from './services/ApplicationDeploymentServic
 import ApplicationInterfaceService from './services/ApplicationInterfaceService'
 import ApplicationModuleService from './services/ApplicationModuleService'
 import ExperimentService from './services/ExperimentService'
+import ExperimentSearchService from './services/ExperimentSearchService'
 import FullExperimentService from './services/FullExperimentService'
 import ProjectService from './services/ProjectService'
 
@@ -32,6 +33,7 @@ exports.services = {
     ApplicationInterfaceService,
     ApplicationModuleService,
     ExperimentService,
+    ExperimentSearchService,
     FullExperimentService,
     ProjectService,
 }
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/ExperimentSummary.js b/django_airavata/apps/api/static/django_airavata_api/js/models/ExperimentSummary.js
new file mode 100644
index 0000000..2026aed
--- /dev/null
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/ExperimentSummary.js
@@ -0,0 +1,28 @@
+
+import BaseModel from './BaseModel'
+
+const FIELDS = [
+    'experimentId',
+    'projectId',
+    'gatewayId',
+    {
+        name: 'creationTime',
+        type: 'date'
+    },
+    'userName',
+    'name',
+    'description',
+    'executionId',
+    'resourceHostId',
+    'experimentStatus',
+    {
+        name: 'statusUpdateTime',
+        type: 'date',
+    },
+];
+
+export default class ExperimentSummary extends BaseModel {
+    constructor(data = {}) {
+        super(FIELDS, data);
+    }
+}
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/services/ExperimentSearchService.js b/django_airavata/apps/api/static/django_airavata_api/js/services/ExperimentSearchService.js
new file mode 100644
index 0000000..c9de306
--- /dev/null
+++ b/django_airavata/apps/api/static/django_airavata_api/js/services/ExperimentSearchService.js
@@ -0,0 +1,21 @@
+
+import ExperimentSummary from '../models/ExperimentSummary'
+import FetchUtils from '../utils/FetchUtils'
+import PaginationIterator from '../utils/PaginationIterator'
+
+class ExperimentSearchService {
+    list(data = {}) {
+        if (data && data.results) {
+            return Promise.resolve(new PaginationIterator(data, ExperimentSummary));
+        } else {
+            return fetch('/api/experiment-search/', {
+                credentials: 'include'
+            })
+            .then(response => response.json())
+            .then(json => new PaginationIterator(json, ExperimentSummary));
+        }
+    }
+}
+
+// Export as a singleton
+export default new ExperimentSearchService();
\ No newline at end of file
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/ExperimentListContainer.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/ExperimentListContainer.vue
new file mode 100644
index 0000000..854f0f4
--- /dev/null
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/ExperimentListContainer.vue
@@ -0,0 +1,84 @@
+<template>
+    <div>
+        <div class="row">
+            <div class="col">
+                <h1 class="h4 mb-4">Browse Experiments</h1>
+            </div>
+        </div>
+        <div class="row">
+            <div class="col">
+                <div class="card">
+                    <div class="card-body">
+                        <table class="table table-hover">
+                            <thead>
+                                <tr>
+                                    <th>Name</th>
+                                    <th>Creation Time</th>
+                                    <th>Status</th>
+                                    <th>Actions</th>
+                                </tr>
+                            </thead>
+                            <tbody>
+                                <tr v-for="experiment in experiments" :key="experiment.experimentId">
+                                    <td><a :href="'/workspace/experiments/' + encodeURIComponent(experiment.experimentId) + '/'">{{experiment.name}}</a></td>
+                                    <td><span :title="experiment.creationTime">{{ fromNow(experiment.creationTime) }}</span></td>
+                                    <td>{{experiment.experimentStatus}}</td>
+                                    <td></td>
+                                </tr>
+                            </tbody>
+                        </table>
+                        <pager v-bind:paginator="experimentsPaginator"
+                        v-on:next="nextExperiments" v-on:previous="previousExperiments"></pager>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+
+import { models, services } from 'django-airavata-api'
+import { components as comps } from 'django-airavata-common-ui'
+
+import moment from 'moment';
+
+export default {
+    props: ['initialExperimentsData'],
+    name: 'experiment-list-container',
+    data () {
+        return {
+            experimentsPaginator: null,
+        }
+    },
+    components: {
+        'pager': comps.Pager,
+    },
+    methods: {
+        nextExperiments: function(event) {
+            this.experimentsPaginator.next();
+        },
+        previousExperiments: function(event) {
+            this.experimentsPaginator.previous();
+        },
+        fromNow: function(date) {
+            return moment(date).fromNow();
+        }
+    },
+    computed: {
+        experiments: function() {
+            return this.experimentsPaginator ? this.experimentsPaginator.results : null;
+        },
+    },
+    beforeMount: function () {
+        services.ExperimentSearchService.list(this.initialExperimentsData)
+            .then(result => {
+                this.experimentsPaginator = result
+                console.log("experiments", result.results);
+            });
+    }
+}
+</script>
+
+<style>
+</style>
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-experiment-list.js b/django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-experiment-list.js
new file mode 100644
index 0000000..34593aa
--- /dev/null
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-experiment-list.js
@@ -0,0 +1,25 @@
+import Vue from 'vue'
+import BootstrapVue from 'bootstrap-vue'
+import ExperimentListContainer from './containers/ExperimentListContainer.vue'
+
+// This is imported globally on the website so no need to include it again in this view
+// import 'bootstrap/dist/css/bootstrap.css'
+import 'bootstrap-vue/dist/bootstrap-vue.css'
+
+Vue.use(BootstrapVue);
+
+new Vue({
+  el: '#experiment-list',
+  template: '<experiment-list-container v-bind:initialExperimentsData="experimentsData"></experiment-list-container>',
+  data: {
+      experimentsData: null
+  },
+  components: {
+      ExperimentListContainer
+  },
+  beforeMount: function () {
+      if (this.$el.dataset.experimentsData) {
+          this.experimentsData = JSON.parse(this.$el.dataset.experimentsData);
+      }
+  }
+})
diff --git a/django_airavata/apps/workspace/templates/django_airavata_workspace/experiments_list.html b/django_airavata/apps/workspace/templates/django_airavata_workspace/experiments_list.html
index e188310..49d7b84 100644
--- a/django_airavata/apps/workspace/templates/django_airavata_workspace/experiments_list.html
+++ b/django_airavata/apps/workspace/templates/django_airavata_workspace/experiments_list.html
@@ -1,8 +1,19 @@
 {% extends './base.html' %}
 
+{% load static %}
+
+{% block css %}
+{{ block.super }}
+<link rel=stylesheet type=text/css href="{% static 'django_airavata_workspace/dist/experiment-list.css' %}">
+{% endblock %}
 
 {% block content %}
 
-<h1>Experiments</h1>
+<div id="experiment-list" data-experiments-data="{{ experiments_data }}"></div>
 
 {% endblock content %}
+
+{% block scripts %}
+{{ block.super }}
+<script src="{% static "django_airavata_workspace/dist/experiment-list.js" %}"></script>
+{% endblock %}
diff --git a/django_airavata/apps/workspace/views.py b/django_airavata/apps/workspace/views.py
index 363475c..fd79970 100644
--- a/django_airavata/apps/workspace/views.py
+++ b/django_airavata/apps/workspace/views.py
@@ -2,14 +2,13 @@
 import json
 import logging
 
-from rest_framework.renderers import JSONRenderer
-from django.conf import settings
 from django.contrib.auth.decorators import login_required
-from django.shortcuts import render, redirect
+from django.shortcuts import render
+from rest_framework.renderers import JSONRenderer
 
-from django_airavata.apps.api.views import ExperimentViewSet
-from django_airavata.apps.api.views import FullExperimentViewSet
-from django_airavata.apps.api.views import ProjectViewSet
+from django_airavata.apps.api.views import (ExperimentSearchViewSet,
+                                            FullExperimentViewSet,
+                                            ProjectViewSet)
 
 logger = logging.getLogger(__name__)
 
@@ -17,13 +16,20 @@ logger = logging.getLogger(__name__)
 @login_required
 def experiments_list(request):
     request.active_nav_item = 'experiments'
-    return render(request, 'django_airavata_workspace/experiments_list.html')
+
+    response = ExperimentSearchViewSet.as_view({'get': 'list'})(request)
+    experiments_json = JSONRenderer().render(response.data)
+    return render(request, 'django_airavata_workspace/experiments_list.html', {
+        'experiments_data': experiments_json
+    })
+
 
 @login_required
 def dashboard(request):
     request.active_nav_item = 'dashboard'
     return render(request, 'django_airavata_workspace/dashboard.html')
 
+
 @login_required
 def projects_list(request):
     request.active_nav_item = 'projects'
@@ -35,6 +41,7 @@ def projects_list(request):
         'projects_data': projects_json
     })
 
+
 @login_required
 def create_experiment(request, app_module_id):
     request.active_nav_item = 'dashboard'
diff --git a/django_airavata/apps/workspace/webpack.config.js b/django_airavata/apps/workspace/webpack.config.js
index b200ad7..378df1b 100644
--- a/django_airavata/apps/workspace/webpack.config.js
+++ b/django_airavata/apps/workspace/webpack.config.js
@@ -9,6 +9,7 @@ module.exports = {
       'dashboard': './static/django_airavata_workspace/js/entry-dashboard',
       'create-experiment': './static/django_airavata_workspace/js/entry-create-experiment',
       'view-experiment': './static/django_airavata_workspace/js/entry-view-experiment',
+      'experiment-list': './static/django_airavata_workspace/js/entry-experiment-list',
   },
   output: {
     path: path.resolve(__dirname, './static/django_airavata_workspace/dist/'),

-- 
To stop receiving notification emails like this one, please contact
machristie@apache.org.

[airavata-django-portal] 01/03: AIRAVATA-2614 Map searchExperiments to ViewSet, Serializer

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 07a0770b0a50973bebe3af0f5180afcec9d32a90
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Tue Jan 30 16:05:25 2018 -0500

    AIRAVATA-2614 Map searchExperiments to ViewSet, Serializer
---
 django_airavata/apps/api/serializers.py |  7 +++++++
 django_airavata/apps/api/urls.py        |  1 +
 django_airavata/apps/api/views.py       | 21 +++++++++++++++++++++
 3 files changed, 29 insertions(+)

diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
index 3a0fd09..0d045e5 100644
--- a/django_airavata/apps/api/serializers.py
+++ b/django_airavata/apps/api/serializers.py
@@ -305,3 +305,10 @@ class FullExperimentSerializer(serializers.Serializer):
 
     def update(self, instance, validated_data):
         raise Exception("Not implemented")
+
+
+class ExperimentSummarySerializer(
+        thrift_utils.create_serializer_class(ExperimentSummaryModel)):
+    creationTime = UTCPosixTimestampDateTimeField()
+    url = FullyEncodedHyperlinkedIdentityField(view_name='django_airavata_api:experiment-detail', lookup_field='experimentId', lookup_url_kwarg='experiment_id')
+    project = FullyEncodedHyperlinkedIdentityField(view_name='django_airavata_api:project-detail', lookup_field='projectId', lookup_url_kwarg='project_id')
diff --git a/django_airavata/apps/api/urls.py b/django_airavata/apps/api/urls.py
index e20babf..345f85d 100644
--- a/django_airavata/apps/api/urls.py
+++ b/django_airavata/apps/api/urls.py
@@ -12,6 +12,7 @@ router = routers.DefaultRouter()
 router.register(r'projects', views.ProjectViewSet, base_name='project')
 router.register(r'experiments', views.ExperimentViewSet, base_name='experiment')
 router.register(r'full-experiments', views.FullExperimentViewSet, base_name='full-experiment')
+router.register(r'experiment-search', views.ExperimentSearchViewSet, base_name='experiment-search')
 router.register(r'new/application/module', views.RegisterApplicationModule, base_name='register_app_module')
 router.register(r'application-interfaces', views.ApplicationInterfaceViewSet, base_name='application-interface')
 router.register(r'applications', views.ApplicationModuleViewSet, base_name='application')
diff --git a/django_airavata/apps/api/views.py b/django_airavata/apps/api/views.py
index c9b2f57..cf44e41 100644
--- a/django_airavata/apps/api/views.py
+++ b/django_airavata/apps/api/views.py
@@ -268,6 +268,27 @@ class ExperimentViewSet(APIBackedViewSet):
         return Response(serializer.data)
 
 
+class ExperimentSearchViewSet(mixins.ListModelMixin, GenericAPIBackedViewSet):
+
+    serializer_class = serializers.ExperimentSummarySerializer
+    pagination_class = APIResultPagination
+    pagination_viewname = 'django_airavata_api:experiment-search-list'
+
+    def get_list(self):
+        view = self
+
+        # TODO: implement support for filters
+        class ExperimentSearchResultIterator(APIResultIterator):
+            def get_results(self, limit=-1, offset=0):
+                return view.request.airavata_client.searchExperiments(
+                    view.authz_token, view.gateway_id, view.username, {},
+                    limit, offset)
+        return ExperimentSearchResultIterator()
+
+    def get_instance(self, lookup_value):
+        raise NotImplementedError()
+
+
 class FullExperimentViewSet(mixins.RetrieveModelMixin,
                             GenericAPIBackedViewSet):
 

-- 
To stop receiving notification emails like this one, please contact
machristie@apache.org.

[airavata-django-portal] 02/03: AIRAVATA-2614 Sort imports

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 bcdfad188b87cd56669596f44c0a63d6fff7046b
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Tue Jan 30 16:05:40 2018 -0500

    AIRAVATA-2614 Sort imports
---
 django_airavata/apps/api/serializers.py | 35 +++++++++++++++++++--------------
 1 file changed, 20 insertions(+), 15 deletions(-)

diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
index 0d045e5..2d14366 100644
--- a/django_airavata/apps/api/serializers.py
+++ b/django_airavata/apps/api/serializers.py
@@ -1,26 +1,31 @@
 
-from airavata.model.appcatalog.appdeployment.ttypes import ApplicationModule, ApplicationDeploymentDescription,CommandObject,SetEnvPaths
-from airavata.model.appcatalog.appinterface.ttypes import ApplicationInterfaceDescription
+import copy
+import datetime
+import logging
+from urllib.parse import quote
+
+from django.conf import settings
+from rest_framework import serializers
+
+from airavata.model.appcatalog.appdeployment.ttypes import (ApplicationDeploymentDescription,
+                                                            ApplicationModule,
+                                                            CommandObject,
+                                                            SetEnvPaths)
+from airavata.model.appcatalog.appinterface.ttypes import \
+    ApplicationInterfaceDescription
 from airavata.model.appcatalog.computeresource.ttypes import BatchQueue
-from airavata.model.application.io.ttypes import InputDataObjectType, OutputDataObjectType
-from airavata.model.data.replica.ttypes import DataProductModel, DataReplicaLocationModel
-from airavata.model.experiment.ttypes import ExperimentModel
+from airavata.model.application.io.ttypes import (InputDataObjectType,
+                                                  OutputDataObjectType)
+from airavata.model.data.replica.ttypes import (DataProductModel,
+                                                DataReplicaLocationModel)
+from airavata.model.experiment.ttypes import (ExperimentModel,
+                                              ExperimentSummaryModel)
 from airavata.model.job.ttypes import JobModel
 from airavata.model.status.ttypes import ExperimentStatus
 from airavata.model.workspace.ttypes import Project
 
 from . import thrift_utils
 
-from django.conf import settings
-
-from rest_framework import serializers
-
-import datetime
-import copy
-from urllib.parse import quote
-import logging
-
-
 log = logging.getLogger(__name__)
 
 

-- 
To stop receiving notification emails like this one, please contact
machristie@apache.org.