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/15 19:32:00 UTC
[airavata-django-portal] branch develop updated: AIRAVATA-3510 When
getApplicationInterface fails,
check to see if it failed because it no longer exists, and return a 404
This is an automated email from the ASF dual-hosted git repository.
machristie pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git
The following commit(s) were added to refs/heads/develop by this push:
new f5160a2 AIRAVATA-3510 When getApplicationInterface fails, check to see if it failed because it no longer exists, and return a 404
f5160a2 is described below
commit f5160a202afaadd441023df42864280aca83d522
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Wed Sep 15 15:30:34 2021 -0400
AIRAVATA-3510 When getApplicationInterface fails, check to see if it failed because it no longer exists, and return a 404
---
.../django_airavata_api/js/errors/ErrorUtils.js | 3 +
django_airavata/apps/api/views.py | 14 +-
.../js/containers/EditExperimentContainer.vue | 13 +-
.../js/containers/ExperimentListContainer.vue | 158 ++++++++++++---------
.../js/containers/RecentExperimentsContainer.vue | 13 +-
.../common/js/components/ApplicationName.vue | 11 +-
6 files changed, 130 insertions(+), 82 deletions(-)
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/errors/ErrorUtils.js b/django_airavata/apps/api/static/django_airavata_api/js/errors/ErrorUtils.js
index e4f62bb..7832993 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/errors/ErrorUtils.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/errors/ErrorUtils.js
@@ -19,4 +19,7 @@ export default {
isUnauthorizedError(error) {
return this.isAPIException(error) && error.details.status === 403;
},
+ isNotFoundError(error) {
+ return this.isAPIException(error) && error.details.status === 404;
+ },
};
diff --git a/django_airavata/apps/api/views.py b/django_airavata/apps/api/views.py
index d8ec2c8..0bcc714 100644
--- a/django_airavata/apps/api/views.py
+++ b/django_airavata/apps/api/views.py
@@ -700,8 +700,18 @@ class ApplicationInterfaceViewSet(APIBackedViewSet):
self.authz_token, self.gateway_id)
def get_instance(self, lookup_value):
- return self.request.airavata_client.getApplicationInterface(
- self.authz_token, lookup_value)
+ try:
+ return self.request.airavata_client.getApplicationInterface(
+ self.authz_token, lookup_value)
+ except Exception:
+ # If it failed to load, check to see if it exists at all
+ all_interfaces = self.request.airavata_client.getAllApplicationInterfaces(
+ self.authz_token, self.gateway_id)
+ interface_ids = map(lambda i: i.applicationInterfaceId, all_interfaces)
+ if lookup_value not in interface_ids:
+ raise Http404("Application interface does not exist")
+ else:
+ raise # re-raise
def perform_create(self, serializer):
application_interface = serializer.save()
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/EditExperimentContainer.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/EditExperimentContainer.vue
index 6a71d43..5729c91 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/EditExperimentContainer.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/EditExperimentContainer.vue
@@ -11,7 +11,7 @@
</template>
<script>
-import { services } from "django-airavata-api";
+import { errors, services } from "django-airavata-api";
import { notifications } from "django-airavata-common-ui";
import ExperimentEditor from "../components/experiment/ExperimentEditor.vue";
import urls from "../utils/urls";
@@ -67,14 +67,15 @@ export default {
.then((appModule) => {
this.appModule = appModule;
})
- .catch(() => {
+ .catch((error) => {
+ const message = errors.ErrorUtils.isNotFoundError(error)
+ ? `Application interface (${this.experiment.executionId}) was not found.
+ If it has been deleted then you won't be able to edit this experiment.`
+ : `Unable to load application interface (${this.experiment.executionId}) or module`;
notifications.NotificationList.add(
new notifications.Notification({
type: "ERROR",
- message:
- "Unable to load application interface (" +
- this.experiment.executionId +
- ") or module. If it has been deleted then you won't be able to edit this experiment.",
+ message,
})
);
});
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
index 39a98b1..d243578 100644
--- 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
@@ -8,31 +8,44 @@
<div class="row">
<div class="col">
<div class="card">
- <div class = "card-body">
+ <div class="card-body">
<b-input-group class="w-100 mb-2">
- <b-form-input v-if="defaultOptionSelected" v-model="search"
+ <b-form-input
+ v-if="defaultOptionSelected"
+ v-model="search"
placeholder="Search Experiments"
@keydown.native.enter="searchExperiments"
/>
- <b-form-select v-if="applicationSelected" v-model="applicationSelect"
- :options="applicationNameOptions"
+ <b-form-select
+ v-if="applicationSelected"
+ v-model="applicationSelect"
+ :options="applicationNameOptions"
>
<template slot="first">
- <option :value="null" disabled>Select an application to search by</option>
+ <option :value="null" disabled>
+ Select an application to search by
+ </option>
</template>
</b-form-select>
- <b-form-select v-if="projectSelected" v-model="projectSelect"
- :options="projectNameOptions"
+ <b-form-select
+ v-if="projectSelected"
+ v-model="projectSelect"
+ :options="projectNameOptions"
>
<template slot="first">
- <option :value="null" disabled>Select a project to search by</option>
+ <option :value="null" disabled>
+ Select a project to search by
+ </option>
</template>
</b-form-select>
- <b-form-select v-model="experimentAttributeSelect"
- @input="checkSearchOptions"
+ <b-form-select
+ v-model="experimentAttributeSelect"
+ @input="checkSearchOptions"
>
<template slot="first">
- <option :value="null" disabled>Select an attribute to search by</option>
+ <option :value="null" disabled>
+ Select an attribute to search by
+ </option>
</template>
<option value="USER_NAME">User Name</option>
<option value="EXPERIMENT_NAME">Experiment Name</option>
@@ -43,7 +56,9 @@
</b-form-select>
<b-form-select v-model="experimentStatusSelect">
<template slot="first">
- <option :value="null" disabled>Select an experiment status to filter by</option>
+ <option :value="null" disabled>
+ Select an experiment status to filter by
+ </option>
</template>
<option value="ALL">ALL</option>
<option value="CREATED">Created</option>
@@ -57,25 +72,22 @@
</b-form-select>
<b-input-group-append>
<b-button @click="resetSearch">Reset</b-button>
- <b-button
- variant="primary"
- @click="searchExperiments"
- >Search</b-button>
+ <b-button variant="primary" @click="searchExperiments"
+ >Search</b-button
+ >
</b-input-group-append>
</b-input-group>
<b-input-group class="w-100 mb-2">
- <b-input-group-prepend is-text >
- <i
- class="fa fa-calendar-week"
- aria-hidden="true"
- ></i>
- </b-input-group-prepend>
- <flat-pickr v-model="dateSelect"
- :config="dateConfig"
- placeholder="Select a date range to filter by"
- @on-change="dateRangeChanged"
- class="form-control"
- />
+ <b-input-group-prepend is-text>
+ <i class="fa fa-calendar-week" aria-hidden="true"></i>
+ </b-input-group-prepend>
+ <flat-pickr
+ v-model="dateSelect"
+ :config="dateConfig"
+ placeholder="Select a date range to filter by"
+ @on-change="dateRangeChanged"
+ class="form-control"
+ />
</b-input-group>
</div>
</div>
@@ -160,7 +172,7 @@
</template>
<script>
-import { models, services, utils } from "django-airavata-api";
+import { errors, models, services, utils } from "django-airavata-api";
import { components as comps } from "django-airavata-common-ui";
import moment from "moment";
@@ -173,18 +185,18 @@ export default {
return {
experimentsPaginator: null,
applicationInterfaces: {},
- search: null,
- applicationSelect: null,
+ search: null,
+ applicationSelect: null,
projectSelect: null,
- dateSelect : null,
- experimentAttributeSelect: null,
- experimentStatusSelect: null,
+ dateSelect: null,
+ experimentAttributeSelect: null,
+ experimentStatusSelect: null,
appInterfaces: null,
projectInterfaces: null,
fromDate: null,
toDate: null,
applicationSelected: false,
- projectSelected: false,
+ projectSelected: false,
defaultOptionSelected: true,
dateConfig: {
mode: "range",
@@ -199,11 +211,11 @@ export default {
"experiment-status-badge": comps.ExperimentStatusBadge,
},
methods: {
- searchExperiments: function(){
+ searchExperiments: function () {
this.experimentsPaginator = null;
this.reloadExperiments();
},
- resetSearch: function(){
+ resetSearch: function () {
this.experimentsPaginator = null;
this.search = null;
this.experimentAttributeSelect = null;
@@ -216,58 +228,60 @@ export default {
this.checkSearchOptions();
this.reloadExperiments();
},
- reloadExperiments: function(){
+ reloadExperiments: function () {
const searchParams = {};
if (this.experimentAttributeSelect) {
- if (this.experimentAttributeSelect=="APPLICATION_ID"&& this.applicationSelect){
+ if (
+ this.experimentAttributeSelect == "APPLICATION_ID" &&
+ this.applicationSelect
+ ) {
searchParams["APPLICATION_ID"] = this.applicationSelect;
- }
- else if (this.experimentAttributeSelect=="PROJECT_ID"&& this.projectSelect){
+ } else if (
+ this.experimentAttributeSelect == "PROJECT_ID" &&
+ this.projectSelect
+ ) {
searchParams["PROJECT_ID"] = this.projectSelect;
- }
- else if (this.search){
+ } else if (this.search) {
searchParams[this.experimentAttributeSelect] = this.search;
}
}
- if (this.experimentStatusSelect){
- if (this.experimentStatusSelect != "ALL"){
- searchParams["STATUS"]= this.experimentStatusSelect;
+ if (this.experimentStatusSelect) {
+ if (this.experimentStatusSelect != "ALL") {
+ searchParams["STATUS"] = this.experimentStatusSelect;
}
}
- if (this.fromDate && this.toDate){
+ if (this.fromDate && this.toDate) {
searchParams["FROM_DATE"] = this.fromDate.getTime();
searchParams["TO_DATE"] = this.toDate.getTime();
}
services.ExperimentSearchService.list(searchParams).then(
- result => (this.experimentsPaginator = result)
- );
+ (result) => (this.experimentsPaginator = result)
+ );
},
- checkSearchOptions: function(){
+ checkSearchOptions: function () {
this.applicationSelected = false;
this.projectSelected = false;
this.defaultOptionSelected = false;
- if(this.experimentAttributeSelect == "APPLICATION_ID"){
+ if (this.experimentAttributeSelect == "APPLICATION_ID") {
this.applicationSelected = true;
- }
- else if( this.experimentAttributeSelect == "PROJECT_ID"){
- this.projectSelected=true;
- }
- else{
+ } else if (this.experimentAttributeSelect == "PROJECT_ID") {
+ this.projectSelected = true;
+ } else {
this.defaultOptionSelected = true;
}
},
- loadApplicationInterfaces: function() {
+ loadApplicationInterfaces: function () {
return services.ApplicationInterfaceService.list().then(
(appInterfaces) => (this.appInterfaces = appInterfaces)
);
},
- loadProjectInterfaces: function(){
+ loadProjectInterfaces: function () {
return services.ProjectService.listAll().then(
(projectInterfaces) => (this.projectInterfaces = projectInterfaces)
);
},
- dateRangeChanged: function(selectedDates) {
+ dateRangeChanged: function (selectedDates) {
[this.fromDate, this.toDate] = selectedDates;
if (this.fromDate && this.toDate) {
this.reloadExperiments();
@@ -310,17 +324,25 @@ export default {
ignoreErrors: true,
}
)
- .then((result) =>
+ .then((result) => {
this.$set(
this.applicationInterfaces,
experiment.executionId,
result
- )
- )
- .catch(() => {
- // Application interface may be deleted
- this.$set(this.applicationInterfaces, experiment.executionId, null);
- });
+ );
+ })
+ .catch((error) => {
+ if (errors.ErrorUtils.isNotFoundError(error)) {
+ this.$set(
+ this.applicationInterfaces,
+ experiment.executionId,
+ null
+ );
+ } else {
+ throw error;
+ }
+ })
+ .catch(utils.FetchUtils.reportError);
this.$set(this.applicationInterfaces, experiment.executionId, request);
}
return "...";
@@ -353,7 +375,7 @@ export default {
}
},
projectNameOptions() {
- if (this.projectInterfaces){
+ if (this.projectInterfaces) {
const options = this.projectInterfaces.map((projectInterface) => {
return {
value: projectInterface.projectID,
@@ -361,7 +383,7 @@ export default {
};
});
return utils.StringUtils.sortIgnoreCase(options, (o) => o.text);
- } else{
+ } else {
return [];
}
},
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/RecentExperimentsContainer.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/RecentExperimentsContainer.vue
index 0001d35..84ad18d 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/RecentExperimentsContainer.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/RecentExperimentsContainer.vue
@@ -18,7 +18,7 @@
<script>
import urls from "../utils/urls";
-import { models, services } from "django-airavata-api";
+import { errors, models, services, utils } from "django-airavata-api";
import { components } from "django-airavata-common-ui";
export default {
name: "recent-experiments-container",
@@ -103,10 +103,15 @@ export default {
.then((applicationInterface) => {
this.applicationInterfaces[interfaceId] = applicationInterface;
})
- .catch(() => {
+ .catch((error) => {
// ignore if missing
- this.applicationInterfaces[interfaceId] = null;
- });
+ if (errors.ErrorUtils.isNotFoundError(error)) {
+ this.applicationInterfaces[interfaceId] = null;
+ } else {
+ throw error;
+ }
+ })
+ .catch(utils.FetchUtils.reportError);
},
populateApplicationNames() {
this.feedItems
diff --git a/django_airavata/static/common/js/components/ApplicationName.vue b/django_airavata/static/common/js/components/ApplicationName.vue
index 6fc425b..df0c95e 100644
--- a/django_airavata/static/common/js/components/ApplicationName.vue
+++ b/django_airavata/static/common/js/components/ApplicationName.vue
@@ -2,7 +2,7 @@
<span :class="{ 'font-italic': notAvailable }">{{ applicationName }}</span>
</template>
<script>
-import { services } from "django-airavata-api";
+import { errors, services, utils } from "django-airavata-api";
export default {
name: "application-name",
props: {
@@ -27,7 +27,14 @@ export default {
{ ignoreErrors: true, cache: true }
)
.then((appInterface) => (this.applicationInterface = appInterface))
- .catch(() => (this.notAvailable = true));
+ .catch((error) => {
+ if (errors.ErrorUtils.isNotFoundError(error)) {
+ this.notAvailable = true;
+ } else {
+ throw error;
+ }
+ })
+ .catch(utils.FetchUtils.reportError);
},
},
computed: {