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 a3037536fbec1611c56daa8404e53a0b689176d3 Author: Marcus Christie <[email protected]> AuthorDate: Fri May 3 15:27:54 2019 -0400 AIRAVATA-3030 Display inherited parent permissions, parent entity owner --- .../js/components/experiment/ExperimentEditor.vue | 3 + .../static/common/js/components/ShareButton.vue | 85 ++++++++++++++++++++-- .../common/js/components/SharedEntityEditor.vue | 55 ++++++++++++-- 3 files changed, 129 insertions(+), 14 deletions(-) diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue index 773b9c8..16193c1 100644 --- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue +++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue @@ -18,6 +18,9 @@ <share-button ref="shareButton" :entity-id="localExperiment.experimentId" + :entity-label="'Experiment'" + :parent-entity-id="localExperiment.projectId" + :parent-entity-label="'Project'" :auto-add-default-gateway-users-group="false" /> </div> diff --git a/django_airavata/static/common/js/components/ShareButton.vue b/django_airavata/static/common/js/components/ShareButton.vue index 4e947b0..f9eb6f9 100644 --- a/django_airavata/static/common/js/components/ShareButton.vue +++ b/django_airavata/static/common/js/components/ShareButton.vue @@ -1,13 +1,52 @@ <template> <div class="share-button btn-container"> - <b-button :variant="'outline-primary'" :title="title" :disabled="!shareButtonEnabled" @click="openSharingSettingsModal"> + <b-button + :variant="'outline-primary'" + :title="title" + :disabled="!shareButtonEnabled" + @click="openSharingSettingsModal" + > Share <b-badge>{{ totalCount }}</b-badge> </b-button> - <b-modal class="modal-share-settings" title="Sharing Settings" ref="sharingSettingsModal" ok-title="Save" @ok="saveSharedEntity" - @cancel="cancelEditSharedEntity" no-close-on-esc no-close-on-backdrop hide-header-close @show="showSharingSettingsModal"> - <shared-entity-editor v-if="localSharedEntity && users && groups" v-model="localSharedEntity" :users="users" - :groups="groups" :disallow-editing-admin-groups="disallowEditingAdminGroups" /> + <b-modal + class="modal-share-settings" + title="Sharing Settings" + ref="sharingSettingsModal" + ok-title="Save" + @ok="saveSharedEntity" + @cancel="cancelEditSharedEntity" + no-close-on-esc + no-close-on-backdrop + hide-header-close + @show="showSharingSettingsModal" + > + <shared-entity-editor + v-if="localSharedEntity && users && groups" + v-model="localSharedEntity" + :users="users" + :groups="groups" + :parent-entity-owner="parentEntityOwner" + :parent-entity-label="parentEntityLabel" + :disallow-editing-admin-groups="disallowEditingAdminGroups" + /> + <!-- Only show parent entity permissions for new entities --> + <template v-if="!entityId && hasParentSharedEntityPermissions"> + <shared-entity-editor + v-if="parentSharedEntity && users && groups" + v-model="parentSharedEntity" + :users="users" + :groups="groups" + :readonly="true" + class="mt-5" + > + <span slot="permissions-header">Inherited {{ parentEntityLabel }} Permissions</span> + </shared-entity-editor> + <small class="text-muted">These permissions are inherited when your <span class="text-lowercase">{{ entityLabel + }}</span> is initially + created but can be updated + afterwards.</small> + </template> </b-modal> </div> </template> @@ -20,6 +59,15 @@ export default { name: "share-button", props: { entityId: String, + parentEntityId: String, + parentEntityLabel: { + type: String, + default: "Parent" + }, + entityLabel: { + type: String, + default: "Entity" + }, sharedEntity: models.SharedEntity, autoAddDefaultGatewayUsersGroup: { type: Boolean, @@ -36,6 +84,7 @@ export default { data: function() { return { localSharedEntity: null, + parentSharedEntity: null, sharedEntityCopy: null, defaultGatewayUsersGroup: null, users: null, @@ -69,7 +118,9 @@ export default { }, filteredGroupPermissions: function() { if (this.localSharedEntity && this.localSharedEntity.groupPermissions) { - return this.disallowEditingAdminGroups ? this.localSharedEntity.nonAdminGroupPermissions : this.localSharedEntity.groupPermissions; + return this.disallowEditingAdminGroups + ? this.localSharedEntity.nonAdminGroupPermissions + : this.localSharedEntity.groupPermissions; } else { return []; } @@ -91,6 +142,16 @@ export default { this.localSharedEntity && (!this.localSharedEntity.entityId || this.localSharedEntity.isOwner) ); + }, + hasParentSharedEntityPermissions() { + return ( + this.parentSharedEntity && + (this.parentSharedEntity.userPermissions.length > 0 || + this.parentSharedEntity.groupPermissions.length > 0) + ); + }, + parentEntityOwner() { + return this.parentSharedEntity && this.parentSharedEntity.owner; } }, methods: { @@ -123,6 +184,13 @@ export default { }) ); } + if (this.parentEntityId) { + promises.push( + this.loadSharedEntity(this.parentEntityId).then( + sharedEntity => (this.parentSharedEntity = sharedEntity) + ) + ); + } Promise.all(promises).then(() => { if (this.sharedEntity) { this.localSharedEntity = this.sharedEntity.clone(); @@ -216,6 +284,11 @@ export default { sharedEntity => (this.localSharedEntity = sharedEntity) ); } + }, + parentEntityId(newParentEntityId) { + this.loadSharedEntity(newParentEntityId).then(sharedEntity => { + this.parentSharedEntity = sharedEntity; + }); } } }; diff --git a/django_airavata/static/common/js/components/SharedEntityEditor.vue b/django_airavata/static/common/js/components/SharedEntityEditor.vue index dcba2c7..be778ff 100644 --- a/django_airavata/static/common/js/components/SharedEntityEditor.vue +++ b/django_airavata/static/common/js/components/SharedEntityEditor.vue @@ -1,6 +1,7 @@ <template> <div> <b-form-group + v-if="!readonly" label="Search for users/groups" labelFor="user-groups-autocomplete" > @@ -24,40 +25,48 @@ </template> </autocomplete-text-input> </b-form-group> - <h5 v-if="totalCount > 0">Currently Shared With</h5> + <h5 v-if="totalCount > 0"> + <slot name="permissions-header">Currently Shared With</slot> + </h5> <b-table v-if="usersCount > 0" id="modal-user-table" hover - :items="sortedUserPermissions" + :items="sortedUserPermissionsData" :fields="userFields" > <template slot="name" slot-scope="data" > - <span :title="data.item.user.userId">{{data.item.user.firstName}} {{data.item.user.lastName}}</span> + <span :title="data.item.user.userId" :class="data.item.classes">{{data.item.user.firstName}} {{data.item.user.lastName}}</span> </template> <template slot="email" slot-scope="data" > - {{data.item.user.email}} + <span :class="data.item.classes">{{data.item.user.email}}</span> </template> <template slot="permission" slot-scope="data" > <b-form-select + v-if="!data.item.readonly" v-model="data.item.permissionType" :options="permissionOptions" /> + <span + v-else + class="text-uppercase" + :class="data.item.classes" + >{{ data.item.permissionTypeLabel }}</span> </template> <template slot="remove" slot-scope="data" > - <b-link @click="removeUser(data.item.user)"> + <b-link v-if="!data.item.readonly" @click="removeUser(data.item.user)"> <span class="fa fa-trash"></span> </b-link> </template> @@ -131,6 +140,17 @@ export default { disallowEditingAdminGroups: { type: Boolean, default: true + }, + readonly: { + type: Boolean, + default: false + }, + parentEntityOwner: { + type: models.UserProfile, + }, + parentEntityLabel: { + type: String, + default: "Parent" } }, components: { @@ -157,14 +177,33 @@ export default { ? this.data.userPermissions.length : 0; }, - sortedUserPermissions: function() { + sortedUserPermissionsData: function() { const userPermsCopy = this.data.userPermissions ? this.data.userPermissions.slice() : []; - return utils.StringUtils.sortIgnoreCase( + const sorted = utils.StringUtils.sortIgnoreCase( userPermsCopy, userPerm => userPerm.user.lastName + ", " + userPerm.user.firstName ); + const sortedData = sorted.map(up => { + return { + user: up.user, + permissionType: up.permissionType, + permissionTypeLabel: up.permissionType.name, + readonly: this.readonly, + classes: this.readonly ? ['text-muted', 'font-italic'] : null + } + }); + if (this.parentEntityOwner) { + sortedData.push({ + user: this.parentEntityOwner, + permissionType: models.ResourcePermissionType.OWNER, + permissionTypeLabel: this.parentEntityLabel + " OWNER", + readonly: true, + classes: ['text-muted', 'font-italic'] + }); + } + return sortedData; }, filteredGroupPermissions: function() { return this.data && this.data.groupPermissions @@ -279,7 +318,7 @@ export default { * should not be allowed. */ editingAllowed(group) { - return !this.disallowEditingAdminGroups || !group.isAdminGroup; + return !this.readonly && (!this.disallowEditingAdminGroups || !group.isAdminGroup); } } };
