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 2020/08/04 22:26:06 UTC

[airavata-django-portal] 01/02: AIRAVATA-3330 Refactor UI component and require at least one queue

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

commit b392b987f93ef05d027f581cf9dde622921df936
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Tue Aug 4 17:53:23 2020 -0400

    AIRAVATA-3330 Refactor UI component and require at least one queue
---
 .../BatchQueueResourcePolicy.vue                   |  14 +-
 .../ComputePreference.vue                          | 135 +++-----------
 .../ComputeResourcePolicyEditor.vue                | 197 +++++++++++++++++++++
 .../js/models/ComputeResourcePolicy.js             |  38 ++--
 4 files changed, 251 insertions(+), 133 deletions(-)

diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/BatchQueueResourcePolicy.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/BatchQueueResourcePolicy.vue
index 1a3dc11..7a06851 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/BatchQueueResourcePolicy.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/BatchQueueResourcePolicy.vue
@@ -16,7 +16,7 @@
           :max="batchQueue.maxNodes"
           :formatter="numberFormatter"
           :placeholder="'Max Nodes: ' + batchQueue.maxNodes"
-        :state="validationFeedback.maxAllowedNodes.state"
+          :state="validationFeedback.maxAllowedNodes.state"
         >
         </b-form-input>
       </b-form-group>
@@ -37,7 +37,7 @@
           :max="batchQueue.maxProcessors"
           :formatter="numberFormatter"
           :placeholder="'Max Cores: ' + batchQueue.maxProcessors"
-        :state="validationFeedback.maxAllowedCores.state"
+          :state="validationFeedback.maxAllowedCores.state"
         >
         </b-form-input>
       </b-form-group>
@@ -46,7 +46,9 @@
       <b-form-group
         label="Maximum Allowed Wall Time"
         label-for="max-allowed-walltime"
-        :invalid-feedback="validationFeedback.maxAllowedWalltime.invalidFeedback"
+        :invalid-feedback="
+          validationFeedback.maxAllowedWalltime.invalidFeedback
+        "
         :state="validationFeedback.maxAllowedWalltime.state"
       >
         <b-form-input
@@ -58,7 +60,7 @@
           :max="batchQueue.maxRunTime"
           :formatter="numberFormatter"
           :placeholder="'Max Wall Time: ' + batchQueue.maxRunTime"
-        :state="validationFeedback.maxAllowedWalltime.state"
+          :state="validationFeedback.maxAllowedWalltime.state"
         >
         </b-form-input>
       </b-form-group>
@@ -113,9 +115,9 @@ export default {
     },
     validate() {
       if (this.valid) {
-        this.$emit('valid');
+        this.$emit("valid");
       } else {
-        this.$emit('invalid');
+        this.$emit("invalid");
       }
     }
   },
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 013370b..7c3b38c 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
@@ -104,42 +104,19 @@
         <div class="card">
           <div class="card-body">
             <h5 class="card-title">Policy</h5>
-            <b-form-group
-              label="Allowed Queues"
-              v-if="localComputeResourcePolicy"
-            >
-              <div
-                v-for="batchQueue in computeResource.batchQueues"
-                :key="batchQueue.queueName"
-              >
-                <b-form-checkbox
-                  :checked="
-                    localComputeResourcePolicy.allowedBatchQueues.includes(
-                      batchQueue.queueName
-                    )
-                  "
-                  @input="batchQueueChecked(batchQueue, $event)"
-                >
-                  {{ batchQueue.queueName }}
-                </b-form-checkbox>
-                <batch-queue-resource-policy
-                  v-if="
-                    localComputeResourcePolicy.allowedBatchQueues.includes(
-                      batchQueue.queueName
-                    )
-                  "
-                  :batch-queue="batchQueue"
-                  :value="
-                    localBatchQueueResourcePolicies.find(
-                      pol => pol.queuename === batchQueue.queueName
-                    )
-                  "
-                  @input="updatedBatchQueueResourcePolicy(batchQueue, $event)"
-                  @valid="recordValidBatchQueueResourcePolicy(batchQueue)"
-                  @invalid="recordInvalidBatchQueueResourcePolicy(batchQueue)"
-                />
-              </div>
-            </b-form-group>
+            <compute-resource-policy-editor
+              :batch-queues="computeResource.batchQueues"
+              :compute-resource-policy="localComputeResourcePolicy"
+              :batch-queue-resource-policies="localBatchQueueResourcePolicies"
+              @compute-resource-policy-updated="
+                localComputeResourcePolicy = $event
+              "
+              @batch-queue-resource-policies-updated="
+                localBatchQueueResourcePolicies = $event
+              "
+              @valid="computeResourcePolicyInvalid = false"
+              @invalid="computeResourcePolicyInvalid = true"
+            />
           </div>
         </div>
       </div>
@@ -179,9 +156,9 @@
 
 <script>
 import DjangoAiravataAPI from "django-airavata-api";
-import BatchQueueResourcePolicy from "./BatchQueueResourcePolicy.vue";
 import SSHCredentialSelector from "../../credentials/SSHCredentialSelector.vue";
 import ComputeResourceReservationList from "./ComputeResourceReservationList";
+import ComputeResourcePolicyEditor from "./ComputeResourcePolicyEditor";
 
 import { models, services, errors } from "django-airavata-api";
 import {
@@ -194,10 +171,10 @@ import {
 export default {
   name: "compute-preference",
   components: {
-    BatchQueueResourcePolicy,
     "delete-button": components.DeleteButton,
     "ssh-credential-selector": SSHCredentialSelector,
-    ComputeResourceReservationList
+    ComputeResourceReservationList,
+    ComputeResourcePolicyEditor
   },
   props: {
     id: {
@@ -268,8 +245,8 @@ export default {
         jobSubmissionInterfaces: []
       },
       validationErrors: null,
-      invalidBatchQueueResourcePolicies: [],
-      reservationsInvalid: false
+      reservationsInvalid: false,
+      computeResourcePolicyInvalid: false
     };
   },
   computed: {
@@ -284,14 +261,9 @@ export default {
     },
     valid() {
       return (
-        this.allowedInvalidBatchQueueResourcePolicies.length === 0 &&
         Object.keys(this.groupComputeResourceValidation).length === 0 &&
-        !this.reservationsInvalid
-      );
-    },
-    allowedInvalidBatchQueueResourcePolicies() {
-      return this.invalidBatchQueueResourcePolicies.filter(queueName =>
-        this.localComputeResourcePolicy.allowedBatchQueues.includes(queueName)
+        !this.reservationsInvalid &&
+        !this.computeResourcePolicyInvalid
       );
     },
     queueNames() {
@@ -300,54 +272,6 @@ export default {
   },
   mixins: [mixins.VModelMixin],
   methods: {
-    batchQueueChecked: function(batchQueue, checked) {
-      if (checked) {
-        this.localComputeResourcePolicy.allowedBatchQueues.push(
-          batchQueue.queueName
-        );
-      } else {
-        const queueIndex = this.localComputeResourcePolicy.allowedBatchQueues.indexOf(
-          batchQueue.queueName
-        );
-        this.localComputeResourcePolicy.allowedBatchQueues.splice(
-          queueIndex,
-          1
-        );
-        // Remove batchQueueResourcePolicy if it exists
-        const policyIndex = this.localBatchQueueResourcePolicies.findIndex(
-          pol => pol.queuename === batchQueue.queueName
-        );
-        if (policyIndex >= 0) {
-          this.localBatchQueueResourcePolicies.splice(policyIndex, 1);
-        }
-      }
-    },
-    updatedBatchQueueResourcePolicy: function(
-      batchQueue,
-      batchQueueResourcePolicy
-    ) {
-      const queueName = batchQueue.queueName;
-      if (batchQueueResourcePolicy) {
-        const existingPolicy = this.localBatchQueueResourcePolicies.find(
-          pol => pol.queuename === queueName
-        );
-        if (existingPolicy) {
-          Object.assign(existingPolicy, batchQueueResourcePolicy);
-        } else {
-          // For new BatchQueueResourcePolicy instances, set the parent ids
-          batchQueueResourcePolicy.groupResourceProfileId = this.id;
-          batchQueueResourcePolicy.computeResourceId = this.host_id;
-          this.localBatchQueueResourcePolicies.push(batchQueueResourcePolicy);
-        }
-      } else {
-        const existingPolicyIndex = this.localBatchQueueResourcePolicies.findIndex(
-          pol => pol.queuename === queueName
-        );
-        if (existingPolicyIndex >= 0) {
-          this.localBatchQueueResourcePolicies.splice(existingPolicyIndex, 1);
-        }
-      }
-    },
     fetchComputeResource: function(id) {
       return DjangoAiravataAPI.utils.FetchUtils.get(
         "/api/compute-resources/" + encodeURIComponent(id) + "/"
@@ -452,25 +376,6 @@ export default {
         this.localComputeResourcePolicy = defaultComputeResourcePolicy;
       });
     },
-    recordValidBatchQueueResourcePolicy(batchQueue) {
-      if (
-        this.invalidBatchQueueResourcePolicies.includes(batchQueue.queueName)
-      ) {
-        const index = this.invalidBatchQueueResourcePolicies.indexOf(
-          batchQueue.queueName
-        );
-        this.invalidBatchQueueResourcePolicies.splice(index, 1);
-      }
-      this.validate(); // propagate validation
-    },
-    recordInvalidBatchQueueResourcePolicy(batchQueue) {
-      if (
-        !this.invalidBatchQueueResourcePolicies.includes(batchQueue.queueName)
-      ) {
-        this.invalidBatchQueueResourcePolicies.push(batchQueue.queueName);
-      }
-      this.validate(); // propagate validation
-    },
     validate() {
       if (this.valid) {
         this.$emit("valid");
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/ComputeResourcePolicyEditor.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/ComputeResourcePolicyEditor.vue
new file mode 100644
index 0000000..3f61d08
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/ComputeResourcePolicyEditor.vue
@@ -0,0 +1,197 @@
+<template>
+  <b-form-group
+    label="Allowed Queues"
+    v-if="localComputeResourcePolicy"
+    :invalid-feedback="validationFeedback.allowedBatchQueues.invalidFeedback"
+    :state="validationFeedback.allowedBatchQueues.state"
+  >
+    <div v-for="batchQueue in batchQueues" :key="batchQueue.queueName">
+      <b-form-checkbox
+        :checked="
+          localComputeResourcePolicy.allowedBatchQueues.includes(
+            batchQueue.queueName
+          )
+        "
+        @input="batchQueueChecked(batchQueue, $event)"
+      >
+        {{ batchQueue.queueName }}
+      </b-form-checkbox>
+      <batch-queue-resource-policy
+        v-if="
+          localComputeResourcePolicy.allowedBatchQueues.includes(
+            batchQueue.queueName
+          )
+        "
+        :batch-queue="batchQueue"
+        :value="
+          localBatchQueueResourcePolicies.find(
+            pol => pol.queuename === batchQueue.queueName
+          )
+        "
+        @input="updatedBatchQueueResourcePolicy(batchQueue, $event)"
+        @valid="recordValidBatchQueueResourcePolicy(batchQueue)"
+        @invalid="recordInvalidBatchQueueResourcePolicy(batchQueue)"
+      />
+    </div>
+  </b-form-group>
+</template>
+
+<script>
+import BatchQueueResourcePolicy from "./BatchQueueResourcePolicy.vue";
+
+import { models } from "django-airavata-api";
+import { errors } from "django-airavata-common-ui";
+
+export default {
+  name: "compute-resource-policy-editor",
+  props: {
+    batchQueues: {
+      type: Array
+    },
+    computeResourcePolicy: {
+      type: models.ComputeResourcePolicy
+    },
+    batchQueueResourcePolicies: {
+      type: Array
+    }
+  },
+  components: {
+    BatchQueueResourcePolicy
+  },
+  data: function() {
+    return {
+      localComputeResourcePolicy: this.computeResourcePolicy
+        ? this.computeResourcePolicy.clone()
+        : null,
+      localBatchQueueResourcePolicies: this.batchQueueResourcePolicies
+        ? this.batchQueueResourcePolicies.map(pol => pol.clone())
+        : [],
+      validationErrors: null,
+      invalidBatchQueueResourcePolicies: []
+    };
+  },
+  computed: {
+    computeResourcePolicyValidation() {
+      return this.localComputeResourcePolicy.validate();
+    },
+    validationFeedback() {
+      return errors.ValidationErrors.createValidationFeedback(
+        this.localComputeResourcePolicy,
+        this.computeResourcePolicyValidation
+      );
+    },
+    valid() {
+      return (
+        this.allowedInvalidBatchQueueResourcePolicies.length === 0 &&
+        Object.keys(this.computeResourcePolicyValidation).length === 0
+      );
+    },
+    allowedInvalidBatchQueueResourcePolicies() {
+      return this.invalidBatchQueueResourcePolicies.filter(queueName =>
+        this.localComputeResourcePolicy.allowedBatchQueues.includes(queueName)
+      );
+    }
+  },
+  methods: {
+    batchQueueChecked: function(batchQueue, checked) {
+      if (checked) {
+        this.localComputeResourcePolicy.allowedBatchQueues.push(
+          batchQueue.queueName
+        );
+      } else {
+        const queueIndex = this.localComputeResourcePolicy.allowedBatchQueues.indexOf(
+          batchQueue.queueName
+        );
+        this.localComputeResourcePolicy.allowedBatchQueues.splice(
+          queueIndex,
+          1
+        );
+        // Remove batchQueueResourcePolicy if it exists
+        const policyIndex = this.localBatchQueueResourcePolicies.findIndex(
+          pol => pol.queuename === batchQueue.queueName
+        );
+        if (policyIndex >= 0) {
+          this.localBatchQueueResourcePolicies.splice(policyIndex, 1);
+        }
+        this.$emit(
+          "batch-queue-resource-policies-updated",
+          this.localBatchQueueResourcePolicies
+        );
+      }
+      this.validate();
+      this.$emit(
+        "compute-resource-policy-updated",
+        this.localComputeResourcePolicy
+      );
+    },
+    updatedBatchQueueResourcePolicy: function(
+      batchQueue,
+      batchQueueResourcePolicy
+    ) {
+      const queueName = batchQueue.queueName;
+      if (batchQueueResourcePolicy) {
+        const existingPolicy = this.localBatchQueueResourcePolicies.find(
+          pol => pol.queuename === queueName
+        );
+        if (existingPolicy) {
+          Object.assign(existingPolicy, batchQueueResourcePolicy);
+        } else {
+          this.localComputeResourcePolicy.populateParentIdsOnBatchQueueResourcePolicy(
+            batchQueueResourcePolicy
+          );
+          this.localBatchQueueResourcePolicies.push(batchQueueResourcePolicy);
+        }
+      } else {
+        const existingPolicyIndex = this.localBatchQueueResourcePolicies.findIndex(
+          pol => pol.queuename === queueName
+        );
+        if (existingPolicyIndex >= 0) {
+          this.localBatchQueueResourcePolicies.splice(existingPolicyIndex, 1);
+        }
+      }
+      this.$emit(
+        "batch-queue-resource-policies-updated",
+        this.localBatchQueueResourcePolicies
+      );
+    },
+    recordValidBatchQueueResourcePolicy(batchQueue) {
+      if (
+        this.invalidBatchQueueResourcePolicies.includes(batchQueue.queueName)
+      ) {
+        const index = this.invalidBatchQueueResourcePolicies.indexOf(
+          batchQueue.queueName
+        );
+        this.invalidBatchQueueResourcePolicies.splice(index, 1);
+      }
+      this.validate(); // propagate validation
+    },
+    recordInvalidBatchQueueResourcePolicy(batchQueue) {
+      if (
+        !this.invalidBatchQueueResourcePolicies.includes(batchQueue.queueName)
+      ) {
+        this.invalidBatchQueueResourcePolicies.push(batchQueue.queueName);
+      }
+      this.validate(); // propagate validation
+    },
+    validate() {
+      if (this.valid) {
+        this.$emit("valid");
+      } else {
+        this.$emit("invalid");
+      }
+    }
+  },
+  watch: {
+    computeResourcePolicy(value) {
+      this.localComputeResourcePolicy = value.clone();
+    },
+    batchQueueResourcePolicies(value) {
+      this.localBatchQueueResourcePolicies = value
+        ? value.map(p => p.clone())
+        : [];
+    }
+  }
+};
+</script>
+
+<style></style>
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/ComputeResourcePolicy.js b/django_airavata/apps/api/static/django_airavata_api/js/models/ComputeResourcePolicy.js
index 82b97d5..b40d6a0 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/ComputeResourcePolicy.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/ComputeResourcePolicy.js
@@ -1,20 +1,34 @@
-import BaseModel from './BaseModel'
-
+import BaseModel from "./BaseModel";
 
 const FIELDS = [
-     'resourcePolicyId',
-     'computeResourceId',
-     'groupResourceProfileId',
-     {
-         name: 'allowedBatchQueues',
-         type: 'string',
-         list: true
-     }
+  "resourcePolicyId",
+  "computeResourceId",
+  "groupResourceProfileId",
+  {
+    name: "allowedBatchQueues",
+    type: "string",
+    list: true,
+  },
 ];
 
 export default class ComputeResourcePolicy extends BaseModel {
+  constructor(data = {}) {
+    super(FIELDS, data);
+  }
+
+  populateParentIdsOnBatchQueueResourcePolicy(batchQueueResourcePolicy) {
+    // For new BatchQueueResourcePolicy instances, set the parent ids
+    batchQueueResourcePolicy.groupResourceProfileId = this.groupResourceProfileId;
+    batchQueueResourcePolicy.computeResourceId = this.computeResourceId;
+    return batchQueueResourcePolicy;
+  }
 
-    constructor(data = {}) {
-        super(FIELDS, data);
+  validate() {
+    let validationResults = {};
+    if (!this.allowedBatchQueues || this.allowedBatchQueues.length === 0) {
+      validationResults["allowedBatchQueues"] =
+        "Must select at least one queue.";
     }
+    return validationResults;
+  }
 }