Skip to content

Commit

Permalink
Added helper file for collaborators
Browse files Browse the repository at this point in the history
Added permissionsToRole function and restructured roles object

Fixed wrong type in jsdocs

Changed functions to interact with bitmask

Moved collaborators mixins into mixins folder and used roles helper file

Moved roles back into mixin

Move permissions bitmask to own file and introduce permissions sets for files and folders

Use custom permissions object

Split collaborators into smaller components

Move permissions bitmask back to collaborators helper file

Added object filter package and emit events from child components

Refactored default role

Added current role

Use smaller components in collaborator component

Added translations

Added docs and provide default function to return original strings

Added custom role

Implemented bitmaskToRole function

Bring bitmaskToRole into store

Fixed displaying of custom role

Fixed display of existing role

Fixed roleToBitmask function and add new collaborators method

Fixed passing of file into buildShare function

Fixed default role

Implement values of additional permissions

Add read permission to advanced role

Implemented change of collaborator

Fixed parentheses around group suffix)

Implemented requested changes

Renamed collaboratorRoles
  • Loading branch information
Lukas Hirt authored and LukasHirt committed Nov 19, 2019
1 parent 2eb63ce commit 20c88f5
Show file tree
Hide file tree
Showing 13 changed files with 567 additions and 363 deletions.
66 changes: 66 additions & 0 deletions apps/files/src/components/Collaborators/AdditionalPermissions.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<template>
<oc-grid gutter="small">
<label v-for="permission in permissions" :key="permission.name">
<oc-checkbox
class="uk-margin-xsmall-right"
v-model="permission.value"
@change="permissionChecked"
/>
{{ permission.description }}
</label>
</oc-grid>
</template>

<script>
import filterObject from 'filter-obj'
export default {
name: 'AdditionalPermissions',
props: {
/**
* Available permissions for the role
*/
availablePermissions: {
type: Object,
required: true
},
/**
* Additional permissions of the collaborator with values
*/
collaboratorsPermissions: {
type: Object,
required: false
}
},
computed: {
permissions () {
const permissions = this.availablePermissions
for (const permission in permissions) {
if (this.collaboratorsPermissions && this.collaboratorsPermissions[permission]) {
permissions[permission].value = true
continue
}
permissions[permission].value = false
}
return permissions
}
},
methods: {
permissionChecked () {
const selectedPermissions = []
const permissions = filterObject(this.permissions, (key, value) => {
return value.value === true
})
for (const permission in permissions) {
selectedPermissions.push(permission)
}
this.$emit('permissionChecked', selectedPermissions)
}
}
}
</script>
4 changes: 2 additions & 2 deletions apps/files/src/components/Collaborators/AutocompleteItem.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div class="uk-flex uk-flex-middle">
<oc-spinner v-if="loading" uk-spinner="ratio:1.6" class="uk-margin-small-right" />
<oc-spinner v-if="loading" uk-spinner="ratio:1.6" class="uk-margin-small-right" :aria-label="$gettext('Loading avatar')" />
<template v-else>
<oc-avatar v-if="avatar" :src="avatar" class="uk-margin-small-right" width=50 height=50 />
<template v-else>
Expand All @@ -20,7 +20,7 @@
</template>

<script>
import Mixins from './mixins'
import Mixins from '../../mixins/collaborators'
export default {
name: 'AutocompleteItem',
Expand Down
125 changes: 36 additions & 89 deletions apps/files/src/components/Collaborators/Collaborator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,58 +18,23 @@
({{ collaborator.info.share_with_additional_info }})
</span>
</div>
<span class="oc-text">{{ roles[collaborator.role].name }}<template v-if="collaborator.expires"> | <translate :translate-params="{expires: formDateFromNow(collaborator.expires)}">Expires: %{expires}</translate></template></span>
<span class="uk-text-meta">{{ $_ocCollaborators_collaboratorType(collaborator.info.share_type) }}</span>
<span class="oc-text">{{ originalRole.label }}<template v-if="collaborator.expires"> | <translate :translate-params="{expires: formDateFromNow(collaborator.expires)}">Expires: %{expires}</translate></template></span>
<span class="uk-text-meta" v-text="$_ocCollaborators_collaboratorType(collaborator.info.share_type)" />
</div>
</div>
</template>
<template slot="content">
<oc-grid gutter="small" class="uk-margin-bottom">
<div class="uk-width-1-1 uk-position-relative">
<label class="oc-label"><translate>Role</translate></label>
<oc-button :id="`files-collaborators-role-button-${collaborator.info.id}`" class="uk-width-1-1 files-collaborators-role-button">{{ $_ocCollaborators_selectedRoleName(collaborator) }}</oc-button>
<p class="uk-text-meta uk-margin-remove">{{ $_ocCollaborators_selectedRoleDescription(collaborator) }}</p>
<oc-drop :dropId="`files-collaborators-roles-dropdown-${collaborator.info.id}`" closeOnClick :toggle="`#files-collaborators-role-button-${collaborator.info.id}`" mode="click" :options="{ offset: 0, delayHide: 0 }" class="oc-autocomplete-dropdown">
<ul class="oc-autocomplete-suggestion-list">
<li
v-for="(role, key) in roles"
:key="key"
class="oc-autocomplete-suggestion"
:class="rolesDropItemClass(role)"
@click="$_ocCollaborators_changeRole(role); onChange()"
>
<span class="uk-text-bold">{{ role.name }}</span>
<p class="uk-text-meta uk-margin-remove">{{ role.description }}</p>
</li>
</ul>
</oc-drop>
</div>
<div v-if="false" class="uk-width-1-1">
<label class="oc-label"><translate>Expiration date</translate> <translate class="uk-text-meta uk-remove-margin">(optional)</translate></label>
<oc-text-input type="date" class="uk-width-1-1 oc-button-role">04 - 07 - 2019</oc-text-input>
</div>
<oc-grid gutter="small">
<div class="uk-flex uk-flex-row uk-flex-wrap uk-flex-middle">
<oc-switch :key="switchKey" class="uk-margin-small-right" :model="canShare" @change="$_ocCollaborators_switchPermission('canShare')" /> <translate :class="{ 'uk-text-muted': !canShare }">Can share</translate>
</div>
<template v-if="(collaborator.role === 'custom' && !selectedNewRole) || (selectedNewRole && selectedNewRole.tag === 'custom')">
<div class="uk-flex uk-flex-row uk-flex-wrap uk-flex-middle">
<oc-switch :key="switchKey" class="uk-margin-small-right" :model="canChange" @change="$_ocCollaborators_switchPermission('canChange')" /> <translate :class="{ 'uk-text-muted': !canChange }">Can change</translate>
</div>
<div v-if="highlightedFile.type === 'folder'" class="uk-flex uk-flex-row uk-flex-wrap uk-flex-middle">
<oc-switch :key="switchKey" class="uk-margin-small-right" :model="canCreate" @change="$_ocCollaborators_switchPermission('canCreate')" /> <translate :class="{ 'uk-text-muted': !canCreate }">Can create</translate>
</div>
<div v-if="highlightedFile.type === 'folder'" class="uk-flex uk-flex-row uk-flex-wrap uk-flex-middle">
<oc-switch :key="switchKey" class="uk-margin-small-right" :model="canDelete" @change="$_ocCollaborators_switchPermission('canDelete')" /> <translate :class="{ 'uk-text-muted': !canDelete }">Can delete</translate>
</div>
</template>
</oc-grid>
</oc-grid>
<collaborators-edit-options
:existingRole="collaborator.role"
:collaboratorsPermissions="collaborator.customPermissions"
@optionChange="collaboratorOptionChanged"
class="uk-margin-bottom"
/>
<template v-if="editing">
<oc-button :disabled="collaboratorSaving" @click="$_ocCollaborators_cancelChanges">
<translate>Cancel</translate>
</oc-button>
<oc-button variation="primary" :disabled="collaboratorSaving" :aria-label="_saveButtonLabel" @click="$_ocCollaborators_saveChanges(collaborator)">
<oc-button variation="primary" :disabled="collaboratorSaving" :aria-label="_saveButtonLabel" @click="saveChanges(collaborator)">
<translate>Save</translate>
</oc-button>
</template>
Expand All @@ -81,10 +46,16 @@

<script>
import { mapGetters, mapActions } from 'vuex'
import Mixins from './mixins'
import Mixins from '../../mixins/collaborators'
import { roleToBitmask } from '../../helpers/collaborators'
const CollaboratorsEditOptions = () => import('./CollaboratorsEditOptions.vue')
export default {
name: 'Collaborator',
components: {
CollaboratorsEditOptions
},
props: ['collaborator'],
mixins: [
Mixins
Expand All @@ -94,13 +65,9 @@ export default {
avatar: '',
loading: false,
editing: false,
canShare: this.collaborator.canShare,
canChange: this.collaborator.customPermissions.change,
canCreate: this.collaborator.customPermissions.create,
canDelete: this.collaborator.customPermissions.delete,
selectedNewRole: null,
permissionsChanged: false,
switchKey: Math.floor(Math.random() * 100) // Ensure switch gets back to orginal position after cancel
selectedRole: null,
additionalPermissions: null
}
},
computed: {
Expand All @@ -116,7 +83,11 @@ export default {
},
originalRole () {
return this.roles[this.collaborator.role].tag
if (this.collaborator.role.name === 'advancedRole') {
return this.advancedRole
}
return this.roles[this.collaborator.role.name]
}
},
mounted () {
Expand All @@ -130,60 +101,35 @@ export default {
client: this.$client,
share: share
})
this.editing = false
this.toggleCollaboratorsEdit(false)
},
$_ocCollaborators_saveChanges (collaborator) {
if (!this.selectedNewRole) this.selectedNewRole = this.roles[collaborator.role]
saveChanges (collaborator) {
if (!this.selectedRole) this.selectedRole = this.roles[collaborator.role.name]
this.changeShare({
client: this.$client,
share: collaborator,
canShare: this.canShare,
canChange: this.canChange,
canCreate: this.canCreate,
canDelete: this.canDelete,
role: this.selectedNewRole.tag
role: this.selectedRole,
permissions: roleToBitmask(this.selectedRole, this.additionalPermissions, this.highlightedFile.type === 'folder')
})
.then(() => {
this.editing = false
this.toggleCollaboratorsEdit(false)
this.selectedNewRole = null
})
},
$_ocCollaborators_changeRole (role) {
this.selectedNewRole = role
},
$_ocCollaborators_selectedRoleName (collaborator) {
if (!this.selectedNewRole) {
return this.roles[collaborator.role].name
}
return this.selectedNewRole.name
},
$_ocCollaborators_selectedRoleDescription (collaborator) {
if (!this.selectedNewRole) {
return this.roles[collaborator.role].description
}
return this.selectedNewRole.description
},
$_ocCollaborators_cancelChanges () {
this.selectedNewRole = null
this.canShare = this.collaborator.canShare
this.canChange = this.collaborator.customPermissions.change
this.canCreate = this.collaborator.customPermissions.create
this.canDelete = this.collaborator.customPermissions.delete
this.editing = false
this.switchKey = Math.floor(Math.random() * 100)
this.toggleCollaboratorsEdit(false)
},
onChange () {
if (this.selectedNewRole.tag === this.originalRole && !this.permissionsChanged) {
this.editing = false
this.toggleCollaboratorsEdit(false)
return
}
// TODO: Bring this back
// if (this.selectedRole.name === this.originalRole.name && !this.permissionsChanged) {
// this.editing = false
// this.toggleCollaboratorsEdit(false)
// return
// }
this.editing = true
this.toggleCollaboratorsEdit(true)
},
Expand All @@ -197,6 +143,7 @@ export default {
</script>

<style>
/* TODO: Move to ODS */
.oc-text {
font-size: 1rem;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<template>
<oc-grid gutter="small" childWidth="1-1">
<roles-select
:selectedRole="role"
@roleSelected="selectRole"
/>
<additional-permissions
:availablePermissions="role.additionalPermissions"
:collaboratorsPermissions="collaboratorsPermissions"
@permissionChecked="checkAdditionalPermissions"
/>
</oc-grid>
</template>

<script>
import collaboratorsMixins from '../../mixins/collaborators'
const RolesSelect = () => import('./RolesSelect.vue')
const AdditionalPermissions = () => import('./AdditionalPermissions.vue')
export default {
name: 'CollaboratorsEditOptions',
mixins: [
collaboratorsMixins
],
props: {
existingRole: {
type: Object,
required: false
},
collaboratorsPermissions: {
type: Object,
required: false
}
},
components: {
RolesSelect,
AdditionalPermissions
},
data () {
return {
selectedRole: null,
additionalPermissions: null
}
},
computed: {
role () {
// Returns default role
if (!this.existingRole && !this.selectedRole) {
const defaultRole = this.roles[Object.keys(this.roles)[0]]
this.selectRole(defaultRole, false)
return defaultRole
}
if (
(
this.existingRole && this.existingRole.name === 'advancedRole'
) || (
this.selectedRole && this.selectedRole.name === 'advancedRole'
)
) {
this.selectRole(this.advancedRole, false)
return this.advancedRole
}
if (this.existingRole && !this.selectedRole) {
this.selectRole(this.existingRole, false)
return this.existingRole
}
return this.selectedRole
}
},
methods: {
selectRole (role, propagate = true) {
this.selectedRole = role
this.$emit('optionChange', { role: this.selectedRole, permissions: this.additionalPermissions, propagate: propagate })
},
checkAdditionalPermissions (permissions) {
this.additionalPermissions = permissions
this.$emit('optionChange', { role: this.selectedRole, permissions: this.additionalPermissions })
}
}
}
</script>
Loading

0 comments on commit 20c88f5

Please sign in to comment.