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 a790c3eb1a6b659b97ab2b68d62eb02c4ec96e71 Author: Marcus Christie <machr...@iu.edu> AuthorDate: Wed Jul 11 13:09:39 2018 -0400 AIRAVATA-2835 User management in ShareButton --- .../django_airavata_api/js/models/UserProfile.js | 2 +- .../django_airavata_api/js/service_config.js | 8 +++ .../common/js/components/AutocompleteTextInput.vue | 3 +- .../static/common/js/components/ShareButton.vue | 66 ++++++++++++++++++++-- 4 files changed, 71 insertions(+), 8 deletions(-) diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/UserProfile.js b/django_airavata/apps/api/static/django_airavata_api/js/models/UserProfile.js index 3130ce7..82288a7 100644 --- a/django_airavata/apps/api/static/django_airavata_api/js/models/UserProfile.js +++ b/django_airavata/apps/api/static/django_airavata_api/js/models/UserProfile.js @@ -45,6 +45,6 @@ export default class UserProfile extends BaseModel { } get email() { - return (emails != null && emails.length > 0) ? emails[0] : null; + return (this.emails != null && this.emails.length > 0) ? this.emails[0] : null; } } diff --git a/django_airavata/apps/api/static/django_airavata_api/js/service_config.js b/django_airavata/apps/api/static/django_airavata_api/js/service_config.js index d26953a..ef77613 100644 --- a/django_airavata/apps/api/static/django_airavata_api/js/service_config.js +++ b/django_airavata/apps/api/static/django_airavata_api/js/service_config.js @@ -1,5 +1,6 @@ import Group from './models/Group' import SharedEntity from './models/SharedEntity' +import UserProfile from './models/UserProfile' const post = "post"; const get = "get"; @@ -61,4 +62,11 @@ export default { queryParams: ['limit', 'offset'], modelClass: Group, }, + "UserProfiles": { + url: "/api/user-profiles", + viewSet: [{ + name: "list" + }], + modelClass: UserProfile, + }, } \ No newline at end of file diff --git a/django_airavata/static/common/js/components/AutocompleteTextInput.vue b/django_airavata/static/common/js/components/AutocompleteTextInput.vue index ca8dd20..30ef009 100644 --- a/django_airavata/static/common/js/components/AutocompleteTextInput.vue +++ b/django_airavata/static/common/js/components/AutocompleteTextInput.vue @@ -45,7 +45,8 @@ export default { computed: { filtered () { return this.suggestions.filter((data) => { - return data.name.indexOf(this.searchValue) >= 0 + // Case insensitive search + return data.name.toLowerCase().indexOf(this.searchValue.toLowerCase()) >= 0 }) }, }, diff --git a/django_airavata/static/common/js/components/ShareButton.vue b/django_airavata/static/common/js/components/ShareButton.vue index f161cbc..fa04c15 100644 --- a/django_airavata/static/common/js/components/ShareButton.vue +++ b/django_airavata/static/common/js/components/ShareButton.vue @@ -5,19 +5,38 @@ <b-badge>{{ totalCount }}</b-badge> </b-button> <b-modal id="modal-share-settings" title="Sharing Settings"> - <b-form-group label="Search for groups" labelFor="user-groups-autocomplete"> + <b-form-group label="Search for users/groups" labelFor="user-groups-autocomplete"> <autocomplete-text-input id="user-groups-autocomplete" - :suggestions="groupSuggestions" + :suggestions="usersAndGroupsSuggestions" @selected="suggestionSelected"> <template slot="suggestion" slot-scope="slotProps"> <span v-if="slotProps.suggestion.type == 'group'"> <i class="fa fa-users"></i> {{ slotProps.suggestion.name }} </span> + <span v-if="slotProps.suggestion.type == 'user'"> + <i class="fa fa-user"></i> + {{ slotProps.suggestion.user.firstName }} {{ slotProps.suggestion.user.lastName }} + ({{ slotProps.suggestion.user.userId }}) - {{ slotProps.suggestion.user.email }} + </span> </template> </autocomplete-text-input> </b-form-group> - <h5>Currently Shared With</h5> - <b-table id="modal-group-table" hover :items="sharedEntity.groupPermissions" :fields="groupFields"> + <h5 v-if="totalCount > 0">Currently Shared With</h5> + <b-table v-if="usersCount > 0" id="modal-user-table" hover :items="sharedEntity.userPermissions" :fields="userFields"> + <template slot="name" slot-scope="data"> + <span :title="data.item.user.userId">{{data.item.user.firstName}} {{data.item.user.lastName}}</span> + </template> + <template slot="email" slot-scope="data"> + {{data.item.user.email}} + </template> + <template slot="permission" slot-scope="data"> + <b-form-select v-model="data.item.permissionType" :options="permissionOptions"/> + </template> + <template slot="remove" slot-scope="data"> + <a href="#" @click.prevent="removeUser(data.item.user)"><span class="fa fa-trash"></span></a> + </template> + </b-table> + <b-table v-if="groupsCount > 0" id="modal-group-table" hover :items="sharedEntity.groupPermissions" :fields="groupFields"> <template slot="name" slot-scope="data"> {{data.item.group.name}} </template> @@ -48,11 +67,18 @@ export default { data: function() { return { sharedEntity: this.value ? this.value.clone() : new models.SharedEntity(), + userFields: [ + {key: 'name', label: 'User Name'}, + {key: 'email', label: 'Email'}, + {key: 'permission', label: 'Permission'}, + {key: 'remove', label: 'Remove'}, + ], groupFields: [ {key: 'name', label: 'Group Name'}, - {key: 'permission', label: 'Permission Settings'}, + {key: 'permission', label: 'Permission'}, {key: 'remove', label: 'Remove'}, ], + users: [], groups: [], } }, @@ -103,6 +129,23 @@ export default { type: 'group', } }); + }, + userSuggestions: function() { + // filter out already selected users + const currentUserIds = this.sharedEntity.userPermissions.map(userPerm => userPerm.user.airavataInternalUserId); + return this.users + .filter(user => currentUserIds.indexOf(user.airavataInternalUserId) < 0) + .map(user => { + return { + id: user.airavataInternalUserId, + name: user.firstName + ' ' + user.lastName + ' (' + user.userId + ') ' + user.email, + user: user, + type: 'user', + } + }); + }, + usersAndGroupsSuggestions: function() { + return this.userSuggestions.concat(this.groupSuggestions); } }, methods: { @@ -113,6 +156,10 @@ export default { merge: function(sharedEntity) { // TODO: implement this }, + removeUser: function(user) { + this.sharedEntity.userPermissions = this.sharedEntity.userPermissions.filter( + userPermission => userPermission.user.airavataInternalUserId !== user.airavataInternalUserId); + }, removeGroup: function(group) { this.sharedEntity.groupPermissions = this.sharedEntity.groupPermissions.filter( groupPermission => groupPermission.group.id !== group.id); @@ -124,12 +171,19 @@ export default { 'group': group, 'permissionType': models.ResourcePermissionType.READ })); + } else if (suggestion.type === 'user') { + const user = this.users.find(user => user.airavataInternalUserId === suggestion.id); + this.sharedEntity.userPermissions.push(new models.UserPermission({ + 'user': user, + 'permissionType': models.ResourcePermissionType.READ + })); } } }, mounted: function() { - // Load all of the groups + // Load all of the groups and users services.ServiceFactory.service("Groups").list({limit: -1}).then(groups => this.groups = groups); + services.ServiceFactory.service("UserProfiles").list().then(users => this.users = users); } } </script>