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 2018/11/15 16:13:13 UTC

[airavata-django-portal] branch master updated (0fd592a -> 1d847ad)

This is an automated email from the ASF dual-hosted git repository.

machristie pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git.


    from 0fd592a  AIRAVATA-2888 Add new nav extra, create account/login buttons to default theme
     new bae7376  AIRAVATA-2711 Regenerated Python thrift models
     new f39ed7f  AIRAVATA-2711 REST API to update group admins
     new 76083c6  AIRAVATA-2711 Switch to using ServiceFactory for groups
     new 173edb7  AIRAVATA-2711 Raise AutocompleteTextInput above form-controls
     new fe389d0  AIRAVATA-2711 Convert Autocomplete to VModelMixin
     new bc8b0ef  AIRAVATA-2711 Switch member editor to table layout
     new b6f870f  AIRAVATA-2711 Change role of group members
     new a1607ec  AIRAVATA-2711 Sorting members, UI clean up
     new e6d9344  AIRAVATA-2711 Only owners can edit admins
     new 1d847ad  AIRAVATA-2711 Removing Autocomplete.vue component

The 10 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 airavata/model/group/ttypes.py                     |  26 +++-
 django_airavata/apps/api/serializers.py            |  36 +++--
 .../api/static/django_airavata_api/js/index.js     |   3 +-
 .../static/django_airavata_api/js/models/Group.js  |   1 +
 .../js/services/GroupService.js                    |  63 ---------
 django_airavata/apps/api/views.py                  |  22 +--
 .../js/containers/GroupEditContainer.vue           |   2 +-
 .../js/containers/GroupsManageContainer.vue        |   2 +-
 .../js/group_components/GroupEditor.vue            | 116 +++++++++-------
 .../js/group_components/GroupListItem.vue          |   2 +-
 .../js/group_components/GroupMembersEditor.vue     | 151 +++++++++++++++++++++
 .../static/common/js/components/Autocomplete.vue   |  70 ----------
 .../common/js/components/AutocompleteTextInput.vue |   8 +-
 .../static/common/js/components/ShareButton.vue    |   4 +-
 django_airavata/static/common/js/index.js          |   2 -
 15 files changed, 282 insertions(+), 226 deletions(-)
 delete mode 100644 django_airavata/apps/api/static/django_airavata_api/js/services/GroupService.js
 create mode 100644 django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupMembersEditor.vue
 delete mode 100644 django_airavata/static/common/js/components/Autocomplete.vue


[airavata-django-portal] 06/10: AIRAVATA-2711 Switch member editor to table layout

Posted by ma...@apache.org.
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 bc8b0efa1ccb267b4e47bdf58128c4d3226e091b
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Wed Nov 14 12:44:51 2018 -0500

    AIRAVATA-2711 Switch member editor to table layout
---
 .../js/group_components/GroupEditor.vue            | 107 ++++++++++---------
 .../js/group_components/GroupMembersEditor.vue     | 113 +++++++++++++++++++++
 2 files changed, 166 insertions(+), 54 deletions(-)

diff --git a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue
index 5f7f205..cb08f20 100644
--- a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue
+++ b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue
@@ -16,9 +16,8 @@
         </b-form-textarea>
       </b-form-group>
 
-      <b-form-group id="group3" label="Add Members:" label-for="members">
-        <autocomplete id="members" :suggestions="suggestions" v-model="localGroup.members"/>
-      </b-form-group>
+      <group-members-editor :members="localGroup.members" :admins="localGroup.admins"
+        @add-member="addGroupMember" @remove-member="removeGroupMember" />
 
       <b-button @click="submitForm" variant="primary">Submit</b-button>
     </b-form>
@@ -26,60 +25,60 @@
 </template>
 
 <script>
+import { models, services } from "django-airavata-api";
+import GroupMembersEditor from "./GroupMembersEditor.vue";
 
-import { models, services } from 'django-airavata-api'
-import { components as comps } from 'django-airavata-common-ui'
-
-const Autocomplete = comps.Autocomplete;
 
 export default {
-    props: {
-        group: {
-            type: models.Group,
-            required: true,
-        },
-    },
-    data () {
-        return {
-            localGroup: this.group.clone(),
-            showDismissibleAlert: {'variant':'success', 'message':'no data', 'dismissable':false},
-            userProfiles: [],
-        }
-    },
-    components: {
-        Autocomplete
-    },
-    methods: {
-        submitForm () {
-            let saveOperation = (this.localGroup.id)
-                ? services.GroupService.update({lookup: this.localGroup.id, data: this.localGroup})
-                : services.GroupService.create({data: this.localGroup});
-            saveOperation
-                .then(group => {
-                    this.$emit('saved', group);
-                })
-                .catch(error => {
-                    this.showDismissibleAlert.dismissable = true;
-                    this.showDismissibleAlert.message = "Error: "+error.data;
-                    this.showDismissibleAlert.variant = "danger";
-                });
-        },
-    },
-    computed: {
-        suggestions: function() {
-            return this.userProfiles.map(userProfile => {
-                return {
-                    id: userProfile.airavataInternalUserId,
-                    name: userProfile.firstName + ' ' + userProfile.lastName + ' (' + userProfile.userId + ')'
-                }
-            })
-        }
+  props: {
+    group: {
+      type: models.Group,
+      required: true
+    }
+  },
+  data() {
+    return {
+      localGroup: this.group.clone(),
+      showDismissibleAlert: {
+        variant: "success",
+        message: "no data",
+        dismissable: false
+      },
+      userProfiles: []
+    };
+  },
+  components: {
+    GroupMembersEditor
+  },
+  methods: {
+    submitForm() {
+      let saveOperation = this.localGroup.id
+        ? services.GroupService.update({
+            lookup: this.localGroup.id,
+            data: this.localGroup
+          })
+        : services.GroupService.create({ data: this.localGroup });
+      saveOperation
+        .then(group => {
+          this.$emit("saved", group);
+        })
+        .catch(error => {
+          this.showDismissibleAlert.dismissable = true;
+          this.showDismissibleAlert.message = "Error: " + error.data;
+          this.showDismissibleAlert.variant = "danger";
+        });
     },
-    mounted: function () {
-        services.UserProfileService.list()
-            .then(userProfiles => {
-                this.userProfiles = userProfiles;
-            });
+    addGroupMember(airavataInternalUserId) {
+      this.localGroup.members.push(airavataInternalUserId);
     },
-}
+    removeGroupMember(airavataInternalUserId) {
+      const index = this.localGroup.members.indexOf(airavataInternalUserId);
+      this.localGroup.members.splice(index, 1);
+      const adminIndex = this.localGroup.admins.indexOf(airavataInternalUserId);
+      if (adminIndex >= 0) {
+        this.localGroup.admins.splice(adminIndex, 1);
+      }
+    }
+  }
+};
 </script>
diff --git a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupMembersEditor.vue b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupMembersEditor.vue
new file mode 100644
index 0000000..6582645
--- /dev/null
+++ b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupMembersEditor.vue
@@ -0,0 +1,113 @@
+<template>
+  <div>
+    <b-form-group label="Add members" labelFor="user-autocomplete">
+      <autocomplete-text-input id="user-autocomplete" :suggestions="suggestions" @selected="suggestionSelected" />
+    </b-form-group>
+    <b-table v-if="membersCount > 0" hover :items="currentMembers" :fields="fields">
+      <template slot="remove" slot-scope="data">
+        <b-link @click="removeMember(data.item)">
+          <span class="fa fa-trash"></span>
+        </b-link>
+      </template>
+    </b-table>
+  </div>
+</template>
+
+<script>
+import { services } from "django-airavata-api";
+import { components } from "django-airavata-common-ui";
+
+export default {
+  name: "group-members-editor",
+  components: {
+    "autocomplete-text-input": components.AutocompleteTextInput
+  },
+  props: {
+    members: {
+      type: Array,
+      required: true
+    },
+    admins: {
+      type: Array,
+      required: true
+    }
+  },
+  data() {
+    return {
+      userProfiles: null
+    };
+  },
+  computed: {
+    suggestions() {
+      if (!this.userProfiles) {
+        return [];
+      }
+      // TODO: filter out current members
+      return this.userProfiles.map(userProfile => {
+        return {
+          id: userProfile.airavataInternalUserId,
+          name:
+            userProfile.firstName +
+            " " +
+            userProfile.lastName +
+            " (" +
+            userProfile.userId +
+            ")"
+        };
+      });
+    },
+    fields() {
+      return [
+        { key: "name", label: "Name" },
+        { key: "username", label: "Username" },
+        { key: "email", label: "Email" },
+        { key: "role", label: "Role" },
+        { key: "remove", label: "Remove" }
+      ];
+    },
+    userProfilesMap() {
+      if (!this.userProfiles) {
+        return null;
+      }
+      const result = {};
+      this.userProfiles.forEach(up => {
+        result[up.airavataInternalUserId] = up;
+      });
+      return result;
+    },
+    currentMembers() {
+      if (!this.userProfilesMap) {
+        return [];
+      }
+      return this.members.map(m => {
+        const userProfile = this.userProfilesMap[m];
+        const isAdmin = this.admins.indexOf(m) >= 0;
+        return {
+          id: m,
+          name: userProfile.firstName + " " + userProfile.lastName,
+          username: userProfile.userId,
+          email: userProfile.email,
+          role: isAdmin ? "ADMIN" : "MEMBER"
+        };
+      });
+    },
+    membersCount() {
+      return this.members.length;
+    }
+  },
+  created() {
+    services.UserProfileService.list().then(userProfiles => {
+      this.userProfiles = userProfiles;
+    });
+  },
+  methods: {
+    suggestionSelected(suggestion) {
+      this.$emit('add-member', suggestion.id);
+    },
+    removeMember(item) {
+      this.$emit('remove-member', item.id);
+    }
+  }
+};
+</script>
+


[airavata-django-portal] 01/10: AIRAVATA-2711 Regenerated Python thrift models

Posted by ma...@apache.org.
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 bae7376b4ec541e1c032efab4041eb696845dcf4
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Wed Nov 7 10:30:08 2018 -0500

    AIRAVATA-2711 Regenerated Python thrift models
---
 airavata/model/group/ttypes.py | 26 +++++++++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/airavata/model/group/ttypes.py b/airavata/model/group/ttypes.py
index f06cb0c..deccc9d 100644
--- a/airavata/model/group/ttypes.py
+++ b/airavata/model/group/ttypes.py
@@ -70,6 +70,7 @@ class GroupModel(object):
      - ownerId
      - description
      - members
+     - admins
     """
 
     thrift_spec = (
@@ -79,14 +80,16 @@ class GroupModel(object):
         (3, TType.STRING, 'ownerId', 'UTF8', None, ),  # 3
         (4, TType.STRING, 'description', 'UTF8', None, ),  # 4
         (5, TType.LIST, 'members', (TType.STRING, 'UTF8', False), None, ),  # 5
+        (6, TType.LIST, 'admins', (TType.STRING, 'UTF8', False), None, ),  # 6
     )
 
-    def __init__(self, id=None, name=None, ownerId=None, description=None, members=None,):
+    def __init__(self, id=None, name=None, ownerId=None, description=None, members=None, admins=None,):
         self.id = id
         self.name = name
         self.ownerId = ownerId
         self.description = description
         self.members = members
+        self.admins = admins
 
     def read(self, iprot):
         if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
@@ -127,6 +130,16 @@ class GroupModel(object):
                     iprot.readListEnd()
                 else:
                     iprot.skip(ftype)
+            elif fid == 6:
+                if ftype == TType.LIST:
+                    self.admins = []
+                    (_etype9, _size6) = iprot.readListBegin()
+                    for _i10 in range(_size6):
+                        _elem11 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                        self.admins.append(_elem11)
+                    iprot.readListEnd()
+                else:
+                    iprot.skip(ftype)
             else:
                 iprot.skip(ftype)
             iprot.readFieldEnd()
@@ -156,8 +169,15 @@ class GroupModel(object):
         if self.members is not None:
             oprot.writeFieldBegin('members', TType.LIST, 5)
             oprot.writeListBegin(TType.STRING, len(self.members))
-            for iter6 in self.members:
-                oprot.writeString(iter6.encode('utf-8') if sys.version_info[0] == 2 else iter6)
+            for iter12 in self.members:
+                oprot.writeString(iter12.encode('utf-8') if sys.version_info[0] == 2 else iter12)
+            oprot.writeListEnd()
+            oprot.writeFieldEnd()
+        if self.admins is not None:
+            oprot.writeFieldBegin('admins', TType.LIST, 6)
+            oprot.writeListBegin(TType.STRING, len(self.admins))
+            for iter13 in self.admins:
+                oprot.writeString(iter13.encode('utf-8') if sys.version_info[0] == 2 else iter13)
             oprot.writeListEnd()
             oprot.writeFieldEnd()
         oprot.writeFieldStop()


[airavata-django-portal] 10/10: AIRAVATA-2711 Removing Autocomplete.vue component

Posted by ma...@apache.org.
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 1d847ad36f1b03249cda9b13c3bacb02c1559813
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Thu Nov 15 11:12:48 2018 -0500

    AIRAVATA-2711 Removing Autocomplete.vue component
---
 .../static/common/js/components/Autocomplete.vue   | 61 ----------------------
 django_airavata/static/common/js/index.js          |  2 -
 2 files changed, 63 deletions(-)

diff --git a/django_airavata/static/common/js/components/Autocomplete.vue b/django_airavata/static/common/js/components/Autocomplete.vue
deleted file mode 100644
index 8648177..0000000
--- a/django_airavata/static/common/js/components/Autocomplete.vue
+++ /dev/null
@@ -1,61 +0,0 @@
-<template>
-  <div style="position:relative">
-    <span class="selected-cards" style="position:relative">
-      <b-button variant="warning" v-for="item in selected" v-bind:key="item.id" @click="removeClick(item)">
-        {{ item.name }} <b-badge variant="light"><a href="#">x</a></b-badge>
-      </b-button>
-    </span>
-    <hr>
-    <autocomplete-text-input :suggestions="suggestions" @selected="suggestionSelected" />
-  </div>
-</template>
-
-<script>
-import AutocompleteTextInput from "./AutocompleteTextInput.vue";
-import VModelMixin from "../mixins/VModelMixin";
-
-export default {
-  name: "autocomplete",
-  mixins: [VModelMixin],
-  props: {
-    value: {
-      type: Array
-    },
-
-    suggestions: {
-      type: Array,
-      required: true
-    }
-  },
-  components: {
-    AutocompleteTextInput
-  },
-  computed: {
-    selected() {
-      return this.suggestions.filter(suggestion => {
-        return this.data.indexOf(suggestion.id) >= 0;
-      });
-    }
-  },
-  methods: {
-    suggestionSelected(suggestion) {
-      if (this.data.indexOf(suggestion.id) == -1) {
-        this.data.push(suggestion.id);
-      }
-    },
-    removeClick(data) {
-      var index = this.data.indexOf(data.id);
-      this.data.splice(index, 1);
-    }
-  }
-};
-</script>
-<style>
-.selected-cards > button {
-  margin-bottom: 10px;
-  margin-right: 10px;
-}
-.selected-cards > button:last-child {
-  margin-right: 0px;
-}
-</style>
diff --git a/django_airavata/static/common/js/index.js b/django_airavata/static/common/js/index.js
index 2cd1d48..eb66c54 100644
--- a/django_airavata/static/common/js/index.js
+++ b/django_airavata/static/common/js/index.js
@@ -1,5 +1,4 @@
 import ApplicationCard from "./components/ApplicationCard.vue";
-import Autocomplete from "./components/Autocomplete.vue";
 import AutocompleteTextInput from "./components/AutocompleteTextInput.vue";
 import ConfirmationDialog from "./components/ConfirmationDialog.vue";
 import DeleteButton from "./components/DeleteButton.vue";
@@ -24,7 +23,6 @@ import * as utils from "./utils";
 exports.components = {
   Pager,
   ApplicationCard,
-  Autocomplete,
   AutocompleteTextInput,
   ConfirmationDialog,
   DeleteButton,


[airavata-django-portal] 08/10: AIRAVATA-2711 Sorting members, UI clean up

Posted by ma...@apache.org.
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 a1607ec61d0c41fc026cbd3fe126c5c086c7d1b7
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Thu Nov 15 09:56:52 2018 -0500

    AIRAVATA-2711 Sorting members, UI clean up
---
 .../js/group_components/GroupEditor.vue                   |  6 ++++--
 .../js/group_components/GroupMembersEditor.vue            | 15 ++++++++-------
 .../static/common/js/components/AutocompleteTextInput.vue |  6 +++++-
 3 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue
index 9305101..0e28ded 100644
--- a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue
+++ b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue
@@ -16,8 +16,10 @@
         </b-form-textarea>
       </b-form-group>
 
-      <group-members-editor :members="localGroup.members" :admins="localGroup.admins" @add-member="addGroupMember"
-        @remove-member="removeGroupMember" @change-role-to-member="changeRoleToMember" @change-role-to-admin="changeRoleToAdmin" />
+      <b-card title="Group Members" title-tag="h5">
+        <group-members-editor :members="localGroup.members" :admins="localGroup.admins" @add-member="addGroupMember"
+          @remove-member="removeGroupMember" @change-role-to-member="changeRoleToMember" @change-role-to-admin="changeRoleToAdmin" />
+      </b-card>
 
       <b-button @click="submitForm" variant="primary">Submit</b-button>
     </b-form>
diff --git a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupMembersEditor.vue b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupMembersEditor.vue
index d20c6d4..5e8e1e5 100644
--- a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupMembersEditor.vue
+++ b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupMembersEditor.vue
@@ -1,9 +1,10 @@
 <template>
   <div>
-    <b-form-group label="Add members" labelFor="user-autocomplete">
-      <autocomplete-text-input id="user-autocomplete" :suggestions="suggestions" @selected="suggestionSelected" />
+    <b-form-group>
+      <autocomplete-text-input id="user-autocomplete" :suggestions="suggestions" @selected="suggestionSelected"
+        placeholder="Search for users to add to this group" />
     </b-form-group>
-    <b-table v-if="membersCount > 0" hover :items="currentMembers" :fields="fields">
+    <b-table v-if="membersCount > 0" hover :items="currentMembers" :fields="fields" sort-by="name">
       <template slot="role" slot-scope="data">
         <b-form-select :value="data.item.role" @input="changeRole(data.item, $event)" :options="groupRoleOptions">
         </b-form-select>
@@ -62,10 +63,10 @@ export default {
     },
     fields() {
       return [
-        { key: "name", label: "Name" },
-        { key: "username", label: "Username" },
-        { key: "email", label: "Email" },
-        { key: "role", label: "Role" },
+        { key: "name", label: "Name", sortable: true },
+        { key: "username", label: "Username", sortable: true },
+        { key: "email", label: "Email", sortable: true },
+        { key: "role", label: "Role", sortable: true },
         { key: "remove", label: "Remove" }
       ];
     },
diff --git a/django_airavata/static/common/js/components/AutocompleteTextInput.vue b/django_airavata/static/common/js/components/AutocompleteTextInput.vue
index 709c640..511232b 100644
--- a/django_airavata/static/common/js/components/AutocompleteTextInput.vue
+++ b/django_airavata/static/common/js/components/AutocompleteTextInput.vue
@@ -4,7 +4,7 @@
       <b-input-group-text slot="prepend">
         <i class="fa fa-search"></i>
       </b-input-group-text>
-      <b-form-input type="text" :value="searchValue" placeholder="Type to get suggestions..." @input="updateSearchValue" @keydown.native.enter='enter'
+      <b-form-input type="text" :value="searchValue" :placeholder="placeholder" @input="updateSearchValue" @keydown.native.enter='enter'
         @keydown.native.down='down' @keydown.native.up='up'></b-form-input>
     </b-input-group>
     <b-list-group class="autocomplete-suggestion-list" v-if="open">
@@ -25,6 +25,10 @@ export default {
     suggestions: {
       type: Array,
       required: true
+    },
+    placeholder: {
+      type: String,
+      default: "Type to get suggestions..."
     }
   },
   data() {


[airavata-django-portal] 03/10: AIRAVATA-2711 Switch to using ServiceFactory for groups

Posted by ma...@apache.org.
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 76083c6ea8f61f36fa84c7b20a29085ad308c05d
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Wed Nov 7 11:51:31 2018 -0500

    AIRAVATA-2711 Switch to using ServiceFactory for groups
---
 .../api/static/django_airavata_api/js/index.js     |  3 +-
 .../static/django_airavata_api/js/models/Group.js  |  1 +
 .../js/services/GroupService.js                    | 63 ----------------------
 .../js/containers/GroupEditContainer.vue           |  2 +-
 .../js/containers/GroupsManageContainer.vue        |  2 +-
 .../js/group_components/GroupEditor.vue            |  4 +-
 .../js/group_components/GroupListItem.vue          |  2 +-
 .../static/common/js/components/ShareButton.vue    |  4 +-
 8 files changed, 9 insertions(+), 72 deletions(-)

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 7a04bee..9cfa626 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
@@ -33,7 +33,6 @@ import ExperimentService from "./services/ExperimentService";
 import ExperimentSearchService from "./services/ExperimentSearchService";
 import FullExperimentService from "./services/FullExperimentService";
 import ProjectService from "./services/ProjectService";
-import GroupService from "./services/GroupService";
 import UserProfileService from "./services/UserProfileService";
 import CloudJobSubmissionService from "./services/CloudJobSubmissionService";
 import GlobusJobSubmissionService from "./services/GlobusJobSubmissionService";
@@ -99,7 +98,7 @@ exports.services = {
   GlobusJobSubmissionService,
   GridFTPDataMovementService,
   GroupResourceProfileService: ServiceFactory.service("GroupResourceProfiles"),
-  GroupService,
+  GroupService: ServiceFactory.service("Groups"),
   LocaJobSubmissionService,
   ProjectService,
   SCPDataMovementService,
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/Group.js b/django_airavata/apps/api/static/django_airavata_api/js/models/Group.js
index 54afe01..7b6fb42 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/Group.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/Group.js
@@ -6,6 +6,7 @@ const FIELDS = [
     'ownerId',
     'description',
     'members',
+    'admins',
     'isOwner',
     'isAdmin',
     'isMember',
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/services/GroupService.js b/django_airavata/apps/api/static/django_airavata_api/js/services/GroupService.js
deleted file mode 100644
index 3a7685e..0000000
--- a/django_airavata/apps/api/static/django_airavata_api/js/services/GroupService.js
+++ /dev/null
@@ -1,63 +0,0 @@
-
-import Group from '../models/Group'
-import PaginationIterator from '../utils/PaginationIterator'
-import FetchUtils from '../utils/FetchUtils'
-
-class GroupService {
-
-    list(data={}) {
-      if (data && data.results) {
-          return Promise.resolve(new PaginationIterator(data, Group));
-      } else {
-          return fetch('/api/groups/', {
-              credentials: 'include'
-          })
-          .then(response => response.json())
-          .then(json => new PaginationIterator(json, Group));
-      }
-    }
-
-    create(group) {
-        return FetchUtils.post('/api/groups/', JSON.stringify(group))
-            .then(result => new Group(result))
-    }
-
-    update(group) {
-        return FetchUtils.put('/api/groups/' + encodeURIComponent(group.id) + '/', JSON.stringify(group))
-            .then(result => new Group(result));
-    }
-
-    get(groupId, data = null) {
-        if (data) {
-            return Promise.resolve(new Group(data));
-        } else {
-            return FetchUtils.get('/api/groups/'
-                    + encodeURIComponent(groupId) + '/')
-                .then(result => new Group(result));
-        }
-    }
-
-    delete(groupId) {
-        return FetchUtils.delete('/api/groups/'
-                                 + encodeURIComponent(groupId) + '/');
-    }
-
-    // adminIds is an array of sharing user ids, for example:
-    //   ['user1@test-domain', 'user2@test-domain']
-    addAdmins(groupId, adminIds) {
-        return FetchUtils.post('/api/groups/'
-                                 + encodeURIComponent(groupId) + '/add_admins/',
-                               JSON.stringify(adminIds));
-    }
-
-    // adminIds is an array of sharing user ids, for example:
-    //   ['user1@test-domain', 'user2@test-domain']
-    removeAdmins(groupId, adminIds) {
-        return FetchUtils.post('/api/groups/'
-                                 + encodeURIComponent(groupId) + '/remove_admins/',
-                               JSON.stringify(adminIds));
-    }
-}
-
-// Export as a singleton
-export default new GroupService();
diff --git a/django_airavata/apps/groups/static/django_airavata_groups/js/containers/GroupEditContainer.vue b/django_airavata/apps/groups/static/django_airavata_groups/js/containers/GroupEditContainer.vue
index 152a33e..66b036d 100644
--- a/django_airavata/apps/groups/static/django_airavata_groups/js/containers/GroupEditContainer.vue
+++ b/django_airavata/apps/groups/static/django_airavata_groups/js/containers/GroupEditContainer.vue
@@ -33,7 +33,7 @@ export default {
     computed: {
     },
     mounted: function () {
-        services.GroupService.get(this.groupId)
+        services.GroupService.retrieve({lookup: this.groupId})
             .then(group => this.group = group);
     },
 }
diff --git a/django_airavata/apps/groups/static/django_airavata_groups/js/containers/GroupsManageContainer.vue b/django_airavata/apps/groups/static/django_airavata_groups/js/containers/GroupsManageContainer.vue
index a5a7637..e296ccf 100755
--- a/django_airavata/apps/groups/static/django_airavata_groups/js/containers/GroupsManageContainer.vue
+++ b/django_airavata/apps/groups/static/django_airavata_groups/js/containers/GroupsManageContainer.vue
@@ -55,7 +55,7 @@ export default {
         },
     },
     beforeMount: function () {
-        services.GroupService.list(this.groupsDataOwners)
+        services.GroupService.list()
             .then(result => this.groupPaginator = result);
     },
 }
diff --git a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue
index b573eb9..5f7f205 100644
--- a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue
+++ b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue
@@ -52,8 +52,8 @@ export default {
     methods: {
         submitForm () {
             let saveOperation = (this.localGroup.id)
-                ? services.GroupService.update(this.localGroup)
-                : services.GroupService.create(this.localGroup);
+                ? services.GroupService.update({lookup: this.localGroup.id, data: this.localGroup})
+                : services.GroupService.create({data: this.localGroup});
             saveOperation
                 .then(group => {
                     this.$emit('saved', group);
diff --git a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupListItem.vue b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupListItem.vue
index 6357d9f..c8de521 100644
--- a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupListItem.vue
+++ b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupListItem.vue
@@ -58,7 +58,7 @@ export default {
     methods: {
       deleteGroup(id) {
           this.deleting = true;
-          services.GroupService.delete(id)
+          services.GroupService.delete({lookup: id})
               .then(result => {
                   this.$emit('deleteSuccess','Group Deleted Successfully!');
                   this.show = false;
diff --git a/django_airavata/static/common/js/components/ShareButton.vue b/django_airavata/static/common/js/components/ShareButton.vue
index 5231c3e..2a8f2de 100644
--- a/django_airavata/static/common/js/components/ShareButton.vue
+++ b/django_airavata/static/common/js/components/ShareButton.vue
@@ -108,7 +108,7 @@ export default {
         !this.defaultGatewayUsersGroup
       ) {
         promises.push(
-          services.ServiceFactory.service("Groups")
+          services.GroupService
             .list({ limit: -1 })
             .then(groups => {
               this.groups = groups;
@@ -188,7 +188,7 @@ export default {
           .then(users => (this.users = users));
       }
       if (!this.groups) {
-        services.ServiceFactory.service("Groups")
+        services.GroupService
           .list({ limit: -1 })
           .then(groups => {
             this.groups = groups;


[airavata-django-portal] 09/10: AIRAVATA-2711 Only owners can edit admins

Posted by ma...@apache.org.
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 e6d9344fd9f963ce55ab635bc9c6acbfb1204d8f
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Thu Nov 15 11:07:15 2018 -0500

    AIRAVATA-2711 Only owners can edit admins
---
 .../js/group_components/GroupEditor.vue            |  4 +--
 .../js/group_components/GroupMembersEditor.vue     | 34 +++++++++++++++-------
 2 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue
index 0e28ded..3685df5 100644
--- a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue
+++ b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue
@@ -17,8 +17,8 @@
       </b-form-group>
 
       <b-card title="Group Members" title-tag="h5">
-        <group-members-editor :members="localGroup.members" :admins="localGroup.admins" @add-member="addGroupMember"
-          @remove-member="removeGroupMember" @change-role-to-member="changeRoleToMember" @change-role-to-admin="changeRoleToAdmin" />
+        <group-members-editor :group="localGroup" @add-member="addGroupMember" @remove-member="removeGroupMember"
+          @change-role-to-member="changeRoleToMember" @change-role-to-admin="changeRoleToAdmin" />
       </b-card>
 
       <b-button @click="submitForm" variant="primary">Submit</b-button>
diff --git a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupMembersEditor.vue b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupMembersEditor.vue
index 5e8e1e5..6c9ac66 100644
--- a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupMembersEditor.vue
+++ b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupMembersEditor.vue
@@ -5,12 +5,21 @@
         placeholder="Search for users to add to this group" />
     </b-form-group>
     <b-table v-if="membersCount > 0" hover :items="currentMembers" :fields="fields" sort-by="name">
+      <template slot="HEAD_role" slot-scope="data">
+        <div class="d-flex">
+          <div>Role</div>
+          <div class="ml-auto mr-2">
+            <i class="fa fa-info-circle text-info align-text-top" v-b-tooltip.hover title="Admins can add and remove group members." />
+          </div>
+        </div>
+      </template>
       <template slot="role" slot-scope="data">
-        <b-form-select :value="data.item.role" @input="changeRole(data.item, $event)" :options="groupRoleOptions">
+        <b-form-select v-if="group.isOwner" :value="data.item.role" @input="changeRole(data.item, $event)" :options="groupRoleOptions">
         </b-form-select>
+        <span v-else>{{ data.value }}</span>
       </template>
       <template slot="remove" slot-scope="data">
-        <b-link @click="removeMember(data.item)">
+        <b-link v-if="data.item.editable" @click="removeMember(data.item)">
           <span class="fa fa-trash"></span>
         </b-link>
       </template>
@@ -19,7 +28,7 @@
 </template>
 
 <script>
-import { services } from "django-airavata-api";
+import { models, services } from "django-airavata-api";
 import { components } from "django-airavata-common-ui";
 
 export default {
@@ -28,12 +37,8 @@ export default {
     "autocomplete-text-input": components.AutocompleteTextInput
   },
   props: {
-    members: {
-      type: Array,
-      required: true
-    },
-    admins: {
-      type: Array,
+    group: {
+      type: models.Group,
       required: true
     }
   },
@@ -43,6 +48,12 @@ export default {
     };
   },
   computed: {
+    members() {
+      return this.group.members;
+    },
+    admins() {
+      return this.group.admins;
+    },
     suggestions() {
       if (!this.userProfiles) {
         return [];
@@ -87,12 +98,15 @@ export default {
       return this.members.map(m => {
         const userProfile = this.userProfilesMap[m];
         const isAdmin = this.admins.indexOf(m) >= 0;
+        // Owners can edit all members and admins can edit non-admin members
+        const editable = this.group.isOwner || (this.group.isAdmin && !isAdmin);
         return {
           id: m,
           name: userProfile.firstName + " " + userProfile.lastName,
           username: userProfile.userId,
           email: userProfile.email,
-          role: isAdmin ? "ADMIN" : "MEMBER"
+          role: isAdmin ? "ADMIN" : "MEMBER",
+          editable: editable
         };
       });
     },


[airavata-django-portal] 07/10: AIRAVATA-2711 Change role of group members

Posted by ma...@apache.org.
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 b6f870f1b1bf9ec8898b09393b2b2e76a5028ad2
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Thu Nov 15 09:00:19 2018 -0500

    AIRAVATA-2711 Change role of group members
---
 .../js/group_components/GroupEditor.vue            | 17 +++++++++++---
 .../js/group_components/GroupMembersEditor.vue     | 27 ++++++++++++++++++++--
 2 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue
index cb08f20..9305101 100644
--- a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue
+++ b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupEditor.vue
@@ -16,8 +16,8 @@
         </b-form-textarea>
       </b-form-group>
 
-      <group-members-editor :members="localGroup.members" :admins="localGroup.admins"
-        @add-member="addGroupMember" @remove-member="removeGroupMember" />
+      <group-members-editor :members="localGroup.members" :admins="localGroup.admins" @add-member="addGroupMember"
+        @remove-member="removeGroupMember" @change-role-to-member="changeRoleToMember" @change-role-to-admin="changeRoleToAdmin" />
 
       <b-button @click="submitForm" variant="primary">Submit</b-button>
     </b-form>
@@ -28,7 +28,6 @@
 import { models, services } from "django-airavata-api";
 import GroupMembersEditor from "./GroupMembersEditor.vue";
 
-
 export default {
   props: {
     group: {
@@ -74,10 +73,22 @@ export default {
     removeGroupMember(airavataInternalUserId) {
       const index = this.localGroup.members.indexOf(airavataInternalUserId);
       this.localGroup.members.splice(index, 1);
+      this.removeAdminMember(airavataInternalUserId);
+    },
+    removeAdminMember(airavataInternalUserId) {
       const adminIndex = this.localGroup.admins.indexOf(airavataInternalUserId);
       if (adminIndex >= 0) {
         this.localGroup.admins.splice(adminIndex, 1);
       }
+    },
+    changeRoleToMember(airavataInternalUserId) {
+      this.removeAdminMember(airavataInternalUserId);
+    },
+    changeRoleToAdmin(airavataInternalUserId) {
+      const adminIndex = this.localGroup.admins.indexOf(airavataInternalUserId);
+      if (adminIndex < 0) {
+        this.localGroup.admins.push(airavataInternalUserId);
+      }
     }
   }
 };
diff --git a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupMembersEditor.vue b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupMembersEditor.vue
index 6582645..d20c6d4 100644
--- a/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupMembersEditor.vue
+++ b/django_airavata/apps/groups/static/django_airavata_groups/js/group_components/GroupMembersEditor.vue
@@ -4,6 +4,10 @@
       <autocomplete-text-input id="user-autocomplete" :suggestions="suggestions" @selected="suggestionSelected" />
     </b-form-group>
     <b-table v-if="membersCount > 0" hover :items="currentMembers" :fields="fields">
+      <template slot="role" slot-scope="data">
+        <b-form-select :value="data.item.role" @input="changeRole(data.item, $event)" :options="groupRoleOptions">
+        </b-form-select>
+      </template>
       <template slot="remove" slot-scope="data">
         <b-link @click="removeMember(data.item)">
           <span class="fa fa-trash"></span>
@@ -93,6 +97,18 @@ export default {
     },
     membersCount() {
       return this.members.length;
+    },
+    groupRoleOptions() {
+      return [
+        {
+          value: "MEMBER",
+          text: "MEMBER"
+        },
+        {
+          value: "ADMIN",
+          text: "ADMIN"
+        }
+      ];
     }
   },
   created() {
@@ -102,10 +118,17 @@ export default {
   },
   methods: {
     suggestionSelected(suggestion) {
-      this.$emit('add-member', suggestion.id);
+      this.$emit("add-member", suggestion.id);
     },
     removeMember(item) {
-      this.$emit('remove-member', item.id);
+      this.$emit("remove-member", item.id);
+    },
+    changeRole(item, role) {
+      if (role === "ADMIN") {
+        this.$emit("change-role-to-admin", item.id);
+      } else {
+        this.$emit("change-role-to-member", item.id);
+      }
     }
   }
 };


[airavata-django-portal] 05/10: AIRAVATA-2711 Convert Autocomplete to VModelMixin

Posted by ma...@apache.org.
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 fe389d06a13c97c508872af62b38084621530900
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Wed Nov 14 11:57:17 2018 -0500

    AIRAVATA-2711 Convert Autocomplete to VModelMixin
---
 .../static/common/js/components/Autocomplete.vue   | 73 ++++++++++------------
 1 file changed, 32 insertions(+), 41 deletions(-)

diff --git a/django_airavata/static/common/js/components/Autocomplete.vue b/django_airavata/static/common/js/components/Autocomplete.vue
index 8497ac7..8648177 100644
--- a/django_airavata/static/common/js/components/Autocomplete.vue
+++ b/django_airavata/static/common/js/components/Autocomplete.vue
@@ -1,25 +1,25 @@
 <template>
-    <div style="position:relative">
-        <span class="selected-cards" style="position:relative">
-          <b-button variant="warning" v-for="item in selected" v-bind:key="item.id" @click="removeClick(item)">
-             {{ item.name }} <b-badge variant="light"><a href="#">x</a></b-badge>
-          </b-button>
-        </span>
-        <hr>
-        <autocomplete-text-input :suggestions="suggestions" @selected="suggestionSelected"/>
-    </div>
+  <div style="position:relative">
+    <span class="selected-cards" style="position:relative">
+      <b-button variant="warning" v-for="item in selected" v-bind:key="item.id" @click="removeClick(item)">
+        {{ item.name }} <b-badge variant="light"><a href="#">x</a></b-badge>
+      </b-button>
+    </span>
+    <hr>
+    <autocomplete-text-input :suggestions="suggestions" @selected="suggestionSelected" />
+  </div>
 </template>
 
 <script>
-import AutocompleteTextInput from './AutocompleteTextInput.vue'
+import AutocompleteTextInput from "./AutocompleteTextInput.vue";
+import VModelMixin from "../mixins/VModelMixin";
 
 export default {
-
-  name: 'autocomplete',
+  name: "autocomplete",
+  mixins: [VModelMixin],
   props: {
     value: {
-      type: Array,
-      required: false,
+      type: Array
     },
 
     suggestions: {
@@ -27,44 +27,35 @@ export default {
       required: true
     }
   },
-  data () {
-    return {
-      localValue: this.value ? this.value.slice() : [],
-    }
-  },
   components: {
-      AutocompleteTextInput,
+    AutocompleteTextInput
   },
   computed: {
-    selected () {
-        return this.suggestions.filter((suggestion) => {
-            return this.localValue.indexOf(suggestion.id) >= 0;
-        });
+    selected() {
+      return this.suggestions.filter(suggestion => {
+        return this.data.indexOf(suggestion.id) >= 0;
+      });
     }
   },
   methods: {
-    suggestionSelected (suggestion) {
-      if(this.localValue.indexOf(suggestion.id)==-1) {
-        this.localValue.push(suggestion.id);
+    suggestionSelected(suggestion) {
+      if (this.data.indexOf(suggestion.id) == -1) {
+        this.data.push(suggestion.id);
       }
-      this.$emit('input',this.localValue);
     },
     removeClick(data) {
-      var index = this.localValue.indexOf(data.id);
-      this.localValue.splice(index,1);
-      this.$emit('input',this.localValue);
-    }
-  },
-    watch:{
-      value:function (newValue) {
-          this.localValue=newValue;
-      }
+      var index = this.data.indexOf(data.id);
+      this.data.splice(index, 1);
     }
-}
-
+  }
+};
 </script>
 <style>
-.selected-cards > button + button {
-    margin-left: 10px;
+.selected-cards > button {
+  margin-bottom: 10px;
+  margin-right: 10px;
+}
+.selected-cards > button:last-child {
+  margin-right: 0px;
 }
 </style>


[airavata-django-portal] 02/10: AIRAVATA-2711 REST API to update group admins

Posted by ma...@apache.org.
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 f39ed7fcd6b8c779cb7b35d0caf3a880d4c50f42
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Wed Nov 7 11:11:11 2018 -0500

    AIRAVATA-2711 REST API to update group admins
---
 django_airavata/apps/api/serializers.py | 36 +++++++++++++++++++++++----------
 django_airavata/apps/api/views.py       | 22 ++++++--------------
 2 files changed, 31 insertions(+), 27 deletions(-)

diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
index 73d5e25..82499fc 100644
--- a/django_airavata/apps/api/serializers.py
+++ b/django_airavata/apps/api/serializers.py
@@ -138,17 +138,11 @@ class OrderedListField(serializers.ListField):
         return validated_data
 
 
-class GroupSerializer(serializers.Serializer):
+class GroupSerializer(thrift_utils.create_serializer_class(GroupModel)):
     url = FullyEncodedHyperlinkedIdentityField(
         view_name='django_airavata_api:group-detail',
         lookup_field='id',
         lookup_url_kwarg='group_id')
-    id = serializers.CharField(
-        default=GroupModel.thrift_spec[1][4], allow_null=True)
-    name = serializers.CharField(required=True)
-    description = serializers.CharField(allow_null=True, allow_blank=True)
-    ownerId = serializers.CharField(read_only=True)
-    members = serializers.ListSerializer(child=serializers.CharField())
     isAdmin = serializers.SerializerMethodField()
     isOwner = serializers.SerializerMethodField()
     isMember = serializers.SerializerMethodField()
@@ -156,10 +150,15 @@ class GroupSerializer(serializers.Serializer):
     isReadOnlyGatewayAdminsGroup = serializers.SerializerMethodField()
     isDefaultGatewayUsersGroup = serializers.SerializerMethodField()
 
+    class Meta:
+        required = ('name',)
+        read_only = ('id', 'ownerId')
+
     def create(self, validated_data):
-        validated_data['ownerId'] = self.context['request'].user.username + \
+        group = super().create(validated_data)
+        group.ownerId = self.context['request'].user.username + \
             "@" + settings.GATEWAY_ID
-        return GroupModel(**validated_data)
+        return group
 
     def update(self, instance, validated_data):
         instance.name = validated_data.get('name', instance.name)
@@ -173,16 +172,31 @@ class GroupSerializer(serializers.Serializer):
         instance._removed_members = list(removed_members)
         instance._added_members = list(added_members)
         instance.members = validated_data.get('members', instance.members)
+        # Calculate added and removed admins
+        old_admins = set(instance.admins)
+        new_admins = set(validated_data.get('admins', instance.admins))
+        removed_admins = old_admins - new_admins
+        added_admins = new_admins - old_admins
+        instance._removed_admins = list(removed_admins)
+        instance._added_admins = list(added_admins)
+        instance.admins = validated_data.get('admins', instance.admins)
+        # Add new admins that aren't members to the added_members list
+        instance._added_members.extend(list(added_admins - new_members))
+        instance.members.extend(list(added_admins - new_members))
         return instance
 
     def get_isAdmin(self, group):
         request = self.context['request']
         return request.profile_service['group_manager'].hasAdminAccess(
-            request.authz_token, group.id, request.user.username + "@" + settings.GATEWAY_ID)
+            request.authz_token,
+            group.id,
+            request.user.username + "@" + settings.GATEWAY_ID)
 
     def get_isOwner(self, group):
         request = self.context['request']
-        return group.ownerId == request.user.username + "@" + settings.GATEWAY_ID
+        return group.ownerId == (request.user.username +
+                                 "@" +
+                                 settings.GATEWAY_ID)
 
     def get_isMember(self, group):
         request = self.context['request']
diff --git a/django_airavata/apps/api/views.py b/django_airavata/apps/api/views.py
index 4569d55..88fd2f2 100644
--- a/django_airavata/apps/api/views.py
+++ b/django_airavata/apps/api/views.py
@@ -79,6 +79,12 @@ class GroupViewSet(APIBackedViewSet):
         if len(group._removed_members) > 0:
             group_manager_client.removeUsersFromGroup(
                 self.authz_token, group._removed_members, group.id)
+        if len(group._added_admins) > 0:
+            group_manager_client.addGroupAdmins(
+                self.authz_token, group.id, group._added_admins)
+        if len(group._removed_admins) > 0:
+            group_manager_client.removeGroupAdmins(
+                self.authz_token, group.id, group._removed_admins)
         group_manager_client.updateGroup(self.authz_token, group)
 
     def perform_destroy(self, group):
@@ -86,22 +92,6 @@ class GroupViewSet(APIBackedViewSet):
         group_manager_client.deleteGroup(
             self.authz_token, group.id, group.ownerId)
 
-    @detail_route(methods=['post'])
-    def add_admins(self, request, group_id=None):
-        admin_ids = request.data
-        group_manager_client = self.request.profile_service['group_manager']
-        result = group_manager_client.addGroupAdmins(
-            self.authz_token, group_id, admin_ids)
-        return Response({'success': result})
-
-    @detail_route(methods=['post'])
-    def remove_admins(self, request, group_id=None):
-        admin_ids = request.data
-        group_manager_client = self.request.profile_service['group_manager']
-        result = group_manager_client.removeGroupAdmins(
-            self.authz_token, group_id, admin_ids)
-        return Response({'success': result})
-
 
 class ProjectViewSet(APIBackedViewSet):
     serializer_class = serializers.ProjectSerializer


[airavata-django-portal] 04/10: AIRAVATA-2711 Raise AutocompleteTextInput above form-controls

Posted by ma...@apache.org.
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 173edb78655d18b59a0ed636613e69204118de2c
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Wed Nov 14 11:56:41 2018 -0500

    AIRAVATA-2711 Raise AutocompleteTextInput above form-controls
---
 django_airavata/static/common/js/components/AutocompleteTextInput.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/django_airavata/static/common/js/components/AutocompleteTextInput.vue b/django_airavata/static/common/js/components/AutocompleteTextInput.vue
index 6caf16b..709c640 100644
--- a/django_airavata/static/common/js/components/AutocompleteTextInput.vue
+++ b/django_airavata/static/common/js/components/AutocompleteTextInput.vue
@@ -93,6 +93,6 @@ export default {
 .autocomplete-suggestion-list {
   width: 100%;
   position: absolute;
-  z-index: 1;
+  z-index: 3;
 }
 </style>