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 2019/06/17 14:23:17 UTC
[airavata-django-portal] 04/11: AIRAVATA-2990 Add UI component for
picking date range for stats
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 1ce5892dcdc47db7967d2ee4ea480a0096adc67d
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Fri Jun 7 16:51:30 2019 -0400
AIRAVATA-2990 Add UI component for picking date range for stats
---
django_airavata/apps/admin/package.json | 1 +
.../statistics/ExperimentStatisticsCard.vue | 2 +-
.../statistics/ExperimentStatisticsContainer.vue | 96 ++++++++++++++--------
.../admin/static/django_airavata_admin/src/main.js | 4 +
.../django_airavata_api/js/service_config.js | 2 +-
django_airavata/apps/api/view_utils.py | 16 ++++
django_airavata/apps/api/views.py | 27 ++++--
7 files changed, 105 insertions(+), 43 deletions(-)
diff --git a/django_airavata/apps/admin/package.json b/django_airavata/apps/admin/package.json
index f1f904c..d6b9048 100644
--- a/django_airavata/apps/admin/package.json
+++ b/django_airavata/apps/admin/package.json
@@ -17,6 +17,7 @@
"django-airavata-common-ui": "file:../../static/common",
"moment": "^2.22.2",
"vue": "^2.5.22",
+ "vue-flatpickr-component": "^8.1.2",
"vue-resource": "^1.3.4",
"vue-router": "^2.7.0",
"vuedraggable": "^2.16.0",
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/statistics/ExperimentStatisticsCard.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/statistics/ExperimentStatisticsCard.vue
index 63dc8ed..db8a464 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/statistics/ExperimentStatisticsCard.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/statistics/ExperimentStatisticsCard.vue
@@ -2,7 +2,7 @@
<b-card
:bg-variant="bgVariant"
- body-bg-variant="light"
+ body-bg-variant="white"
:header-text-variant="headerTextVariant"
class="statistics-card"
>
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/statistics/ExperimentStatisticsContainer.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/statistics/ExperimentStatisticsContainer.vue
index 0a20b76..dcbe586 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/statistics/ExperimentStatisticsContainer.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/statistics/ExperimentStatisticsContainer.vue
@@ -6,6 +6,17 @@
</div>
</div>
<div class="row">
+ <div class="col">
+ <b-card>
+ <flat-pickr
+ v-model="dateRange"
+ :config="dateConfig"
+ @on-change="dateRangeChanged"
+ />
+ </b-card>
+ </div>
+ </div>
+ <div class="row">
<div class="col-lg-2 col-md-4">
<experiment-statistics-card
bg-variant="primary"
@@ -82,35 +93,37 @@
v-if="items.length"
>
<div class="col">
- <b-table
- :fields="fields"
- :items="items"
- >
- <template
- slot="executionId"
- slot-scope="data"
- >
- <application-name :application-interface-id="data.value" />
- </template>
- <template
- slot="resourceHostId"
- slot-scope="data"
+ <b-card>
+ <b-table
+ :fields="fields"
+ :items="items"
>
- <compute-resource-name :compute-resource-id="data.value" />
- </template>
- <template
- slot="creationTime"
- slot-scope="data"
- >
- <human-date :date="data.value" />
- </template>
- <template
- slot="experimentStatus"
- slot-scope="data"
- >
- <experiment-status-badge :status-name="data.value.name" />
- </template>
- </b-table>
+ <template
+ slot="executionId"
+ slot-scope="data"
+ >
+ <application-name :application-interface-id="data.value" />
+ </template>
+ <template
+ slot="resourceHostId"
+ slot-scope="data"
+ >
+ <compute-resource-name :compute-resource-id="data.value" />
+ </template>
+ <template
+ slot="creationTime"
+ slot-scope="data"
+ >
+ <human-date :date="data.value" />
+ </template>
+ <template
+ slot="experimentStatus"
+ slot-scope="data"
+ >
+ <experiment-status-badge :status-name="data.value.name" />
+ </template>
+ </b-table>
+ </b-card>
</div>
</div>
</div>
@@ -123,15 +136,22 @@ import ExperimentStatisticsCard from "./ExperimentStatisticsCard";
export default {
name: "experiment-statistics-container",
data() {
+ const fromTime = new Date(Date.now() - 24 * 60 * 60 * 1000); // 24 hours ago
+ const toTime = new Date();
return {
experimentStatistics: {},
- selectedExperimentSummaries: null
+ selectedExperimentSummaries: null,
+ fromTime: fromTime,
+ toTime: toTime,
+ dateRange: [fromTime, toTime],
+ dateConfig: {
+ mode: "range",
+ maxDate: new Date()
+ }
};
},
created() {
- services.ExperimentStatisticsService.get().then(
- stats => (this.experimentStatistics = stats)
- );
+ this.loadStatistics();
},
components: {
ExperimentStatisticsCard,
@@ -207,6 +227,18 @@ export default {
methods: {
selectExperiments(experiments) {
this.selectedExperimentSummaries = experiments;
+ },
+ dateRangeChanged(selectedDates) {
+ [this.fromTime, this.toTime] = selectedDates;
+ if (this.fromTime && this.toTime) {
+ this.loadStatistics();
+ }
+ },
+ loadStatistics() {
+ services.ExperimentStatisticsService.get({
+ fromTime: this.fromTime.toJSON(),
+ toTime: this.toTime.toJSON()
+ }).then(stats => (this.experimentStatistics = stats));
}
}
};
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/main.js b/django_airavata/apps/admin/static/django_airavata_admin/src/main.js
index 60cd37a..31a3644 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/main.js
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/main.js
@@ -1,14 +1,18 @@
import { components, entry } from "django-airavata-common-ui";
import VueResource from "vue-resource";
import VueRouter from "vue-router";
+import VueFlatPickr from 'vue-flatpickr-component';
import App from "./App.vue";
import router from "./router";
+import 'flatpickr/dist/flatpickr.css';
+
entry(Vue => {
Vue.config.productionTip = false;
Vue.use(VueResource);
Vue.use(VueRouter);
+ Vue.use(VueFlatPickr);
new Vue({
render: h => h(components.MainLayout, [h(App)]),
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/service_config.js b/django_airavata/apps/api/static/django_airavata_api/js/service_config.js
index 43551c7..0770e81 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/service_config.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/service_config.js
@@ -194,7 +194,7 @@ export default {
get: {
url: "/api/experiment-statistics",
requestType: "get",
- queryParams: ["fromDate", "toDate"],
+ queryParams: ["fromTime", "toTime"],
modelClass: ExperimentStatistics
}
}
diff --git a/django_airavata/apps/api/view_utils.py b/django_airavata/apps/api/view_utils.py
index 1046684..8e932da 100644
--- a/django_airavata/apps/api/view_utils.py
+++ b/django_airavata/apps/api/view_utils.py
@@ -1,5 +1,8 @@
+import logging
from collections.__init__ import OrderedDict
+from datetime import datetime
+import pytz
from django.conf import settings
from django.http import Http404
from rest_framework import mixins, pagination
@@ -8,6 +11,8 @@ from rest_framework.reverse import reverse
from rest_framework.utils.urls import remove_query_param, replace_query_param
from rest_framework.viewsets import GenericViewSet
+logger = logging.getLogger(__name__)
+
class GenericAPIBackedViewSet(GenericViewSet):
# Make lookup_value_regex to any set of non-forward-slash characters. Many
@@ -178,3 +183,14 @@ class APIResultPagination(pagination.LimitOffsetPagination):
return self.request.build_absolute_uri(reverse(self.viewname))
else:
return self.request.build_absolute_uri()
+
+
+def convert_utc_iso8601_to_date(iso8601_utc_string):
+ # This is meant to convert a JavaScript `new Date().toJSON()` into a
+ # datetime instance
+ timestamp = datetime.strptime(
+ iso8601_utc_string, "%Y-%m-%dT%H:%M:%S.%fZ")
+ timestamp = timestamp.replace(tzinfo=pytz.UTC)
+ logger.debug("convert_utc_iso8601_to_date({})={}".format(
+ iso8601_utc_string, timestamp))
+ return timestamp
diff --git a/django_airavata/apps/api/views.py b/django_airavata/apps/api/views.py
index 6bd8a93..e58326e 100644
--- a/django_airavata/apps/api/views.py
+++ b/django_airavata/apps/api/views.py
@@ -2,6 +2,7 @@ import logging
import os
from datetime import datetime, timedelta
+import pytz
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
@@ -47,7 +48,8 @@ from . import (
models,
output_views,
serializers,
- thrift_utils
+ thrift_utils,
+ view_utils
)
READ_PERMISSION_TYPE = '{}:READ'
@@ -1448,16 +1450,23 @@ class ExperimentStatisticsView(APIView):
serializer_class = serializers.ExperimentStatisticsSerializer
def get(self, request, format=None):
- # TODO: convert from ISO-8601 to posix timestamp
- from_time = request.GET.get(
- 'fromTime',
- (datetime.utcnow() - timedelta(days=7)).timestamp() * 1000)
- to_time = request.GET.get(
- 'toTime',
- datetime.utcnow().timestamp() * 1000)
+ if 'fromTime' in request.GET:
+ from_time = view_utils.convert_utc_iso8601_to_date(
+ request.GET['fromTime']).timestamp() * 1000
+ else:
+ from_time = (datetime.utcnow() -
+ timedelta(days=7)).timestamp() * 1000
+ if 'toTime' in request.GET:
+ to_time = view_utils.convert_utc_iso8601_to_date(
+ request.GET['toTime']).timestamp() * 1000
+ else:
+ to_time = datetime.utcnow().timestamp() * 1000
+ username = request.GET.get('userName', None)
+ application_name = request.GET.get('applicationName', None)
+ resource_hostname = request.GET.get('requestHostName', None)
statistics = request.airavata_client.getExperimentStatistics(
request.authz_token, settings.GATEWAY_ID, from_time, to_time,
- None, None, None)
+ username, application_name, resource_hostname)
serializer = self.serializer_class(
statistics, context={'request': request})
return Response(serializer.data)