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 2017/10/11 19:42:29 UTC

[1/3] airavata-django-portal git commit: AIRAVATA-2537 Simple Project list view

Repository: airavata-django-portal
Updated Branches:
  refs/heads/master fee999bef -> 4ed82de91


AIRAVATA-2537 Simple Project list view


Project: http://git-wip-us.apache.org/repos/asf/airavata-django-portal/repo
Commit: http://git-wip-us.apache.org/repos/asf/airavata-django-portal/commit/71ca603c
Tree: http://git-wip-us.apache.org/repos/asf/airavata-django-portal/tree/71ca603c
Diff: http://git-wip-us.apache.org/repos/asf/airavata-django-portal/diff/71ca603c

Branch: refs/heads/master
Commit: 71ca603c0a5747f09e8ce49c161c661e01f2c179
Parents: fee999b
Author: Marcus Christie <ma...@iu.edu>
Authored: Thu Sep 28 14:41:55 2017 -0400
Committer: Marcus Christie <ma...@iu.edu>
Committed: Thu Sep 28 14:41:55 2017 -0400

----------------------------------------------------------------------
 .../js/entry-project-list.js                    | 17 +++++++++---
 .../js/views/ProjectList.vue                    | 27 ++++++++++----------
 .../js/views/ProjectListContainer.vue           | 23 +++++++++++++++++
 .../js/views/ProjectListItem.vue                | 17 ++++++++++++
 .../projects_list.html                          |  2 +-
 django_airavata/templates/base.html             |  6 +++--
 6 files changed, 72 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/71ca603c/django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-project-list.js
----------------------------------------------------------------------
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-project-list.js b/django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-project-list.js
index 14d61c1..7d771c2 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-project-list.js
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-project-list.js
@@ -1,7 +1,18 @@
 import Vue from 'vue'
-import ProjectList from './views/ProjectList.vue'
+import ProjectListContainer from './views/ProjectListContainer.vue'
 
 new Vue({
-  el: '#app',
-  render: h => h(ProjectList)
+  el: '#project-list',
+  template: '<project-list-container v-bind:initialProjects="projects"></project-list-container>',
+  data: {
+      projects: null
+  },
+  components: {
+      ProjectListContainer
+  },
+  beforeMount: function () {
+      if (this.$el.dataset.projects) {
+          this.projects = JSON.parse(this.$el.dataset.projects);
+      }
+  }
 })

http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/71ca603c/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectList.vue
----------------------------------------------------------------------
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectList.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectList.vue
index 89d380b..a7fdfcc 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectList.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectList.vue
@@ -1,24 +1,23 @@
 <template>
     <ul id="project-list">
-        <li v-for="project in projects">
-            {{ project.name }}
-        </li>
+        <project-list-item v-bind:project="project" v-for="project in projects" v-bind:key="project.projectID">
+        </project-list-item>
     </ul>
 </template>
 
 <script>
+import ProjectListItem from './ProjectListItem.vue'
+
 export default {
-  name: 'project-list',
-  data () {
-    return {
-      projects: [
-              {"name": "Project 1"},
-              {"name": "Project 2"},
-              {"name": "Project 3"},
-              {"name": "Project 4"},
-          ]
-      }
-  }
+    name: 'project-list',
+    props: ['projects'],
+    data: function () {
+        return {
+        }
+    },
+    components: {
+        ProjectListItem
+    }
 }
 </script>
 

http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/71ca603c/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectListContainer.vue
----------------------------------------------------------------------
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectListContainer.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectListContainer.vue
new file mode 100644
index 0000000..47d1b5f
--- /dev/null
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectListContainer.vue
@@ -0,0 +1,23 @@
+<template>
+    <project-list v-bind:projects="projects"></project-list>
+</template>
+
+<script>
+import ProjectList from './ProjectList.vue'
+
+export default {
+    props: ['initialProjects'],
+    name: 'project-list-container',
+    data () {
+        return {
+            projects: this.initialProjects
+        }
+    },
+    components: {
+        ProjectList
+    }
+}
+</script>
+
+<style>
+</style>

http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/71ca603c/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectListItem.vue
----------------------------------------------------------------------
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectListItem.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectListItem.vue
new file mode 100644
index 0000000..9903dd1
--- /dev/null
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectListItem.vue
@@ -0,0 +1,17 @@
+<template>
+    <li>{{ project.name }}</li>
+</template>
+
+<script>
+export default {
+    name: 'project-list-item',
+    props: ['project'],
+    data: function () {
+        return {
+        }
+    }
+}
+</script>
+
+<style>
+</style>

http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/71ca603c/django_airavata/apps/workspace/templates/django_airavata_workspace/projects_list.html
----------------------------------------------------------------------
diff --git a/django_airavata/apps/workspace/templates/django_airavata_workspace/projects_list.html b/django_airavata/apps/workspace/templates/django_airavata_workspace/projects_list.html
index 399e478..3ab4184 100644
--- a/django_airavata/apps/workspace/templates/django_airavata_workspace/projects_list.html
+++ b/django_airavata/apps/workspace/templates/django_airavata_workspace/projects_list.html
@@ -6,7 +6,7 @@
 
 <h1>Projects</h1>
 
-<div id="app"></div>
+<div id="project-list" data-projects="{{ projects_data }}"></div>
 
 {% endblock content %}
 

http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/71ca603c/django_airavata/templates/base.html
----------------------------------------------------------------------
diff --git a/django_airavata/templates/base.html b/django_airavata/templates/base.html
index 092c046..29af934 100644
--- a/django_airavata/templates/base.html
+++ b/django_airavata/templates/base.html
@@ -51,8 +51,10 @@
         {% block nav-items %}
         {% endblock %}
     </nav>
-    {% block content %}
-    {% endblock %}
+    <main class="main-content">
+        {% block content %}
+        {% endblock %}
+    </main>
 </div>
 
 {% block scripts %}


[2/3] airavata-django-portal git commit: AIRAVATA-2537 Fleshing out project list table

Posted by ma...@apache.org.
AIRAVATA-2537 Fleshing out project list table


Project: http://git-wip-us.apache.org/repos/asf/airavata-django-portal/repo
Commit: http://git-wip-us.apache.org/repos/asf/airavata-django-portal/commit/ae10daf4
Tree: http://git-wip-us.apache.org/repos/asf/airavata-django-portal/tree/ae10daf4
Diff: http://git-wip-us.apache.org/repos/asf/airavata-django-portal/diff/ae10daf4

Branch: refs/heads/master
Commit: ae10daf49f6f21b85c7102f25ad58e11453ba53c
Parents: 71ca603
Author: Marcus Christie <ma...@iu.edu>
Authored: Thu Sep 28 15:46:18 2017 -0400
Committer: Marcus Christie <ma...@iu.edu>
Committed: Thu Sep 28 15:46:18 2017 -0400

----------------------------------------------------------------------
 django_airavata/apps/api/serializers.py           | 12 ++++++++++++
 django_airavata/apps/workspace/package-lock.json  |  5 +++++
 django_airavata/apps/workspace/package.json       |  1 +
 .../js/views/ProjectList.vue                      | 18 ++++++++++++++----
 .../js/views/ProjectListItem.vue                  | 15 ++++++++++++---
 .../django_airavata_workspace/projects_list.html  |  2 +-
 django_airavata/static/common/scss/main.scss      |  1 +
 django_airavata/templates/base.html               |  2 +-
 8 files changed, 47 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/ae10daf4/django_airavata/apps/api/serializers.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
index afdb09d..45c6d10 100644
--- a/django_airavata/apps/api/serializers.py
+++ b/django_airavata/apps/api/serializers.py
@@ -5,6 +5,7 @@ from django.conf import settings
 
 from rest_framework import serializers
 
+import datetime
 from urllib.parse import quote
 
 
@@ -19,6 +20,16 @@ class FullyEncodedHyperlinkedIdentityField(serializers.HyperlinkedIdentityField)
         url = self.reverse(view_name, kwargs=kwargs, request=request, format=format)
         return url.replace("__PLACEHOLDER__", encoded_lookup_value)
 
+class UTCPosixTimestampDateTimeField(serializers.DateTimeField):
+    def to_representation(self, obj):
+        dt = datetime.datetime.utcfromtimestamp(obj/1000)
+        return super().to_representation(dt)
+
+    def to_internal_value(self, data):
+        dt = super().to_internal_value(data)
+        return int(dt.timestamp() * 1000)
+
+
 class GetGatewayUsername(object):
 
     def __call__(self):
@@ -49,6 +60,7 @@ class ProjectSerializer(serializers.Serializer):
     owner = GatewayUsernameDefaultField()
     gatewayId = GatewayIdDefaultField()
     experiments = FullyEncodedHyperlinkedIdentityField(view_name='django_airavata_api:project-experiments', lookup_field='projectID', lookup_url_kwarg='project_id')
+    creationTime = UTCPosixTimestampDateTimeField()
 
     def create(self, validated_data):
         return Project(**validated_data)

http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/ae10daf4/django_airavata/apps/workspace/package-lock.json
----------------------------------------------------------------------
diff --git a/django_airavata/apps/workspace/package-lock.json b/django_airavata/apps/workspace/package-lock.json
index 07d2363..dbcf1e2 100644
--- a/django_airavata/apps/workspace/package-lock.json
+++ b/django_airavata/apps/workspace/package-lock.json
@@ -3934,6 +3934,11 @@
         "minimist": "0.0.8"
       }
     },
+    "moment": {
+      "version": "2.18.1",
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz",
+      "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8="
+    },
     "ms": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",

http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/ae10daf4/django_airavata/apps/workspace/package.json
----------------------------------------------------------------------
diff --git a/django_airavata/apps/workspace/package.json b/django_airavata/apps/workspace/package.json
index 028d70d..5a2c4de 100644
--- a/django_airavata/apps/workspace/package.json
+++ b/django_airavata/apps/workspace/package.json
@@ -10,6 +10,7 @@
     "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
   },
   "dependencies": {
+    "moment": "^2.18.1",
     "vue": "^2.3.3"
   },
   "devDependencies": {

http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/ae10daf4/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectList.vue
----------------------------------------------------------------------
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectList.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectList.vue
index a7fdfcc..4951cbb 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectList.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectList.vue
@@ -1,8 +1,18 @@
 <template>
-    <ul id="project-list">
-        <project-list-item v-bind:project="project" v-for="project in projects" v-bind:key="project.projectID">
-        </project-list-item>
-    </ul>
+    <table class="table">
+        <thead>
+            <tr>
+                <th>Name</th>
+                <th>Owner</th>
+                <th>Creation Time</th>
+                <th>Actions</th>
+            </tr>
+        </thead>
+        <tbody>
+            <project-list-item v-bind:project="project" v-for="project in projects" v-bind:key="project.projectID">
+            </project-list-item>
+        </tbody>
+    </table>
 </template>
 
 <script>

http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/ae10daf4/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectListItem.vue
----------------------------------------------------------------------
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectListItem.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectListItem.vue
index 9903dd1..fd5bf92 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectListItem.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectListItem.vue
@@ -1,13 +1,22 @@
 <template>
-    <li>{{ project.name }}</li>
+    <tr>
+        <td>{{ project.name }}</td>
+        <td>{{ project.owner }}</td>
+        <td v-bind:title="project.creationTime">{{ creationTime }}</td>
+        <td><a href="#">View <i class="fa fa-bar-chart" aria-hidden="true"></i></a></td>
+    </tr>
 </template>
 
 <script>
+import moment from 'moment';
+
 export default {
     name: 'project-list-item',
     props: ['project'],
-    data: function () {
-        return {
+    computed: {
+        creationTime: function () {
+            var dt = new Date(this.project.creationTime);
+            return moment(dt).fromNow();
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/ae10daf4/django_airavata/apps/workspace/templates/django_airavata_workspace/projects_list.html
----------------------------------------------------------------------
diff --git a/django_airavata/apps/workspace/templates/django_airavata_workspace/projects_list.html b/django_airavata/apps/workspace/templates/django_airavata_workspace/projects_list.html
index 3ab4184..02943e7 100644
--- a/django_airavata/apps/workspace/templates/django_airavata_workspace/projects_list.html
+++ b/django_airavata/apps/workspace/templates/django_airavata_workspace/projects_list.html
@@ -4,7 +4,7 @@
 
 {% block content %}
 
-<h1>Projects</h1>
+<h4>Browse Projects</h4>
 
 <div id="project-list" data-projects="{{ projects_data }}"></div>
 

http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/ae10daf4/django_airavata/static/common/scss/main.scss
----------------------------------------------------------------------
diff --git a/django_airavata/static/common/scss/main.scss b/django_airavata/static/common/scss/main.scss
index e5d88cf..46167fe 100644
--- a/django_airavata/static/common/scss/main.scss
+++ b/django_airavata/static/common/scss/main.scss
@@ -99,6 +99,7 @@ body {
 .main-content {
     flex-grow: 1;
     padding: 1rem;
+    overflow-y: scroll;
 }
 
 .sidebar {

http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/ae10daf4/django_airavata/templates/base.html
----------------------------------------------------------------------
diff --git a/django_airavata/templates/base.html b/django_airavata/templates/base.html
index 29af934..6a4823c 100644
--- a/django_airavata/templates/base.html
+++ b/django_airavata/templates/base.html
@@ -1,10 +1,10 @@
 {% load static %}
 <!DOCTYPE html>
 <head>
-    <link rel=stylesheet type=text/css href="{% static 'common/dist/main.css' %}">
     <link rel=stylesheet type=text/css href="{% static 'bootstrap-4.0.0-beta/css/bootstrap.min.css' %}">
     <link rel=stylesheet type=text/css
           href=https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css>
+    <link rel=stylesheet type=text/css href="{% static 'common/dist/main.css' %}">
     {% block css %}
 
     {% endblock %}


[3/3] airavata-django-portal git commit: AIRAVATA-2537 Base pagination support for API results

Posted by ma...@apache.org.
AIRAVATA-2537 Base pagination support for API results


Project: http://git-wip-us.apache.org/repos/asf/airavata-django-portal/repo
Commit: http://git-wip-us.apache.org/repos/asf/airavata-django-portal/commit/4ed82de9
Tree: http://git-wip-us.apache.org/repos/asf/airavata-django-portal/tree/4ed82de9
Diff: http://git-wip-us.apache.org/repos/asf/airavata-django-portal/diff/4ed82de9

Branch: refs/heads/master
Commit: 4ed82de91dcf21e9b945ac29e3f8c32a904985f4
Parents: ae10daf
Author: Marcus Christie <ma...@iu.edu>
Authored: Wed Oct 11 15:42:24 2017 -0400
Committer: Marcus Christie <ma...@iu.edu>
Committed: Wed Oct 11 15:42:24 2017 -0400

----------------------------------------------------------------------
 django_airavata/apps/api/views.py | 71 ++++++++++++++++++++++++++++++++--
 1 file changed, 68 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/4ed82de9/django_airavata/apps/api/views.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/api/views.py b/django_airavata/apps/api/views.py
index 82be57e..088cc0a 100644
--- a/django_airavata/apps/api/views.py
+++ b/django_airavata/apps/api/views.py
@@ -1,18 +1,24 @@
 
 from . import serializers
 
-from rest_framework import status, mixins
+from rest_framework import status, mixins, pagination
 from rest_framework.decorators import api_view, detail_route
 from rest_framework.views import APIView
 from rest_framework.viewsets import GenericViewSet
 from rest_framework.response import Response
 from rest_framework.reverse import reverse
+from rest_framework.utils.urls import replace_query_param
 
 from django.conf import settings
 from django.http import JsonResponse, Http404
 from django.shortcuts import render
 from django.views.decorators.csrf import csrf_exempt
 
+from collections import OrderedDict
+import logging
+
+log = logging.getLogger(__name__)
+
 # Create your views here.
 @api_view(['GET'])
 def api_root(request, format=None):
@@ -92,15 +98,74 @@ class APIBackedViewSet(mixins.CreateModelMixin,
     """
     pass
 
+class APIResultIterator(object):
+    """
+    Iterable container over API results which allow limit/offset style slicing.
+    """
+
+    limit = -1
+    offset = 0
+
+    def get_results(self, limit=-1, offset=0):
+        raise NotImplementedError("Subclasses must implement get_results")
+
+    def __iter__(self):
+        results = self.get_results(self.limit, self.offset)
+        for result in results:
+            yield result
+
+    def __getitem__(self, key):
+        if isinstance(key, slice):
+            self.limit = key.stop - key.start
+            self.offset = key.start
+            return iter(self)
+        else:
+            return self.get_results(1, key)
+
+class APIResultPagination(pagination.LimitOffsetPagination):
+    """
+    Based on DRF's LimitOffsetPagination; Airavata API pagination results don't
+    have a known count, so it isn't always possible to know how many pages there
+    are.
+    """
+    def paginate_queryset(self, queryset, request, view=None):
+        assert isinstance(queryset, APIResultIterator), "queryset is not an APIResultIterator: {}".format(queryset)
+        self.limit = self.get_limit(request)
+        if self.limit is None:
+            return None
+
+        self.offset = self.get_offset(request)
+        self.request = request
+
+        return list(queryset[self.offset:self.offset + self.limit])
+
+    def get_paginated_response(self, data):
+        has_next_link = len(data) >= self.limit
+        return Response(OrderedDict([
+            ('next', self.get_next_link() if has_next_link else None),
+            ('previous', self.get_previous_link()),
+            ('results', data)
+        ]))
+
+    def get_next_link(self):
+        url = self.request.build_absolute_uri()
+        url = replace_query_param(url, self.limit_query_param, self.limit)
+
+        offset = self.offset + self.limit
+        return replace_query_param(url, self.offset_query_param, offset)
 
 class ProjectViewSet(APIBackedViewSet):
 
     serializer_class = serializers.ProjectSerializer
     lookup_field = 'project_id'
+    pagination_class = APIResultPagination
 
     def get_list(self):
-        # TODO: support pagination
-        return self.request.airavata_client.getUserProjects(self.authz_token, self.gateway_id, self.username, -1, 0)
+        view = self
+        class ProjectResultIterator(APIResultIterator):
+            def get_results(self, limit=-1, offset=0):
+                return view.request.airavata_client.getUserProjects(view.authz_token, view.gateway_id, view.username, limit, offset)
+        return ProjectResultIterator()
 
     def get_instance(self, lookup_value):
         return self.request.airavata_client.getProject(self.authz_token, lookup_value)