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)