airavata-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From machris...@apache.org
Subject [airavata-django-portal] 02/05: AIRAVATA-2842 Integrate new API method to get accessible deployments
Date Mon, 16 Jul 2018 22:56:02 GMT
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 2c5533c43bf27329e346b54bd568aa4434fd82b8
Author: Marcus Christie <machrist@iu.edu>
AuthorDate: Mon Jul 16 18:28:29 2018 -0400

    AIRAVATA-2842 Integrate new API method to get accessible deployments
---
 .../components/admin/ApplicationDeployments.vue    |  5 +-
 .../ComputePreference.vue                          |  2 +-
 django_airavata/apps/api/serializers.py            | 12 ++--
 .../django_airavata_api/js/service_config.js       | 45 +++++++-----
 .../js/services/ComputeResourceService.js          |  4 +-
 .../js/services/ServiceFactory.js                  |  5 ++
 django_airavata/apps/api/urls.py                   |  7 +-
 django_airavata/apps/api/views.py                  | 82 ++++++++++------------
 .../ComputationalResourceSchedulingEditor.vue      | 48 +++++--------
 .../js/components/experiment/ExperimentEditor.vue  |  5 --
 .../js/containers/CreateExperimentContainer.vue    | 21 +++---
 11 files changed, 110 insertions(+), 126 deletions(-)

diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/ApplicationDeployments.vue
b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/ApplicationDeployments.vue
index 341f75a..41b7d7f 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/ApplicationDeployments.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/ApplicationDeployments.vue
@@ -182,7 +182,7 @@
       fetchComputeHosts:function () {
         this.computeHosts=[{"host":"Loading...","host_id":""}]
         var callable=(value)=>this.computeHosts=value
-        Utils.get('/api/compute/resources',{success:callable,failure:(value)=>this.computeHosts=[]})
+        Utils.get('/api/compute-resources/all_names_list/',{success:callable,failure:(value)=>this.computeHosts=[]})
       },
       saveApplicationDeployment:function ({success=null,failure=null}={}) {
         this.syncData()
@@ -204,7 +204,7 @@
       },
       "appDeployments.computeHostId":function (value) {
         if(value){
-          Utils.get("/api/compute/resource/queues",{queryParams:{id:value},success:(value)=>this.queues=value})
+          Utils.get("/api/compute-resources/" + encodeURIComponent(value) + "/queues",{success:(value)=>this.queues=value})
         }
       },
       "getCompleteData": function (value) {
@@ -259,4 +259,3 @@
     margin-bottom: 5px;
   }
 </style>
-
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/ComputePreference.vue
b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/ComputePreference.vue
index fac4d10..aa5c4bf 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/ComputePreference.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/ComputePreference.vue
@@ -206,7 +206,7 @@
         this.data.overridebyAiravata = value
       },
       fetchComputeResources: function () {
-        return DjangoAiravataAPI.utils.FetchUtils.get('/api/compute/resources').then((value)
=> this.computeResources = value);
+        return DjangoAiravataAPI.utils.FetchUtils.get('/api/compute-resources/all_names_list').then((value)
=> this.computeResources = value);
       },
       createComputeResourcePolicy: function () {
         return {
diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
index e5f2987..c9d37e5 100644
--- a/django_airavata/apps/api/serializers.py
+++ b/django_airavata/apps/api/serializers.py
@@ -15,7 +15,9 @@ from airavata.model.appcatalog.appdeployment.ttypes import (ApplicationDeploymen
                                                             SetEnvPaths)
 from airavata.model.appcatalog.appinterface.ttypes import \
     ApplicationInterfaceDescription
-from airavata.model.appcatalog.computeresource.ttypes import BatchQueue
+from airavata.model.appcatalog.computeresource.ttypes \
+    import (BatchQueue,
+            ComputeResourceDescription)
 from airavata.model.appcatalog.groupresourceprofile.ttypes import \
     GroupResourceProfile
 from airavata.model.application.io.ttypes import (InputDataObjectType,
@@ -333,12 +335,8 @@ class ApplicationDeploymentDescriptionSerializer(thrift_utils.create_serializer_
     queues = FullyEncodedHyperlinkedIdentityField(view_name='django_airavata_api:application-deployment-queues',
lookup_field='appDeploymentId', lookup_url_kwarg='app_deployment_id')
 
 
-class ComputeResourceDescriptionSerializer(CustomSerializer):
-    hostName=serializers.CharField()
-    hostAliases=serializers.ListField(child=serializers.CharField())
-    ipAddresses=serializers.ListField(child=serializers.CharField())
-    resourceDescription=serializers.CharField()
-    enabled=serializers.BooleanField()
+class ComputeResourceDescriptionSerializer(thrift_utils.create_serializer_class(ComputeResourceDescription)):
+    pass
 
 
 class BatchQueueSerializer(thrift_utils.create_serializer_class(BatchQueue)):
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 ef77613..1ceb425 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
@@ -1,3 +1,4 @@
+import ApplicationDeploymentDescription from './models/ApplicationDeploymentDescription'
 import Group from './models/Group'
 import SharedEntity from './models/SharedEntity'
 import UserProfile from './models/UserProfile'
@@ -35,25 +36,32 @@ pagination:true # whether to treat the response as a paginated response
  */
 
 export default {
-    "GroupResourcePreference": {
-        url: "/api/group-resource-profiles/",
-        viewSet: true
-    },
-    "SharedEntitiesGroups": {
-        url: "/api/shared/group/entities",
-        viewSet: true
+    "ApplicationDeployments": {
+        url: "/api/application-deployments",
+        viewSet: true,
+        queryParams: ['appModuleId', 'groupResourceProfileId'],
+        modelClass: ApplicationDeploymentDescription,
     },
-    "Entities": {
-        url: "/api/entities",
+    "ComputeResources": {
+        url: "/api/compute-resources",
         viewSet: [{
-            name:"create",
-            pagination:true
-        }]
+            name: "list"
+        }, {
+            name: "names",
+            url: "/api/compute-resources/all_names",
+            requestType: 'get',
+            modelClass: Object,
+        }, {
+            name: "namesList",
+            url: "/api/compute-resources/all_names_list",
+            requestType: 'get',
+            modelClass: Array,
+        }],
+        modelClass: ApplicationDeploymentDescription,
     },
-    "SharedEntities": {
-        url: "/api/shared-entities",
-        viewSet: true,
-        modelClass: SharedEntity,
+    "GroupResourcePreference": {
+        url: "/api/group-resource-profiles/",
+        viewSet: true
     },
     "Groups": {
         url: "/api/groups",
@@ -62,6 +70,11 @@ export default {
         queryParams: ['limit', 'offset'],
         modelClass: Group,
     },
+    "SharedEntities": {
+        url: "/api/shared-entities",
+        viewSet: true,
+        modelClass: SharedEntity,
+    },
     "UserProfiles": {
         url: "/api/user-profiles",
         viewSet: [{
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/services/ComputeResourceService.js
b/django_airavata/apps/api/static/django_airavata_api/js/services/ComputeResourceService.js
index 5e62d31..1bf029c 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/services/ComputeResourceService.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/services/ComputeResourceService.js
@@ -44,12 +44,12 @@ class ComputeResourceService {
     }
 
     list() {
-        return FetchUtils.get('/api/compute/resources')
+        return FetchUtils.get('/api/compute-resources/all_names_list')
     }
 
      retrieve(id) {
         this.data=null
-        return  FetchUtils.get('/api/compute/resource/details', {id: id})
+        return  FetchUtils.get('/api/compute-resource/' + encodeURIComponent(id) + '/')
     }
 }
 
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/services/ServiceFactory.js
b/django_airavata/apps/api/static/django_airavata_api/js/services/ServiceFactory.js
index cb78a37..6ab85b5 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/services/ServiceFactory.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/services/ServiceFactory.js
@@ -99,6 +99,11 @@ const parseServiceMapping = function (serviceConfiguration) {
                         modelClass: modelClass,
                         queryParams: queryParams,
                     }
+                    break;
+                default:
+                    // Assume all fields have been provided
+                    serviceConfiguration[supportedFunctionName] = supportedFunction;
+                    break;
             }
             serviceConfiguration[supportedFunctionName].pagination = pagination
         }
diff --git a/django_airavata/apps/api/urls.py b/django_airavata/apps/api/urls.py
index 8a2134c..c6e9c56 100644
--- a/django_airavata/apps/api/urls.py
+++ b/django_airavata/apps/api/urls.py
@@ -24,6 +24,8 @@ router.register(r'group-resource-profiles', views.GroupResourceProfileViewSet,
 router.register(r'shared/group/entities',views.SharedEntityGroups,base_name="shared_entities_with_groups")
 router.register(r'shared-entities', views.SharedEntityViewSet,
                 base_name='shared-entity')
+router.register(r'compute-resources', views.ComputeResourceViewSet,
+                base_name='compute-resource')
 
 app_name = 'django_airavata_api'
 urlpatterns = [
@@ -33,9 +35,6 @@ urlpatterns = [
         name='register_application_interface'),
     url(r'^new/application/deployment$', views.RegisterApplicationDeployments.as_view(),
         name='register_application_deployments'),
-    url(r'^compute/resources$', views.ComputeResourceList.as_view(), name="compute_resources"),
-    url(r'^compute/resource/details$', views.ComputeResourceDetails.as_view(), name="compute_resource_details"),
-    url(r'^compute/resource/queues', views.ComputeResourcesQueues.as_view(), name="compute_resource_queues"),
     url(r'^application/interfaces$', views.ApplicationInterfaceList.as_view(), name="app_interfaces"),
     url(r'^application/interface$', views.FetchApplicationInterface.as_view(), name="app_interface"),
     url(r'^application/deployment$', views.FetchApplicationDeployment.as_view(), name="app_deployment"),
@@ -45,8 +44,6 @@ urlpatterns = [
     url(r'^upload$', views.upload_input_file, name='upload_input_file'),
     url(r'^download', views.download_file, name='download_file'),
     url(r'^credentials/ssh/key/create', views.GenerateRegisterSSHKeys.as_view(), name="ssh_key_creation"),
-    url(r'^compute/resources$', views.ComputeResourceListView.as_view(), name="compute_resources"),
-    url(r'^compute/resource/details', views.ComputeResourceDetails.as_view(), name="compute_resource_details"),
     url(r'^job/submission/local', views.LocalJobSubmissionView.as_view(), name="local_job_submission"),
     url(r'^job/submission/cloud', views.CloudJobSubmissionView.as_view(), name="cloud_job_submission"),
     url(r'^job/submission/globus', views.GlobusJobSubmissionView.as_view(), name="globus_job_submission"),
diff --git a/django_airavata/apps/api/views.py b/django_airavata/apps/api/views.py
index 0b84d4f..db622a6 100644
--- a/django_airavata/apps/api/views.py
+++ b/django_airavata/apps/api/views.py
@@ -8,6 +8,7 @@ from rest_framework import mixins
 from rest_framework import status
 from rest_framework.decorators import detail_route
 from rest_framework.decorators import list_route
+from rest_framework.exceptions import ParseError
 from rest_framework.parsers import JSONParser
 from rest_framework.renderers import JSONRenderer
 from rest_framework.response import Response
@@ -23,7 +24,7 @@ from airavata.model.data.movement.ttypes import GridFTPDataMovement, LOCALDataMo
     UnicoreDataMovement
 from airavata.model.group.ttypes import ResourcePermissionType
 from django_airavata.apps.api.view_utils import GenericAPIBackedViewSet, APIBackedViewSet,
APIResultIterator, \
-    APIResultPagination
+    APIResultPagination, ReadOnlyAPIBackedViewSet
 from . import datastore
 from . import serializers
 from . import thrift_utils
@@ -380,7 +381,18 @@ class ApplicationDeploymentViewSet(APIBackedViewSet):
     lookup_value_regex = '[^/]+'
 
     def get_list(self):
-        return self.request.airavata_client.getAllApplicationDeployments(self.authz_token,
self.gateway_id)
+        app_module_id = self.request.query_params.get('appModuleId', None)
+        group_resource_profile_id = self.request.query_params.get('groupResourceProfileId',
None)
+        if (app_module_id and not group_resource_profile_id)\
+                or (not app_module_id and group_resource_profile_id):
+            raise ParseError("Query params appModuleId and "
+                             "groupResourceProfileId are required together.")
+        if app_module_id and group_resource_profile_id:
+            return self.request.airavata_client.getApplicationDeploymentsForAppModuleAndGroupResourceProfile(
+                self.authz_token, app_module_id, group_resource_profile_id)
+        else:
+            return self.request.airavata_client.getAccessibleApplicationDeployments(
+                self.authz_token, self.gateway_id, ResourcePermissionType.READ)
 
     def get_instance(self, lookup_value):
         return self.request.airavata_client.getApplicationDeployment(self.authz_token, lookup_value)
@@ -419,27 +431,6 @@ class ApplicationDeploymentViewSet(APIBackedViewSet):
         return Response(serializer.data)
 
 
-class ComputeResourceList(APIView):
-    renderer_classes = (JSONRenderer,)
-
-    def get(self, request, format=None):
-        gateway_id = settings.GATEWAY_ID
-        cr = request.airavata_client.getAllComputeResourceNames(request.authz_token)
-
-        return Response([{'host_id': host_id, 'host': host} for host_id, host in cr.items()])
-
-
-class ComputeResourceDetails(APIView):
-    renderer_classes = (JSONRenderer,)
-
-    def get(self, request, format=None):
-        details = request.airavata_client.getComputeResource(request.authz_token, request.query_params["id"])
-        serializer = thrift_utils.create_serializer(ComputeResourceDescription, instance=details,
-                                                    context={'request': request})
-        print(details)
-        return Response(serializer.data)
-
-
 class ComputeResourcesQueues(APIView):
     renderer_classes = (JSONRenderer,)
 
@@ -521,34 +512,33 @@ class DeleteSSHPubKey(APIView):
         return Response(request.airavata_client.deleteSSHPubKey(request.authz_token, request.data['token'],
gateway_id))
 
 
-class ComputeResourceAPIViewSet(mixins.RetrieveModelMixin,
-                                mixins.ListModelMixin,
-                                GenericAPIBackedViewSet):
-    serializer_class = thrift_utils.create_serializer_class(ComputeResourceDescription)
-
-    def list(self, request, *args, **kwargs):
-        return Response(request.airavata_client.getAllComputeResourceNames(request.authz_token))
-
-    def retrieve(self, request, pk=None):
-        compute_resource_id = request.query_params["id"]
-        compute_resource = request.airavata_client.getComputeResource(request.authz_token,
compute_resource_id)
-        return Response(thrift_utils.create_serializer(ComputeResourceDescription, instance=compute_resource).data)
-
+class ComputeResourceViewSet(mixins.RetrieveModelMixin,
+                             GenericAPIBackedViewSet):
+    serializer_class = serializers.ComputeResourceDescriptionSerializer
+    lookup_field = 'compute_resource_id'
+    lookup_value_regex = '[^/]+'
 
-class ComputeResourceListView(APIView):
-    renderer_classes = (JSONRenderer,)
+    def get_instance(self, lookup_value, format=None):
+        return self.request.airavata_client.getComputeResource(self.authz_token, lookup_value)
 
-    def get(self, request, format=None):
+    @list_route()
+    def all_names(self, request, format=None):
+        """Return a map of compute resource names keyed by resource id."""
         return Response(request.airavata_client.getAllComputeResourceNames(request.authz_token))
 
+    @list_route()
+    def all_names_list(self, request, format=None):
+        """Return a list of compute resource names keyed by resource id."""
+        all_names = request.airavata_client.getAllComputeResourceNames(request.authz_token)
+        return Response([{'host_id': host_id, 'host': host} for host_id, host in all_names.items()])
 
-class ComputeResourceView(APIView):
-    renderer_classes = (JSONRenderer,)
-
-    def get(self, request, format=None):
-        compute_resource_id = request.query_params["id"]
-        compute_resource = request.airavata_client.getComputeResource(request.authz_token,
compute_resource_id)
-        return Response(thrift_utils.create_serializer(ComputeResourceDescription, instance=compute_resource).data)
+    @detail_route()
+    def queues(self, request, compute_resource_id, format=None):
+        details = request.airavata_client.getComputeResource(request.authz_token, compute_resource_id)
+        serializer = self.serializer_class(instance=details,
+                                           context={'request': request})
+        data = serializer.data
+        return Response([queue["queueName"] for queue in data["batchQueues"]])
 
 
 class LocalJobSubmissionView(APIView):
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ComputationalResourceSchedulingEditor.vue
b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ComputationalResourceSchedulingEditor.vue
index 93918f9..f44330a 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ComputationalResourceSchedulingEditor.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ComputationalResourceSchedulingEditor.vue
@@ -49,10 +49,6 @@ export default {
             type: String,
             required: true
         },
-        appInterfaceId: {
-            type: String,
-            required: true
-        },
         groupResourceProfileId: {
             type: String,
             required: true
@@ -73,22 +69,18 @@ export default {
         QueueSettingsEditor,
     },
     mounted: function () {
-        this.loadApplicationDeployments(this.appModuleId);
-        this.loadComputeResourcesForApplicationInterface(this.appInterfaceId);
+        this.loadApplicationDeployments(this.appModuleId, this.groupResourceProfileId);
+        this.loadComputeResourceNames();
         this.loadGroupResourceProfile();
     },
     computed: {
         computeResourceOptions: function() {
-            const computeResourceOptions = [];
-            for (let computeResourceId in this.computeResources) {
-                if (this.computeResources.hasOwnProperty(computeResourceId)
-                    && this.isComputeHostInGroupResourceProfile(computeResourceId))
{
-                    computeResourceOptions.push({
-                        value: computeResourceId,
-                        text: this.computeResources[computeResourceId],
-                    })
+            const computeResourceOptions = this.applicationDeployments.map(dep => {
+                return {
+                    value: dep.computeHostId,
+                    text: dep.computeHostId in this.computeResources ? this.computeResources[dep.computeHostId]
: null,
                 }
-            }
+            });
             computeResourceOptions.sort((a, b) => a.text.localeCompare(b.text));
             return computeResourceOptions;
         },
@@ -137,20 +129,14 @@ export default {
             this.localComputationalResourceScheduling.resourceHostId = selectedComputeResourceId;
             this.emitValueChanged();
         },
-        loadApplicationDeployments: function(appModuleId) {
+        loadApplicationDeployments: function(appModuleId, groupResourceProfileId) {
             this.loadingCount++;
-            services.ApplicationModuleService.getApplicationDeployments(appModuleId)
+            services.ServiceFactory.service("ApplicationDeployments").list({appModuleId:
appModuleId, groupResourceProfileId: groupResourceProfileId})
                 .then(applicationDeployments => {
                     this.applicationDeployments = applicationDeployments;
                 })
                 .then(()=> {this.loadingCount--;}, () => {this.loadingCount--;});
         },
-        loadComputeResourcesForApplicationInterface: function(appInterfaceId) {
-            this.loadingCount++;
-            services.ApplicationInterfaceService.getComputeResources(appInterfaceId)
-                .then(computeResources => this.computeResources = computeResources)
-                .then(()=> {this.loadingCount--;}, () => {this.loadingCount--;});
-        },
         loadGroupResourceProfile: function() {
             this.loadingCount++;
             services.GroupResourceProfileService.get(this.groupResourceProfileId)
@@ -159,14 +145,11 @@ export default {
                 })
                 .then(()=> {this.loadingCount--;}, () => {this.loadingCount--;});
         },
-        isComputeHostInGroupResourceProfile: function(computeHostId) {
-            // TODO: for now don't require a GroupResourceProfile
-            if (this.selectedGroupResourceProfile === null) {
-                return true;
-            }
-            return this.selectedGroupResourceProfile.computePreferences.some(cp => {
-                return cp.computeResourceId === computeHostId;
-            })
+        loadComputeResourceNames: function() {
+            this.loadingCount++;
+            services.ServiceFactory.service("ComputeResources").names()
+                .then(computeResourceNames => this.computeResources = computeResourceNames)
+                .then(()=> {this.loadingCount--;}, () => {this.loadingCount--;});
         },
         queueSettingsChanged: function() {
             // QueueSettingsEditor updates the full
@@ -193,6 +176,9 @@ export default {
             if (this.resourceHostId !== null && !newOptions.find(opt => opt.value
=== this.resourceHostId)) {
                 this.resourceHostId = null;
             }
+        },
+        groupResourceProfileId: function(newGroupResourceProfileId) {
+            this.loadApplicationDeployments(this.appModuleId, newGroupResourceProfileId);
         }
     }
 }
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue
b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue
index 34d29b0..c68df85 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue
@@ -77,7 +77,6 @@
                         v-model="localExperiment.userConfigurationData.computationalResourceScheduling"
                         v-if="localExperiment.userConfigurationData.groupResourceProfileId"
                         :app-module-id="appModule.appModuleId"
-                        :app-interface-id="appInterface.applicationInterfaceId"
                         :group-resource-profile-id="localExperiment.userConfigurationData.groupResourceProfileId">
                     </computational-resource-scheduling-editor>
                 </div>
@@ -117,10 +116,6 @@ export default {
             type: models.ApplicationModule,
             required: true
         },
-        appInterface: {
-            type: models.ApplicationInterface,
-            required: true
-        }
     },
     data () {
         return {
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/CreateExperimentContainer.vue
b/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/CreateExperimentContainer.vue
index fbce3fe..b79f2f4 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/CreateExperimentContainer.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/CreateExperimentContainer.vue
@@ -1,6 +1,6 @@
 <template>
-    <experiment-editor v-if="appModule && appInterface" :experiment="experiment"
-            :app-module="appModule" :app-interface="appInterface"
+    <experiment-editor v-if="experiment" :experiment="experiment"
+            :app-module="appModule"
             @saved="handleSavedExperiment"
             @savedAndLaunched="handleSavedAndLaunchedExperiment">
         <span slot="title">Create a New Experiment</span>
@@ -21,9 +21,8 @@ export default {
     ],
     data () {
         return {
-            'experiment': new models.Experiment(),
+            'experiment': null,
             'appModule': null,
-            'appInterface': null,
         }
     },
     components: {
@@ -42,18 +41,20 @@ export default {
     computed: {
     },
     mounted: function () {
+        const experiment = new models.Experiment();
         // TODO: integrate loading spinner
-        services.ApplicationModuleService.get(this.appModuleId)
+        const loadAppModule = services.ApplicationModuleService.get(this.appModuleId)
             .then(appModule => {
-                this.experiment.experimentName = appModule.appModuleName + ' on ' + moment().format('lll');
+                experiment.experimentName = appModule.appModuleName + ' on ' + moment().format('lll');
                 this.appModule = appModule;
             });
-        services.ApplicationInterfaceService.getForAppModuleId(this.appModuleId)
+        const loadAppInterface = services.ApplicationInterfaceService.getForAppModuleId(this.appModuleId)
             .then(appInterface => {
-                this.experiment.populateInputsOutputsFromApplicationInterface(appInterface);
-                this.appInterface = appInterface;
-                this.experiment.executionId = this.appInterface.applicationInterfaceId;
+                experiment.populateInputsOutputsFromApplicationInterface(appInterface);
+                experiment.executionId = appInterface.applicationInterfaceId;
             });
+        Promise.all([loadAppModule, loadAppInterface])
+            .then(() => this.experiment = experiment);
     }
 }
 </script>


Mime
View raw message