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 6b70bc344b6646f52d4fc03441921de183c87131 Author: Marcus Christie <[email protected]> AuthorDate: Tue Sep 11 09:51:46 2018 -0400 AIRAVATA-2876 New and delete deployment --- .../src/components/admin/ComputeResourcesModal.vue | 71 +++++ .../GroupComputeResourcePreference.vue | 307 ++++++++++----------- .../applications/ApplicationDeploymentEditor.vue | 6 +- .../applications/ApplicationDeploymentsList.vue | 60 ++-- .../applications/ApplicationEditorContainer.vue | 74 ++++- .../static/django_airavata_admin/src/router.js | 6 + .../src/store/applications/app_deployments.js | 7 + .../src/store/applications/app_modules.js | 4 +- .../api/static/django_airavata_api/js/index.js | 2 + .../js/models/ApplicationDeploymentDescription.js | 6 +- .../django_airavata_api/js/service_config.js | 3 +- django_airavata/apps/api/views.py | 4 + 12 files changed, 355 insertions(+), 195 deletions(-) diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/ComputeResourcesModal.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/ComputeResourcesModal.vue new file mode 100644 index 0000000..460fd26 --- /dev/null +++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/ComputeResourcesModal.vue @@ -0,0 +1,71 @@ +<template> + <b-modal title="Select Compute Resource" ref="modal" @ok="onSelectComputeResource" :ok-disabled="modalSelectComputeResourceOkDisabled"> + <b-form-select v-model="selectedComputeResource" :options="computeResourceOptions"> + <template slot="first"> + <option :value="null">Please select compute resource</option> + </template> + </b-form-select> + </b-modal> +</template> + +<script> +import { models, services } from "django-airavata-api"; +export default { + name: "compute-resources-modal", + props: { + computeResourceNames: Array, + excludedResourceIds: Array + }, + data() { + return { + selectedComputeResource: null, + localComputeResourceNames: null + }; + }, + created() { + if (!this.computeResourceNames) { + services.ComputeResourceService.namesList().then( + resourceNames => (this.localComputeResourceNames = resourceNames) + ); + } + }, + computed: { + modalSelectComputeResourceOkDisabled: function() { + return this.selectedComputeResource == null; + }, + computeResourceOptions: function() { + const names = this.computeResourceNames + ? this.computeResourceNames + : this.localComputeResourceNames; + const options = names + ? names + .filter( + comp => + this.excludedResourceIds + ? !this.excludedResourceIds.includes(comp.host_id) + : true + ) + .map(comp => { + return { + value: comp.host_id, + text: comp.host + }; + }) + : []; + options.sort((a, b) => + a.text.toLowerCase().localeCompare(b.text.toLowerCase()) + ); + return options; + } + }, + methods: { + onSelectComputeResource() { + this.$emit("selected", this.selectedComputeResource); + }, + show() { + this.$refs.modal.show(); + } + } +}; +</script> + diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/GroupComputeResourcePreference.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/GroupComputeResourcePreference.vue index d0f7a98..1cacce5 100644 --- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/GroupComputeResourcePreference.vue +++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/GroupComputeResourcePreference.vue @@ -10,26 +10,20 @@ <div class="card"> <div class="card-body"> <b-form-group label="Name" label-for="profile-name"> - <b-form-input id="profile-name" type="text" - v-model="data.groupResourceProfileName" - required placeholder="Name of this Group Resource Profile"> + <b-form-input id="profile-name" type="text" v-model="data.groupResourceProfileName" required placeholder="Name of this Group Resource Profile"> </b-form-input> </b-form-group> - <share-button ref="shareButton" v-model="sharedEntity"/> + <share-button ref="shareButton" v-model="sharedEntity" /> </div> </div> </div> </div> - <list-layout :items="data.computePreferences" title="Compute Preferences" - new-item-button-text="New Compute Preference" - @add-new-item="createComputePreference"> + <list-layout :items="data.computePreferences" title="Compute Preferences" new-item-button-text="New Compute Preference" @add-new-item="createComputePreference"> <template slot="item-list" slot-scope="slotProps"> - <b-table hover :fields="computePreferencesFields" :items="slotProps.items" - sort-by="computeResourceId"> + <b-table hover :fields="computePreferencesFields" :items="slotProps.items" sort-by="computeResourceId"> <template slot="policy" slot-scope="row"> - <compute-resource-policy-summary :compute-resource-id="row.item.computeResourceId" - :group-resource-profile="data"/> + <compute-resource-policy-summary :compute-resource-id="row.item.computeResourceId" :group-resource-profile="data" /> </template> <template slot="action" slot-scope="row"> <router-link :to="{ @@ -51,175 +45,164 @@ <i class="fa fa-trash" aria-hidden="true"></i> </a> </template> - </b-table> + </b-table> </template> </list-layout> <div class="row"> - <div class="col d-flex justify-content-end"> - <b-button variant="primary" @click="saveGroupResourceProfile">Save</b-button> - <b-button v-if="id" class="ml-2" variant="danger" @click="removeGroupResourceProfile">Delete</b-button> - <b-button class="ml-2" variant="secondary" @click="cancel">Cancel</b-button> - </div> + <div class="col d-flex justify-content-end"> + <b-button variant="primary" @click="saveGroupResourceProfile">Save</b-button> + <b-button v-if="id" class="ml-2" variant="danger" @click="removeGroupResourceProfile">Delete</b-button> + <b-button class="ml-2" variant="secondary" @click="cancel">Cancel</b-button> + </div> </div> - <b-modal id="modal-select-compute-resource" ref="modalSelectComputeResource" title="Select Compute Resource" - @ok="onSelectComputeResource" :ok-disabled="modalSelectComputeResourceOkDisabled"> - <b-form-select v-model="selectedComputeResource" :options="computeResourceOptions"> - <template slot="first"> - <option :value="null">Please select compute resource</option> - </template> - </b-form-select> - </b-modal> + <compute-resources-modal ref="modalSelectComputeResource" @selected="onSelectComputeResource" :excluded-resource-ids="excludedComputeResourceIds" + /> </div> </template> + <script> - import {components as comps, layouts} from 'django-airavata-common-ui' - import {models, services} from 'django-airavata-api' - import ComputeResourcePolicySummary from './ComputeResourcePolicySummary.vue' +import { components as comps, layouts } from "django-airavata-common-ui"; +import { models, services } from "django-airavata-api"; +import ComputeResourcePolicySummary from "./ComputeResourcePolicySummary.vue"; +import ComputeResourcesModal from "../ComputeResourcesModal.vue"; - export default { - name: "group-compute-resource-preference", - props: { - value: { - type: models.GroupResourceProfile, - default: function () { - return new models.GroupResourceProfile() +export default { + name: "group-compute-resource-preference", + props: { + value: { + type: models.GroupResourceProfile, + default: function() { + return new models.GroupResourceProfile(); + } + }, + id: { + type: String + } + }, + mounted: function() { + if (this.id) { + if (!this.value.groupResourceProfileId) { + services.ServiceFactory.service("GroupResourceProfiles") + .retrieve({ lookup: this.id }) + .then(grp => (this.data = grp)); + } + services.ServiceFactory.service("SharedEntities") + .retrieve({ lookup: this.id }) + .then(sharedEntity => (this.sharedEntity = sharedEntity)); + } + }, + data: function() { + let data = this.value.clone(); + return { + data: data, + service: services.ServiceFactory.service("GroupResourceProfiles"), + sharedEntity: null, + computePreferencesFields: [ + { + label: "Name", + key: "computeResourceId", + sortable: true, + formatter: value => this.getComputeResourceName(value) + }, + { + label: "Username", + key: "loginUserName" + }, + { + label: "Allocation", + key: "allocationProjectNumber" + }, + { + label: "Policy", + key: "policy" // custom rendering + }, + { + label: "Action", + key: "action" } - }, - id: { - type: String, - }, + ] + }; + }, + + components: { + "share-button": comps.ShareButton, + "list-layout": layouts.ListLayout, + ComputeResourcePolicySummary, + ComputeResourcesModal + }, + computed: { + excludedComputeResourceIds() { + const currentPrefs = this.data.computePreferences + ? this.data.computePreferences.map( + computePreference => computePreference.computeResourceId + ) + : []; + return currentPrefs; }, - mounted: function () { + title: function() { + return this.id + ? this.data.groupResourceProfileName + : "New Group Resource Profile"; + } + }, + methods: { + saveGroupResourceProfile: function() { + var persist = null; if (this.id) { - if (!this.value.groupResourceProfileId) { - services.ServiceFactory.service("GroupResourceProfiles").retrieve({lookup: this.id}) - .then(grp => this.data = grp); - } - services.ServiceFactory.service("SharedEntities").retrieve({lookup: this.id}) - .then(sharedEntity => this.sharedEntity = sharedEntity); + persist = this.service.update({ data: this.data, lookup: this.id }); + } else { + persist = this.service.create({ data: this.data }).then(data => { + // Save sharing settings too + const groupResourceProfileId = data.groupResourceProfileId; + return this.$refs.shareButton.mergeAndSave(groupResourceProfileId); + }); } - services.ComputeResourceService.namesList() - .then(names => this.computeResources = names); + persist.then(data => { + this.$router.push("/group-resource-profiles"); + }); }, - data: function () { - let data = this.value.clone(); - return { - data: data, - service: services.ServiceFactory.service("GroupResourceProfiles"), - sharedEntity: null, - computePreferencesFields: [ - { - label: 'Name', - key: 'computeResourceId', - sortable: true, - formatter: (value) => this.getComputeResourceName(value), - }, - { - label: 'Username', - key: 'loginUserName' - }, - { - label: 'Allocation', - key: 'allocationProjectNumber' - }, - { - label: 'Policy', - key: 'policy', // custom rendering - }, - { - label: 'Action', - key: 'action', - }, - ], - computeResources: null, - selectedComputeResource: null, - } + getComputeResourceName: function(computeResourceId) { + // TODO: load compute resources to get the real name + return computeResourceId && computeResourceId.indexOf("_") > 0 + ? computeResourceId.split("_")[0] + : computeResourceId; }, - - components: { - "share-button": comps.ShareButton, - "list-layout": layouts.ListLayout, - ComputeResourcePolicySummary, + cancel: function() { + this.$router.push("/group-resource-profiles"); }, - computed: { - modalSelectComputeResourceOkDisabled: function() { - return this.selectedComputeResource == null; - }, - computeResourceOptions: function() { - const currentPrefs = this.data.computePreferences ? this.data.computePreferences.map(computePreference => computePreference.computeResourceId) : []; - const options = this.computeResources ? this.computeResources - .filter(comp => !currentPrefs.includes(comp.host_id)) - .map(comp => { - return { - value: comp.host_id, - text: comp.host - } - }) : []; - options.sort((a, b) => a.text.toLowerCase().localeCompare(b.text.toLowerCase())); - return options; - }, - title: function() { - return this.id ? this.data.groupResourceProfileName : "New Group Resource Profile"; - } + createComputePreference: function() { + this.$refs.modalSelectComputeResource.show(); }, - methods: { - saveGroupResourceProfile: function () { - var persist = null; - if (this.id) { - persist = this.service.update({data: this.data, lookup: this.id}); - } else { - persist = this.service.create({data: this.data}) - .then((data) => { - // Save sharing settings too - const groupResourceProfileId = data.groupResourceProfileId; - return this.$refs.shareButton.mergeAndSave(groupResourceProfileId); - }); + onSelectComputeResource: function(computeResourceId) { + const computeResourcePreference = new models.GroupComputeResourcePreference(); + computeResourcePreference.computeResourceId = computeResourceId; + this.$router.push({ + name: "compute_preference_for_new_group_resource_profile", + params: { + value: computeResourcePreference, + id: this.id, + host_id: computeResourcePreference.computeResourceId, + groupResourceProfile: this.data } - persist.then(data => { - this.$router.push('/group-resource-profiles'); - }); - }, - getComputeResourceName: function (computeResourceId) { - // TODO: load compute resources to get the real name - return (computeResourceId && computeResourceId.indexOf("_") > 0) ? computeResourceId.split("_")[0] : computeResourceId; - }, - cancel: function() { - this.$router.push('/group-resource-profiles'); - }, - createComputePreference: function() { - this.$refs.modalSelectComputeResource.show(); - }, - onSelectComputeResource: function() { - const computeResourcePreference = new models.GroupComputeResourcePreference(); - const computeResourceId = this.selectedComputeResource; - computeResourcePreference.computeResourceId = computeResourceId; - this.$router.push({ - name: 'compute_preference_for_new_group_resource_profile', params: { - value: computeResourcePreference, - id: this.id, - host_id: computeResourcePreference.computeResourceId, - groupResourceProfile: this.data, - } + }); + }, + removeComputePreference: function(computeResourceId) { + let groupResourceProfile = this.data.clone(); + groupResourceProfile.removeComputeResource(computeResourceId); + this.service + .update({ data: groupResourceProfile, lookup: this.id }) + .then(groupResourceProfile => (this.data = groupResourceProfile)); + }, + removeGroupResourceProfile: function() { + if (this.id) { + this.service.delete({ lookup: this.id }).then(() => { + this.$router.push("/group-resource-profiles"); }); - }, - removeComputePreference: function(computeResourceId) { - - let groupResourceProfile = this.data.clone(); - groupResourceProfile.removeComputeResource(computeResourceId); - this.service.update({data: groupResourceProfile, lookup: this.id}) - .then(groupResourceProfile => this.data = groupResourceProfile); - }, - removeGroupResourceProfile: function() { - if (this.id) { - this.service.delete({lookup: this.id}) - .then(() => { - this.$router.push('/group-resource-profiles'); - }); - } else { - // Nothing to delete so just treat like a cancel - this.cancel(); - } + } else { + // Nothing to delete so just treat like a cancel + this.cancel(); } - }, + } } +}; </script> diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationDeploymentEditor.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationDeploymentEditor.vue index b778577..9bbed4b 100644 --- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationDeploymentEditor.vue +++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationDeploymentEditor.vue @@ -52,10 +52,6 @@ export default { value: { type: models.ApplicationDescriptionDefinition }, - id: { - type: String, - required: true - }, deployment_id: { type: String, required: true @@ -71,7 +67,7 @@ export default { if (this.computeResource) { return this.computeResource.hostName; } else { - return this.data.computeHostId.substring(0, 10); + return this.data.computeHostId.substring(0, 10) + "..."; } }, parallelismTypeOptions() { diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationDeploymentsList.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationDeploymentsList.vue index 05b73e6..5c81732 100644 --- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationDeploymentsList.vue +++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationDeploymentsList.vue @@ -1,35 +1,41 @@ <template> - <list-layout @add-new-item="newApplicationDeployment" :items="deployments" title="Application Deployments" new-item-button-text="New Deployment"> - <template slot="item-list" slot-scope="slotProps"> + <div> + <list-layout @add-new-item="newApplicationDeployment" :items="deployments" title="Application Deployments" new-item-button-text="New Deployment"> + <template slot="item-list" slot-scope="slotProps"> - <b-table striped hover :fields="fields" :items="slotProps.items" sort-by="computeHostId"> - <template slot="action" slot-scope="data"> - <router-link v-if="!data.item.userHasWriteAccess" :to="{name: 'application_deployment', params: {id: id, deployment_id: data.item.appDeploymentId}}"> - View - <i class="fa fa-eye" aria-hidden="true"></i> - </router-link> - <router-link v-if="data.item.userHasWriteAccess" :to="{name: 'application_deployment', params: {id: id, deployment_id: data.item.appDeploymentId}}"> - Edit - <i class="fa fa-edit" aria-hidden="true"></i> - </router-link> - <a href="#" class="text-danger" @click.prevent="removeApplicationDeployment(data.item)" v-if="data.item.userHasWriteAccess"> - Delete - <i class="fa fa-trash" aria-hidden="true"></i> - </a> - </template> - </b-table> - </template> - </list-layout> + <b-table striped hover :fields="fields" :items="slotProps.items" sort-by="computeHostId"> + <template slot="action" slot-scope="data"> + <router-link v-if="!data.item.userHasWriteAccess" :to="{name: 'application_deployment', params: {id: id, deployment_id: data.item.appDeploymentId}}"> + View + <i class="fa fa-eye" aria-hidden="true"></i> + </router-link> + <router-link v-if="data.item.userHasWriteAccess" :to="{name: 'application_deployment', params: {id: id, deployment_id: data.item.appDeploymentId}}"> + Edit + <i class="fa fa-edit" aria-hidden="true"></i> + </router-link> + <a href="#" class="text-danger" @click.prevent="removeApplicationDeployment(data.item)" v-if="data.item.userHasWriteAccess"> + Delete + <i class="fa fa-trash" aria-hidden="true"></i> + </a> + </template> + </b-table> + </template> + </list-layout> + <compute-resources-modal ref="modalSelectComputeResource" @selected="onSelectComputeResource" :excluded-resource-ids="excludedComputeResourceIds" + /> + </div> </template> <script> import { models, services } from "django-airavata-api"; import { layouts } from "django-airavata-common-ui"; +import ComputeResourcesModal from "../admin/ComputeResourcesModal.vue"; export default { name: "application-deployments-list", components: { - "list-layout": layouts.ListLayout + "list-layout": layouts.ListLayout, + ComputeResourcesModal }, props: { deployments: { @@ -65,6 +71,9 @@ export default { key: "action" } ]; + }, + excludedComputeResourceIds() { + return this.deployments.map(dep => dep.computeHostId); } }, mounted() { @@ -82,6 +91,15 @@ export default { } else { return computeResourceId.substring(0, 10) + "..."; } + }, + onSelectComputeResource(computeResourceId) { + this.$emit("new", computeResourceId); + }, + newApplicationDeployment() { + this.$refs.modalSelectComputeResource.show(); + }, + removeApplicationDeployment(deployment) { + this.$emit("delete", deployment); } } }; diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationEditorContainer.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationEditorContainer.vue index ef371b2..4ca9e7f 100644 --- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationEditorContainer.vue +++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationEditorContainer.vue @@ -17,7 +17,8 @@ <router-view name="module" v-if="module" v-model="module" @save="saveModule" @cancel="cancelModule" /> <router-view name="interface" v-if="appInterface" v-model="appInterface" @save="saveInterface" @cancel="cancelInterface" /> - <router-view name="deployments" v-if="deployments" :deployments="deployments" /> + <router-view name="deployments" v-if="deployments" :deployments="deployments" @new="createNewDeployment" @delete="deleteDeployment" + /> <router-view name="deployment" v-if="deployment" v-model="deployment" @save="saveDeployment" @cancel="cancelDeployment" /> </div> </div> @@ -33,7 +34,8 @@ export default { name: "application-editor-container", props: { id: String, - deployment_id: String + deployment_id: String, + hostId: String }, data: function() { return { @@ -63,6 +65,8 @@ export default { this.initialize(); if (this.deployment_id) { this.loadApplicationDeployment(this.deployment_id); + } else if (this.hostId) { + this.createNewDeployment(this.hostId); } }, methods: { @@ -80,7 +84,8 @@ export default { "loadApplicationDeployments", "loadApplicationDeployment", "createApplicationDeployment", - "updateApplicationDeployment" + "updateApplicationDeployment", + "deleteApplicationDeployment" ]), initialize() { // TODO: move this to applications store? @@ -138,11 +143,74 @@ export default { }) .catch(error => notifications.NotificationList.addError(error)); }, + createNewDeployment(computeHostId) { + const deployment = new models.ApplicationDeploymentDescription(); + deployment.appModuleId = this.id; + deployment.computeHostId = computeHostId; + this.deployment = deployment; + this.$router.push({ + name: "new_application_deployment", + params: { id: this.id, hostId: computeHostId } + }); + }, + saveDeployment() { + return this.saveAll().then(appDeployment => { + this.$router.push({ + name: "application_deployments", + params: { id: this.id } + }); + }); + }, + saveAll() { + const moduleSave = this.id + ? this.updateApplicationModule(this.module) + : this.createApplicationModule(this.module); + return moduleSave + .then(appModule => { + this.appInterface.applicationName = appModule.appModuleName; + this.appInterface.applicationDescription = + appModule.appModuleDescription; + + if (this.appInterface.applicationInterfaceId) { + return this.updateApplicationInterface(this.appInterface); + } else { + this.appInterface.applicationModules = [this.id]; + return this.createApplicationInterface(this.appInterface); + } + }) + .then(appInterface => { + if (this.deployment) { + if (this.deployment.appDeploymentId) { + return this.updateApplicationDeployment(this.deployment); + } else { + return this.createApplicationDeployment(this.deployment); + } + } else { + return Promise.resolve(null); + } + }); + }, cancelModule() { this.$router.push({ path: "/applications" }); }, cancelInterface() { this.$router.push({ path: "/applications" }); + }, + cancelDeployment() { + this.$router.push({ + name: "application_deployments", + params: { id: this.id } + }); + }, + deleteDeployment(deployment) { + return this.deleteApplicationDeployment(deployment) + .then(() => this.loadApplicationDeployments(this.id)) + .then(() => { + this.$router.push({ + name: "application_deployments", + params: { id: this.id } + }); + }); } }, watch: { diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/router.js b/django_airavata/apps/admin/static/django_airavata_admin/src/router.js index 23d68cc..43583ee 100644 --- a/django_airavata/apps/admin/static/django_airavata_admin/src/router.js +++ b/django_airavata/apps/admin/static/django_airavata_admin/src/router.js @@ -75,6 +75,12 @@ const routes = [ } }, { + path: 'deployments/new/:hostId', components: { + deployment: ApplicationDeploymentEditor + }, + name: 'new_application_deployment', + }, + { path: 'deployments/:deployment_id', components: { deployment: ApplicationDeploymentEditor }, diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/store/applications/app_deployments.js b/django_airavata/apps/admin/static/django_airavata_admin/src/store/applications/app_deployments.js index c042e8c..65c05f8 100644 --- a/django_airavata/apps/admin/static/django_airavata_admin/src/store/applications/app_deployments.js +++ b/django_airavata/apps/admin/static/django_airavata_admin/src/store/applications/app_deployments.js @@ -42,6 +42,13 @@ export default { commit('setCurrentDeployment', appDeployment); return appDeployment; }) + }, + deleteApplicationDeployment({ commit }, appDeployment) { + return services.ApplicationDeploymentService.delete({lookup: appDeployment.appDeploymentId }) + .then(() => { + commit('setCurrentDeployment', null); + return null; + }); } } } diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/store/applications/app_modules.js b/django_airavata/apps/admin/static/django_airavata_admin/src/store/applications/app_modules.js index 7678c81..7b3f890 100644 --- a/django_airavata/apps/admin/static/django_airavata_admin/src/store/applications/app_modules.js +++ b/django_airavata/apps/admin/static/django_airavata_admin/src/store/applications/app_modules.js @@ -45,8 +45,8 @@ export default { const appModulesCopy = state.modules.slice(); appModulesCopy.push(appModule); commit('setModules', appModulesCopy); - return appModule; } + return appModule; }); }, updateApplicationModule({ commit, state }, appModule) { @@ -57,8 +57,8 @@ export default { const appModules = state.modules.filter(mod => mod.appModuleId !== appModule.appModuleId) appModules.push(appModule); commit('setModules', appModules); - return appModule; } + return appModule; }) } } diff --git a/django_airavata/apps/api/static/django_airavata_api/js/index.js b/django_airavata/apps/api/static/django_airavata_api/js/index.js index 8c9a497..bfb9569 100644 --- a/django_airavata/apps/api/static/django_airavata_api/js/index.js +++ b/django_airavata/apps/api/static/django_airavata_api/js/index.js @@ -2,6 +2,7 @@ import UnhandledError from './errors/UnhandledError' import UnhandledErrorDispatcher from './errors/UnhandledErrorDispatcher' import UnhandledErrorDisplayList from './errors/UnhandledErrorDisplayList' +import ApplicationDeploymentDescription from './models/ApplicationDeploymentDescription' import ApplicationInterfaceDefinition from './models/ApplicationInterfaceDefinition' import ApplicationModule from './models/ApplicationModule' import BaseModel from './models/BaseModel' @@ -54,6 +55,7 @@ exports.errors = { } exports.models = { + ApplicationDeploymentDescription, ApplicationInterfaceDefinition, ApplicationModule, BaseModel, diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationDeploymentDescription.js b/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationDeploymentDescription.js index 812d540..1f35bfb 100644 --- a/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationDeploymentDescription.js +++ b/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationDeploymentDescription.js @@ -49,7 +49,11 @@ const FIELDS = [ 'defaultNodeCount', 'defaultCPUCount', 'defaultWalltime', - 'editableByUser', + { + name: 'editableByUser', + type: 'boolean', + default: false, + }, 'userHasWriteAccess' ]; 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 f7b7408..033958a 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,5 +1,6 @@ import ApplicationDeploymentDescription from './models/ApplicationDeploymentDescription' import ApplicationModule from './models/ApplicationModule'; +import ComputeResourceDescription from './models/ComputeResourceDescription' import CredentialSummary from './models/CredentialSummary' import Group from './models/Group' import GroupResourceProfile from './models/GroupResourceProfile' @@ -105,7 +106,7 @@ export default { url: "/api/compute-resources/all_names_list/", requestType: 'get', }], - modelClass: ApplicationDeploymentDescription, + modelClass: ComputeResourceDescription, }, "CredentialSummaries": { url: "/api/credential-summaries/", diff --git a/django_airavata/apps/api/views.py b/django_airavata/apps/api/views.py index 3ca84de..bb0b546 100644 --- a/django_airavata/apps/api/views.py +++ b/django_airavata/apps/api/views.py @@ -413,6 +413,10 @@ class ApplicationDeploymentViewSet(APIBackedViewSet): application_deployment.appDeploymentId, application_deployment) + def perform_destroy(self, instance): + self.request.airavata_client.deleteApplicationDeployment( + self.authz_token, instance.appDeploymentId) + @detail_route() def queues(self, request, app_deployment_id): """Return queues for this deployment with defaults overridden by deployment defaults if they exist"""
