airavata-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From machris...@apache.org
Subject [airavata-django-portal] branch master updated: AIRAVATA-2876 Only allow admins to edit applications
Date Fri, 14 Sep 2018 19:40:09 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


The following commit(s) were added to refs/heads/master by this push:
     new b91e348  AIRAVATA-2876 Only allow admins to edit applications
b91e348 is described below

commit b91e3489d931ba58cdeb9d78259df47a8b622edc
Author: Marcus Christie <machrist@iu.edu>
AuthorDate: Fri Sep 14 15:37:58 2018 -0400

    AIRAVATA-2876 Only allow admins to edit applications
---
 .../applications/ApplicationDeploymentEditor.vue   |  28 +++---
 .../applications/ApplicationDeploymentsList.vue    |   4 +-
 .../applications/ApplicationEditorContainer.vue    |   5 +-
 .../applications/ApplicationInputFieldEditor.vue   |  30 +++---
 .../applications/ApplicationInterfaceEditor.vue    |  18 ++--
 .../applications/ApplicationModuleEditor.vue       |  12 ++-
 .../applications/ApplicationOutputFieldEditor.vue  |  19 ++--
 .../applications/CommandObjectsEditor.vue          |  14 +--
 .../components/applications/SetEnvPathsEditor.vue  |  12 ++-
 .../ComputeResourcePreferenceDashboard.vue         | 106 +++++++++++----------
 django_airavata/apps/api/serializers.py            |  10 ++
 .../js/models/ApplicationInterfaceDefinition.js    |   1 +
 .../js/models/ApplicationModule.js                 |  15 +--
 13 files changed, 161 insertions(+), 113 deletions(-)

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 015f7f5..7d27ebb 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
@@ -6,27 +6,29 @@
           {{ name }}
         </h1>
         <b-form-group label="Application Executable Path" label-for="executable-path">
-          <b-form-input id="executable-path" type="text" v-model="data.executablePath"
required></b-form-input>
+          <b-form-input id="executable-path" type="text" v-model="data.executablePath"
required :disabled="readonly"></b-form-input>
         </b-form-group>
         <b-form-group label="Application Parallelism Type" label-for="parallelism-type">
-          <b-form-select id="parallelism-type" v-model="data.parallelism" :options="parallelismTypeOptions"
/>
+          <b-form-select id="parallelism-type" v-model="data.parallelism" :options="parallelismTypeOptions"
:disabled="readonly" />
         </b-form-group>
         <b-form-group label="Application Deployment Description" label-for="deployment-description">
-          <b-form-textarea id="deployment-description" v-model="data.appDeploymentDescription"
:rows="3"></b-form-textarea>
+          <b-form-textarea id="deployment-description" v-model="data.appDeploymentDescription"
:rows="3" :disabled="readonly"></b-form-textarea>
         </b-form-group>
         <command-objects-editor title="Module Load Commands" add-button-label="Add Module
Load Command" v-model="data.moduleLoadCmds"
-        />
+          :readonly="readonly" />
         <set-env-paths-editor title="Library Prepend Paths" add-button-label="Add a Library
Prepend Path" v-model="data.libPrependPaths"
-        />
+          :readonly="readonly" />
         <set-env-paths-editor title="Library Append Paths" add-button-label="Add a Library
Append Path" v-model="data.libAppendPaths"
-        />
+          :readonly="readonly" />
         <set-env-paths-editor title="Environment Variables" add-button-label="Add Environment
Variable" v-model="data.setEnvironment"
+          :readonly="readonly" />
+        <command-objects-editor title="Pre Job Commands" add-button-label="Add Pre Job
Command" v-model="data.preJobCommands" :readonly="readonly"
         />
-        <command-objects-editor title="Pre Job Commands" add-button-label="Add Pre Job
Command" v-model="data.preJobCommands" />
         <command-objects-editor title="Post Job Commands" add-button-label="Add Post Job
Command" v-model="data.postJobCommands"
-        />
+          :readonly="readonly" />
         <b-form-group label="Default Queue Name" label-for="default-queue-name">
-          <b-form-select id="default-queue-name" v-model="data.defaultQueueName" :options="queueNameOptions"
@change="defaultQueueChanged">
+          <b-form-select id="default-queue-name" v-model="data.defaultQueueName" :options="queueNameOptions"
@change="defaultQueueChanged"
+            :disabled="readonly">
             <template slot="first">
               <option :value="null">Select a Default Queue</option>
             </template>
@@ -45,7 +47,7 @@
     </div>
     <div class="row mb-4">
       <div class="col">
-        <b-button variant="primary" @click="save">
+        <b-button variant="primary" @click="save" :disabled="readonly">
           Save
         </b-button>
         <b-button variant="secondary" @click="cancel">
@@ -72,6 +74,10 @@ export default {
     deployment_id: {
       type: String,
       required: true
+    },
+    readonly: {
+      type: Boolean,
+      default: false
     }
   },
   components: {
@@ -135,7 +141,7 @@ export default {
       return queue ? queue.maxRuntime : 0;
     },
     defaultQueueAttributesDisabled() {
-      return !this.data.defaultQueueName;
+      return !this.data.defaultQueueName || this.readonly;
     }
   },
   created() {
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 5c81732..8e856f2 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
@@ -5,11 +5,11 @@
 
         <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}}">
+            <router-link v-if="!data.item.userHasWriteAccess" :to="{name: 'application_deployment',
params: {id: id, deployment_id: data.item.appDeploymentId, readonly: true}}">
               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}}">
+            <router-link v-if="data.item.userHasWriteAccess" :to="{name: 'application_deployment',
params: {id: id, deployment_id: data.item.appDeploymentId, readonly: false}}">
               Edit
               <i class="fa fa-edit" aria-hidden="true"></i>
             </router-link>
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 4ca9e7f..5c18f2c 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
@@ -14,9 +14,10 @@
           <b-nav-item exact-active-class="active" exact :to="{name: 'application_interface',
params: {id: id}}" :disabled="!id">Interface</b-nav-item>
           <b-nav-item active-class="active" :to="{name: 'application_deployments', params:
{id: id}}" :disabled="!id">Deployments</b-nav-item>
         </b-nav>
-        <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="module" v-if="module" v-model="module" @save="saveModule" @cancel="cancelModule"
:readonly="!module.userHasWriteAccess"
         />
+        <router-view name="interface" v-if="appInterface" v-model="appInterface" @save="saveInterface"
@cancel="cancelInterface"
+          :readonly="!appInterface.userHasWriteAccess" />
         <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" />
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationInputFieldEditor.vue
b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationInputFieldEditor.vue
index 5388879..99dbadf 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationInputFieldEditor.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationInputFieldEditor.vue
@@ -1,54 +1,56 @@
 <template>
   <b-card>
     <div class="d-flex align-items-center" slot="header">
-      <div class="drag-handle mr-1 text-muted">
+      <div v-if="!readonly" class="drag-handle mr-1 text-muted">
         <font-awesome-icon icon="grip-vertical" />
         <span class="sr-only">Drag handle for reordering</span>
       </div>
       <div class="mr-auto">Input Field: {{ data.name }}</div>
-      <b-link class="text-secondary" @click="deleteApplicationInput">
+      <b-link v-if="!readonly" class="text-secondary" @click="deleteApplicationInput">
         <i class="fa fa-trash"></i>
         <span class="sr-only">Delete</span>
       </b-link>
     </div>
     <b-collapse :visible="!collapse">
       <b-form-group label="Name" :label-for="id+'-name'">
-        <b-form-input :id="id+'-name'" type="text" v-model="data.name" ref="nameInput"
required></b-form-input>
+        <b-form-input :id="id+'-name'" type="text" v-model="data.name" ref="nameInput"
required :disabled="readonly"></b-form-input>
       </b-form-group>
       <b-form-group label="Initial Value" :label-for="id+'-value'">
-        <b-form-input :id="id+'-value'" type="text" v-model="data.value"></b-form-input>
+        <b-form-input :id="id+'-value'" type="text" v-model="data.value" :disabled="readonly"></b-form-input>
       </b-form-group>
       <b-form-group label="Type" :label-for="id+'-type'">
-        <b-form-select :id="id+'-type'" v-model="data.type" :options="inputTypeOptions"
/>
+        <b-form-select :id="id+'-type'" v-model="data.type" :options="inputTypeOptions"
:disabled="readonly" />
       </b-form-group>
       <b-form-group label="Application Argument" :label-for="id+'-argument'">
-        <b-form-input :id="id+'-argument'" type="text" v-model="data.applicationArgument"></b-form-input>
+        <b-form-input :id="id+'-argument'" type="text" v-model="data.applicationArgument"
:disabled="readonly"></b-form-input>
       </b-form-group>
       <div class="d-flex">
         <b-form-group class="flex-fill" label="Standard Input" :label-for="id+'-standard-input'">
-          <b-form-radio-group :id="id+'-standard-input'" v-model="data.standardInput"
:options="trueFalseOptions">
+          <b-form-radio-group :id="id+'-standard-input'" v-model="data.standardInput"
:options="trueFalseOptions" :disabled="readonly">
           </b-form-radio-group>
         </b-form-group>
         <b-form-group class="flex-fill" label="Read Only" :label-for="id+'-read-only'">
-          <b-form-radio-group :id="id+'-read-only'" v-model="data.isReadOnly" :options="trueFalseOptions">
+          <b-form-radio-group :id="id+'-read-only'" v-model="data.isReadOnly" :options="trueFalseOptions"
:disabled="readonly">
           </b-form-radio-group>
         </b-form-group>
       </div>
       <b-form-group label="User Friendly Description" :label-for="id+'-user-friendly-description'">
-        <b-form-textarea :id="id+'-user-friendly-description'" v-model="data.userFriendlyDescription"
:rows="3" />
+        <b-form-textarea :id="id+'-user-friendly-description'" v-model="data.userFriendlyDescription"
:rows="3" :disabled="readonly"
+        />
       </b-form-group>
       <div class="d-flex">
         <b-form-group class="flex-fill" label="Data is staged" :label-for="id+'-data-staged'">
-          <b-form-radio-group :id="id+'-data-staged'" v-model="data.dataStaged" :options="trueFalseOptions">
+          <b-form-radio-group :id="id+'-data-staged'" v-model="data.dataStaged" :options="trueFalseOptions"
:disabled="readonly">
           </b-form-radio-group>
         </b-form-group>
         <b-form-group class="flex-fill" label="Required" :label-for="id+'-required'">
-          <b-form-radio-group :id="id+'-required'" v-model="data.isRequired" :options="trueFalseOptions">
+          <b-form-radio-group :id="id+'-required'" v-model="data.isRequired" :options="trueFalseOptions"
:disabled="readonly">
           </b-form-radio-group>
         </b-form-group>
       </div>
       <b-form-group class="flex-fill" label="Required on Command Line" :label-for="id+'-required-command-line'">
-        <b-form-radio-group :id="id+'-required-command-line'" v-model="data.requiredToAddedToCommandLine"
:options="trueFalseOptions">
+        <b-form-radio-group :id="id+'-required-command-line'" v-model="data.requiredToAddedToCommandLine"
:options="trueFalseOptions"
+          :disabled="readonly">
         </b-form-radio-group>
       </b-form-group>
     </b-collapse>
@@ -72,6 +74,10 @@ export default {
     },
     collapse: {
       type: Boolean
+    },
+    readonly: {
+      type: Boolean,
+      default: false
     }
   },
   computed: {
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationInterfaceEditor.vue
b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationInterfaceEditor.vue
index 417a9f8..2186bfd 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationInterfaceEditor.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationInterfaceEditor.vue
@@ -10,13 +10,13 @@
     <div class="row">
       <div class="col">
         <b-form-group label="Enable Archiving Working Directory" label-for="archive-directory">
-          <b-form-radio-group id="archive-directory" v-model="data.archiveWorkingDirectory"
:options="trueFalseOptions">
+          <b-form-radio-group id="archive-directory" v-model="data.archiveWorkingDirectory"
:options="trueFalseOptions" :disabled="readonly">
           </b-form-radio-group>
         </b-form-group>
       </div>
       <div class="col">
         <b-form-group label="Enable Optional File Inputs" label-for="optional-file-inputs">
-          <b-form-radio-group id="optional-file-inputs" v-model="data.hasOptionalFileInputs"
:options="trueFalseOptions">
+          <b-form-radio-group id="optional-file-inputs" v-model="data.hasOptionalFileInputs"
:options="trueFalseOptions" :disabled="readonly">
           </b-form-radio-group>
         </b-form-group>
       </div>
@@ -28,13 +28,13 @@
         </h1>
         <draggable v-model="data.applicationInputs" :options="dragOptions" @start="onDragStart"
@end="onDragEnd">
           <application-input-field-editor v-for="input in data.applicationInputs" :value="input"
:key="input.key" :focus="input.key === focusApplicationInputKey"
-            :collapse="collapseApplicationInputs" @input="updatedInput" @delete="deleteInput(input)"
/>
+            :collapse="collapseApplicationInputs" @input="updatedInput" @delete="deleteInput(input)"
:readonly="readonly" />
         </draggable>
       </div>
     </div>
     <div class="row mb-4">
       <div class="col">
-        <b-button variant="secondary" @click="addApplicationInput">
+        <b-button variant="secondary" @click="addApplicationInput" :disabled="readonly">
           Add application input
         </b-button>
       </div>
@@ -45,19 +45,19 @@
           Output Fields
         </h1>
         <application-output-field-editor v-for="output in data.applicationOutputs" :value="output"
:key="output.key" :focus="output.key === focusApplicationOutputKey"
-          @input="updatedOutput" @delete="deleteOutput(output)" />
+          @input="updatedOutput" @delete="deleteOutput(output)" :readonly="readonly" />
       </div>
     </div>
     <div class="row mb-4">
       <div class="col">
-        <b-button variant="secondary" @click="addApplicationOutput">
+        <b-button variant="secondary" @click="addApplicationOutput" :disabled="readonly">
           Add application output
         </b-button>
       </div>
     </div>
     <div class="row mb-4">
       <div class="col">
-        <b-button variant="primary" @click="save">
+        <b-button variant="primary" @click="save" :disabled="readonly">
           Save
         </b-button>
         <b-button variant="secondary" @click="cancel">
@@ -82,6 +82,10 @@ export default {
   props: {
     value: {
       type: models.ApplicationInterfaceDefinition
+    },
+    readonly: {
+      type: Boolean,
+      default: false
     }
   },
   components: {
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationModuleEditor.vue
b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationModuleEditor.vue
index b6d08a7..5eddc14 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationModuleEditor.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationModuleEditor.vue
@@ -6,19 +6,19 @@
           Application Details
         </h1>
         <b-form-group label="Application Name" label-for="application-name">
-          <b-form-input id="application-name" type="text" v-model="data.appModuleName"
required></b-form-input>
+          <b-form-input id="application-name" type="text" v-model="data.appModuleName"
required :disabled="readonly"></b-form-input>
         </b-form-group>
         <b-form-group label="Application Version" label-for="application-version">
-          <b-form-input id="application-version" type="text" v-model="data.appModuleVersion"></b-form-input>
+          <b-form-input id="application-version" type="text" v-model="data.appModuleVersion"
:disabled="readonly"></b-form-input>
         </b-form-group>
         <b-form-group label="Application Description" label-for="application-description">
-          <b-form-textarea id="application-description" v-model="data.appModuleDescription"
:rows="3"></b-form-textarea>
+          <b-form-textarea id="application-description" v-model="data.appModuleDescription"
:rows="3" :disabled="readonly"></b-form-textarea>
         </b-form-group>
       </div>
     </div>
     <div class="row">
       <div class="col">
-        <b-button variant="primary" @click="save">
+        <b-button variant="primary" @click="save" :disabled="readonly">
           Save
         </b-button>
         <b-button variant="secondary" @click="cancel">
@@ -39,6 +39,10 @@ export default {
   props: {
     value: {
       type: models.ApplicationModule
+    },
+    readonly: {
+      type: Boolean,
+      default: false
     }
   },
   methods: {
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationOutputFieldEditor.vue
b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationOutputFieldEditor.vue
index 7db4421..4cfec33 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationOutputFieldEditor.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationOutputFieldEditor.vue
@@ -2,30 +2,31 @@
   <b-card>
     <div class="d-flex align-items-center" slot="header">
       <div class="mr-auto">Output Field: {{ data.name }}</div>
-      <b-link class="text-secondary" @click="deleteApplicationOutput">
+      <b-link v-if="!readonly" class="text-secondary" @click="deleteApplicationOutput">
         <i class="fa fa-trash"></i>
         <span class="sr-only">Delete</span>
       </b-link>
     </div>
     <b-form-group label="Name" :label-for="id+'-name'">
-      <b-form-input :id="id+'-name'" type="text" v-model="data.name" ref="nameInput" required></b-form-input>
+      <b-form-input :id="id+'-name'" type="text" v-model="data.name" ref="nameInput" required
:disabled="readonly"></b-form-input>
     </b-form-group>
     <b-form-group label="Value" :label-for="id+'-value'">
-      <b-form-input :id="id+'-value'" type="text" v-model="data.value"></b-form-input>
+      <b-form-input :id="id+'-value'" type="text" v-model="data.value" :disabled="readonly"></b-form-input>
     </b-form-group>
     <b-form-group label="Type" :label-for="id+'-type'">
-      <b-form-select :id="id+'-type'" v-model="data.type" :options="outputTypeOptions"
/>
+      <b-form-select :id="id+'-type'" v-model="data.type" :options="outputTypeOptions"
:disabled="readonly" />
     </b-form-group>
     <b-form-group label="Application Argument" :label-for="id+'-argument'">
-      <b-form-input :id="id+'-argument'" type="text" v-model="data.applicationArgument"></b-form-input>
+      <b-form-input :id="id+'-argument'" type="text" v-model="data.applicationArgument"
:disabled="readonly"></b-form-input>
     </b-form-group>
     <div class="d-flex">
       <b-form-group class="flex-fill" label="Is Required" :label-for="id+'-required'">
-        <b-form-radio-group :id="id+'-required'" v-model="data.isRequired" :options="trueFalseOptions">
+        <b-form-radio-group :id="id+'-required'" v-model="data.isRequired" :options="trueFalseOptions"
:disabled="readonly">
         </b-form-radio-group>
       </b-form-group>
       <b-form-group class="flex-fill" label="Required on Command Line" :label-for="id+'-required-command-line'">
-        <b-form-radio-group :id="id+'-required-command-line'" v-model="data.requiredToAddedToCommandLine"
:options="trueFalseOptions">
+        <b-form-radio-group :id="id+'-required-command-line'" v-model="data.requiredToAddedToCommandLine"
:options="trueFalseOptions"
+          :disabled="readonly">
         </b-form-radio-group>
       </b-form-group>
     </div>
@@ -44,6 +45,10 @@ export default {
     },
     focus: {
       type: Boolean
+    },
+    readonly: {
+      type: Boolean,
+      default: false
     }
   },
   computed: {
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/CommandObjectsEditor.vue
b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/CommandObjectsEditor.vue
index 043ac46..f3655a2 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/CommandObjectsEditor.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/CommandObjectsEditor.vue
@@ -1,15 +1,15 @@
 <template>
   <b-card :title="title" title-tag="h5">
     <b-input-group v-for="commandObject in data" :key="commandObject.key" class="mb-1">
-      <b-form-input type="text" v-model="commandObject.command" required ref="commandObjectInputs"
/>
-      <b-input-group-append>
+      <b-form-input type="text" v-model="commandObject.command" required ref="commandObjectInputs"
:disabled="readonly" />
+      <b-input-group-append v-if="!readonly">
         <b-button variant="secondary" @click="deleteCommandObject(commandObject)">
           <i class="fa fa-trash"></i>
           <span class="sr-only">Delete</span>
         </b-button>
       </b-input-group-append>
     </b-input-group>
-    <b-button variant="secondary" @click="addCommandObject">{{ addButtonLabel }}</b-button>
+    <b-button v-if="!readonly" variant="secondary" @click="addCommandObject">{{ addButtonLabel
}}</b-button>
   </b-card>
 </template>
 
@@ -31,6 +31,10 @@ export default {
     addButtonLabel: {
       type: String,
       required: true
+    },
+    readonly: {
+      type: Boolean,
+      default: false
     }
   },
   methods: {
@@ -46,9 +50,7 @@ export default {
       );
     },
     deleteCommandObject(commandObject) {
-      const index = this.data.findIndex(
-        cmd => cmd.key === commandObject.key
-      );
+      const index = this.data.findIndex(cmd => cmd.key === commandObject.key);
       this.data.splice(index, 1);
     }
   }
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/SetEnvPathsEditor.vue
b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/SetEnvPathsEditor.vue
index 4a5b449..904761e 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/SetEnvPathsEditor.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/SetEnvPathsEditor.vue
@@ -1,17 +1,17 @@
 <template>
   <b-card :title="title" title-tag="h5">
     <b-input-group v-for="setEnvPath in data" :key="setEnvPath.key" class="mb-1 align-items-center">
-      <b-form-input type="text" v-model="setEnvPath.name" required placeholder="NAME"
ref="nameInputs" />
+      <b-form-input type="text" v-model="setEnvPath.name" required placeholder="NAME"
ref="nameInputs" :disabled="readonly" />
       <font-awesome-icon icon="equals" class="mx-1" />
-      <b-form-input type="text" v-model="setEnvPath.value" required placeholder="VALUE"
/>
-      <b-input-group-append>
+      <b-form-input type="text" v-model="setEnvPath.value" required placeholder="VALUE"
:disabled="readonly" />
+      <b-input-group-append v-if="!readonly">
         <b-button variant="secondary" @click="deleteEnvPath(setEnvPath)">
           <i class="fa fa-trash"></i>
           <span class="sr-only">Delete</span>
         </b-button>
       </b-input-group-append>
     </b-input-group>
-    <b-button variant="secondary" @click="addEnvPath">{{ addButtonLabel }}</b-button>
+    <b-button v-if="!readonly" variant="secondary" @click="addEnvPath">{{ addButtonLabel
}}</b-button>
   </b-card>
 </template>
 
@@ -33,6 +33,10 @@ export default {
     addButtonLabel: {
       type: String,
       required: true
+    },
+    readonly: {
+      type: Boolean,
+      default: false
     }
   },
   methods: {
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/dashboards/ComputeResourcePreferenceDashboard.vue
b/django_airavata/apps/admin/static/django_airavata_admin/src/components/dashboards/ComputeResourcePreferenceDashboard.vue
index 42a2520..c9fcc78 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/dashboards/ComputeResourcePreferenceDashboard.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/dashboards/ComputeResourcePreferenceDashboard.vue
@@ -1,11 +1,10 @@
 <template>
-  <list-layout @add-new-item="newGroupResourcePreference" :items="groupResourceProfiles"
-      title="Group Resource Profiles" new-item-button-text="New Group Resource Profile">
+  <list-layout @add-new-item="newGroupResourcePreference" :items="groupResourceProfiles"
title="Group Resource Profiles" new-item-button-text="New Group Resource Profile">
     <template slot="item-list" slot-scope="slotProps">
 
       <b-table striped hover :fields="fields" :items="slotProps.items">
         <template slot="action" slot-scope="data">
-          <router-link :to="{name: 'group_resource_preference', params: {value: data.item,
id: data.item.groupResourceProfileId}}">
+          <router-link v-if="data.item.userHasWriteAccess" :to="{name: 'group_resource_preference',
params: {value: data.item, id: data.item.groupResourceProfileId}}">
             Edit
             <i class="fa fa-edit" aria-hidden="true"></i>
           </router-link>
@@ -14,62 +13,67 @@
             <i class="fa fa-trash" aria-hidden="true"></i>
           </a>
         </template>
-      </b-table> 
+      </b-table>
     </template>
   </list-layout>
 </template>
 
 <script>
-  import {layouts} from 'django-airavata-common-ui'
-  import {services} from 'django-airavata-api'
-  import moment from 'moment'
+import { layouts } from "django-airavata-common-ui";
+import { services } from "django-airavata-api";
+import moment from "moment";
 
-  export default {
-    name: "compute-resource-preference",
-    components: {
-      'list-layout': layouts.ListLayout,
+export default {
+  name: "compute-resource-preference",
+  components: {
+    "list-layout": layouts.ListLayout
+  },
+  data: function() {
+    return {
+      groupResourceProfiles: [],
+      fields: [
+        {
+          label: "Name",
+          key: "groupResourceProfileName"
+        },
+        {
+          label: "Updated",
+          key: "updatedTime",
+          formatter: value => moment(new Date(value)).fromNow()
+        },
+        {
+          label: "Action",
+          key: "action"
+        }
+      ]
+    };
+  },
+  methods: {
+    newGroupResourcePreference: function() {
+      this.$router.push({
+        name: "new_group_resource_preference"
+      });
     },
-    data: function () {
-      return {
-        groupResourceProfiles: [],
-        fields: [
-          {
-            label: 'Name',
-            key: 'groupResourceProfileName',
-          },
-          {
-            label: 'Updated',
-            key: 'updatedTime',
-            formatter: (value) => moment(new Date(value)).fromNow(),
-          },
-          {
-            label: 'Action',
-            key: 'action',
-          },
-        ],
-      }
+    loadGroupResourceProfiles: function() {
+      services.GroupResourceProfileService.list().then(
+        groupResourceProfiles => {
+          this.groupResourceProfiles = groupResourceProfiles;
+        }
+      );
     },
-    methods: {
-      newGroupResourcePreference: function () {
-        this.$router.push({
-          name: 'new_group_resource_preference'
-        });
-      },
-      loadGroupResourceProfiles: function () {
-        services.GroupResourceProfileService.list()
-          .then(groupResourceProfiles => {
-            this.groupResourceProfiles = groupResourceProfiles;
-          });
-      },
-      removeGroupResourceProfile: function(groupResourceProfile) {
-
-        services.GroupResourceProfileService.delete({lookup: groupResourceProfile.groupResourceProfileId})
-          .then(() => services.GroupResourceProfileService.list())
-          .then(groupResourceProfiles => this.groupResourceProfiles = groupResourceProfiles);
-      }
-    },
-    mounted: function () {
-      this.loadGroupResourceProfiles();
+    removeGroupResourceProfile: function(groupResourceProfile) {
+      services.GroupResourceProfileService.delete({
+        lookup: groupResourceProfile.groupResourceProfileId
+      })
+        .then(() => services.GroupResourceProfileService.list())
+        .then(
+          groupResourceProfiles =>
+            (this.groupResourceProfiles = groupResourceProfiles)
+        );
     }
+  },
+  mounted: function() {
+    this.loadGroupResourceProfiles();
   }
+};
 </script>
diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
index eb77164..66d0026 100644
--- a/django_airavata/apps/api/serializers.py
+++ b/django_airavata/apps/api/serializers.py
@@ -252,10 +252,15 @@ class ApplicationModuleSerializer(
     url = FullyEncodedHyperlinkedIdentityField(view_name='django_airavata_api:application-detail',
lookup_field='appModuleId', lookup_url_kwarg='app_module_id')
     applicationInterface = FullyEncodedHyperlinkedIdentityField(view_name='django_airavata_api:application-application-interface',
lookup_field='appModuleId', lookup_url_kwarg='app_module_id')
     applicationDeployments = FullyEncodedHyperlinkedIdentityField(view_name='django_airavata_api:application-application-deployments',
lookup_field='appModuleId', lookup_url_kwarg='app_module_id')
+    userHasWriteAccess = serializers.SerializerMethodField()
 
     class Meta:
         required = ('appModuleName',)
 
+    def get_userHasWriteAccess(self, appDeployment):
+        request = self.context['request']
+        return request.is_gateway_admin
+
 
 class InputDataObjectTypeSerializer(
         thrift_utils.create_serializer_class(InputDataObjectType)):
@@ -272,6 +277,11 @@ class ApplicationInterfaceDescriptionSerializer(
     applicationInputs = OrderedListField(
         order_by='inputOrder',
         child=InputDataObjectTypeSerializer())
+    userHasWriteAccess = serializers.SerializerMethodField()
+
+    def get_userHasWriteAccess(self, appDeployment):
+        request = self.context['request']
+        return request.is_gateway_admin
 
 
 class CommandObjectSerializer(
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationInterfaceDefinition.js
b/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationInterfaceDefinition.js
index 17cb856..fe46c61 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationInterfaceDefinition.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationInterfaceDefinition.js
@@ -36,6 +36,7 @@ const FIELDS = [
     type: 'boolean',
     default: false,
   },
+  'userHasWriteAccess',
 ];
 
 export default class ApplicationInterfaceDefinition extends BaseModel {
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationModule.js
b/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationModule.js
index 5ea8e35..b3f01cc 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationModule.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationModule.js
@@ -1,14 +1,15 @@
 import BaseModel from './BaseModel';
 
 const FIELDS = [
-    'appModuleId',
-    'appModuleName',
-    'appModuleVersion',
-    'appModuleDescription',
+  'appModuleId',
+  'appModuleName',
+  'appModuleVersion',
+  'appModuleDescription',
+  'userHasWriteAccess',
 ];
 
 export default class ApplicationModule extends BaseModel {
-    constructor(data = {}) {
-        super(FIELDS, data);
-    }
+  constructor(data = {}) {
+    super(FIELDS, data);
+  }
 }


Mime
View raw message