airavata-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From machris...@apache.org
Subject [airavata-django-portal] 04/07: AIRAVATA-2835 Merging and saving SharedEntity after creating new entity
Date Fri, 13 Jul 2018 00:18: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

commit 1622a22addf3c41f4d21fbd2d7e9c9a748b534e5
Author: Marcus Christie <machrist@iu.edu>
AuthorDate: Thu Jul 12 12:27:34 2018 -0400

    AIRAVATA-2835 Merging and saving SharedEntity after creating new entity
---
 .../GroupComputeResourcePreference.vue             |  6 ++--
 django_airavata/apps/api/serializers.py            | 14 +++++++-
 .../django_airavata_api/js/models/SharedEntity.js  | 34 ++++++++++++++++--
 .../static/common/js/components/ShareButton.vue    | 41 ++++++++++++++++------
 4 files changed, 80 insertions(+), 15 deletions(-)

diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/GroupComputeResourcePreference.vue
b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/GroupComputeResourcePreference.vue
index 235f8b7..eb3b2ad 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/GroupComputeResourcePreference.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/GroupComputeResourcePreference.vue
@@ -8,7 +8,7 @@
           <input type="text" v-model="data.groupResourceProfileName"/>
         </div>
         <div class="entry">
-          <share-button v-if="sharedEntity" v-model="sharedEntity"/>
+          <share-button ref="shareButton" v-model="sharedEntity"/>
         </div>
       </div>
       <div class="new-application-tab-main">
@@ -201,6 +201,8 @@
             if (data) {
               this.data = this.transformData(data);
             }
+            // Save sharing settings too
+            return this.$refs.shareButton.mergeAndSave(data.groupResourceProfileId);
           });
         }
       },
@@ -220,7 +222,7 @@
     },
     watch: {
       'data.groupResourceProfileId': function (newValue) {
-        let computePreferences = groupResourceProfile.computePreferences;
+        let computePreferences = this.data.computePreferences;
         for (let computePreference of computePreferences) {
           computePreference.groupResourceProfileId = newValue;
           for (let groupSSHAccountProvisionerConfig of computePreference.groupSSHAccountProvisionerConfigs)
{
diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
index e361273..e5f2987 100644
--- a/django_airavata/apps/api/serializers.py
+++ b/django_airavata/apps/api/serializers.py
@@ -38,7 +38,10 @@ log = logging.getLogger(__name__)
 
 class FullyEncodedHyperlinkedIdentityField(serializers.HyperlinkedIdentityField):
     def get_url(self, obj, view_name, request, format):
-        lookup_value = getattr(obj, self.lookup_field)
+        if hasattr(obj, self.lookup_field):
+            lookup_value = getattr(obj, self.lookup_field)
+        else:
+            lookup_value = obj.get(self.lookup_field)
         encoded_lookup_value = quote(lookup_value, safe="")
         # Bit of a hack. Django's URL reversing does URL encoding but it doesn't
         # encode all characters including some like '/' that are used in URL
@@ -512,6 +515,15 @@ class SharedEntitySerializer(serializers.Serializer):
         instance['_group_grant_write_permission'] = group_grant_write_permission
         instance['_group_revoke_read_permission'] = group_revoke_read_permission
         instance['_group_revoke_write_permission'] = group_revoke_write_permission
+        instance['userPermissions'] = [
+            {'user': UserProfile(**data['user']),
+             'permissionType': data['permissionType']}
+            for data in validated_data.get(
+                'userPermissions', instance['userPermissions'])]
+        instance['groupPermissions'] = [
+            {'group': GroupModel(**data['group']),
+             'permissionType': data['permissionType']}
+            for data in validated_data.get('groupPermissions', instance['groupPermissions'])]
         return instance
 
     def _compute_all_revokes_and_grants(self, existing_permissions,
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/SharedEntity.js
b/django_airavata/apps/api/static/django_airavata_api/js/models/SharedEntity.js
index 41e4d19..9f3b618 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/SharedEntity.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/SharedEntity.js
@@ -9,12 +9,14 @@ const FIELDS = [
     {
         name: 'userPermissions',
         type: UserPermission,
-        list: true
+        list: true,
+        default: BaseModel.defaultNewInstance(Array),
     },
     {
         name: 'groupPermissions',
         type: GroupPermission,
-        list: true
+        list: true,
+        default: BaseModel.defaultNewInstance(Array),
     },
     {
         name: 'owner',
@@ -27,4 +29,32 @@ export default class SharedEntity extends BaseModel {
     constructor(data = {}) {
         super(FIELDS, data);
     }
+
+    /**
+     * Merge given sharedEntity with `this`, where the given sharedEntity takes
+     * precedence.
+     */
+    merge(sharedEntity) {
+        if (sharedEntity.entityId) {
+            this.entityId = sharedEntity.entityId;
+        }
+        if (sharedEntity.owner) {
+            this.owner = sharedEntity.owner;
+            this.isOwner = sharedEntity.isOwner;
+        }
+        // Allow userPermissions entries in sharedEntity to override this userPermissions
+        let newUserPermissions = [].concat(this.userPermissions, sharedEntity.userPermissions);
+        let newUserPermissionsMap = newUserPermissions.reduce((map, userPerm) => {
+            map[userPerm.user.airavataInternalUserId] = userPerm;
+            return map;
+        }, {});
+        this.userPermissions = Object.values(newUserPermissionsMap);
+        // Same deal for groupPermissions
+        let newGroupPermissions = [].concat(this.groupPermissions, sharedEntity.groupPermissions);
+        let newGroupPermissionsMap = newGroupPermissions.reduce((map, groupPerm) => {
+            map[groupPerm.group.id] = groupPerm;
+            return map;
+        }, {});
+        this.groupPermissions = Object.values(newGroupPermissionsMap);
+    }
 }
diff --git a/django_airavata/static/common/js/components/ShareButton.vue b/django_airavata/static/common/js/components/ShareButton.vue
index 08dc3bd..b92d2d2 100644
--- a/django_airavata/static/common/js/components/ShareButton.vue
+++ b/django_airavata/static/common/js/components/ShareButton.vue
@@ -97,20 +97,20 @@ export default {
                 + (this.usersCount > 0 ? " (" + this.userNames.join(", ") + ")" : "");
         },
         usersCount: function() {
-            return this.sharedEntity ? this.sharedEntity.userPermissions.length : 0;
+            return this.sharedEntity && this.sharedEntity.userPermissions ? this.sharedEntity.userPermissions.length
: 0;
         },
         userNames: function() {
-            return this.sharedEntity
+            return this.sharedEntity && this.sharedEntity.userPermissions
                 ? this.sharedEntity.userPermissions.map(userPerm => userPerm.user.firstName
+ " " + userPerm.user.lastName)
                 : null;
         },
         groupNames: function() {
-            return this.sharedEntity
+            return this.sharedEntity && this.sharedEntity.groupPermissions
                 ? this.sharedEntity.groupPermissions.map(groupPerm => groupPerm.group.name)
                 : null;
         },
         groupsCount: function() {
-            return this.sharedEntity ? this.sharedEntity.groupPermissions.length: 0;
+            return this.sharedEntity && this.sharedEntity.groupPermissions ? this.sharedEntity.groupPermissions.length:
0;
         },
         totalCount: function() {
             return this.usersCount + this.groupsCount;
@@ -126,7 +126,7 @@ export default {
         },
         groupSuggestions: function() {
             // filter out already selected groups
-            const currentGroupIds = this.sharedEntity.groupPermissions.map(groupPerm =>
groupPerm.group.id);
+            const currentGroupIds = this.sharedEntity.groupPermissions ? this.sharedEntity.groupPermissions.map(groupPerm
=> groupPerm.group.id) : [];
             return this.groups
                 .filter(group => currentGroupIds.indexOf(group.id) < 0)
                 .map(group => {
@@ -139,7 +139,7 @@ export default {
         },
         userSuggestions: function() {
             // filter out already selected users
-            const currentUserIds = this.sharedEntity.userPermissions.map(userPerm => userPerm.user.airavataInternalUserId);
+            const currentUserIds = this.sharedEntity.userPermissions ? this.sharedEntity.userPermissions.map(userPerm
=> userPerm.user.airavataInternalUserId) : [];
             return this.users
                 .filter(user => currentUserIds.indexOf(user.airavataInternalUserId) <
0)
                 .map(user => {
@@ -157,11 +157,19 @@ export default {
     },
     methods: {
         /**
-         * Merge the given persisted SharedEntity with the local SharedEntity
+         * Merge the persisted SharedEntity with the local SharedEntity
          * instance and save it, returning a Promise.
          */
-        merge: function(sharedEntity) {
-            // TODO: implement this
+        mergeAndSave: function(entityId) {
+            return services.ServiceFactory.service("SharedEntities").retrieve({lookup: entityId})
+                .then(persistedSharedEntity => {
+                    // Copy the local sharedEntity instance onto the
+                    // persistedSharedEntity and update it
+                    persistedSharedEntity.merge(this.sharedEntity);
+                    return services.ServiceFactory.service("SharedEntities")
+                        .update({'data': persistedSharedEntity, 'lookup': persistedSharedEntity.entityId})
+                        .then(sharedEntity => this.sharedEntity = sharedEntity);
+                });
         },
         removeUser: function(user) {
             this.sharedEntity.userPermissions = this.sharedEntity.userPermissions.filter(
@@ -174,12 +182,18 @@ export default {
         suggestionSelected: function(suggestion) {
             if (suggestion.type === 'group') {
                 const group = this.groups.find(group => group.id === suggestion.id);
+                if (!this.sharedEntity.groupPermissions) {
+                    this.sharedEntity.groupPermissions = [];
+                }
                 this.sharedEntity.groupPermissions.push(new models.GroupPermission({
                     'group': group,
                     'permissionType': models.ResourcePermissionType.READ
                 }));
             } else if (suggestion.type === 'user') {
                 const user = this.users.find(user => user.airavataInternalUserId === suggestion.id);
+                if (!this.sharedEntity.userPermissions) {
+                    this.sharedEntity.userPermissions = [];
+                }
                 this.sharedEntity.userPermissions.push(new models.UserPermission({
                     'user': user,
                     'permissionType': models.ResourcePermissionType.READ
@@ -187,6 +201,12 @@ export default {
             }
         },
         saveSharedEntity: function(event) {
+            // If entity hasn't been persisted yet then just emitValueChanged.
+            // Sharing settings will need to be saved later (see mergeAndSave).
+            if (!this.sharedEntity.entityId) {
+                this.emitValueChanged();
+                return;
+            }
             // Prevent hiding the modal, hide it programmatically
             this.errorMessage = null;
             this.loading = true;
@@ -212,7 +232,7 @@ export default {
         },
         cloneSharedEntity: function(sharedEntity) {
             return sharedEntity ? sharedEntity.clone() : new models.SharedEntity();
-        }
+        },
     },
     mounted: function() {
         // Load all of the groups and users
@@ -233,6 +253,7 @@ button {
 }
 #share-button >>> #modal-share-settings .modal-body {
     max-height: 50vh;
+    min-height: 300px;
     overflow: auto;
 }
 </style>
\ No newline at end of file


Mime
View raw message