Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use oc-select to select roles #4937

Merged
merged 10 commits into from
Apr 26, 2021
6 changes: 6 additions & 0 deletions changelog/unreleased/enhancement-select-roles
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Enhancement: Use `oc-select` for role select

We've used the new `oc-select` component from ODS for selecting role in people and public links accordions in the right sidebar.
We are using this component to enable keyboard navigation when selecting the role.

https://github.com/owncloud/web/pull/4937
Original file line number Diff line number Diff line change
Expand Up @@ -266,11 +266,8 @@ export default {
},

originalRole() {
if (this.collaborator.role.name === 'advancedRole') {
return this.advancedRole
}
const role = this.displayRoles.find(r => r.name === this.collaborator.role.name)

const role = this.displayRoles[this.collaborator.role.name]
if (role) {
return role
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
<template>
<oc-grid gutter="small" child-width="1-1">
<roles-select
mode="collaborators"
:roles="roles"
:selected-role="role"
@roleSelected="selectRole"
/>
<div>
<translate tag="label" for="files-collaborators-role-button" class="oc-label">Role</translate>
<oc-select
v-model="selectedRole"
input-id="files-collaborators-role-button"
class="files-collaborators-role-button-wrapper"
:options="roles"
:clearable="false"
label="label"
>
<template v-slot:option="option">
<role-item :role="option" />
</template>
<template #no-options v-translate>
No matching role found
</template>
</oc-select>
<template v-if="$_ocCollaborators_hasAdditionalPermissions">
<label v-if="selectedRole.name !== 'advancedRole'" class="oc-label">
<label v-if="selectedRole.name !== 'advancedRole'" class="oc-label oc-mt-s">
<translate>Additional permissions</translate>
</label>
<additional-permissions
:available-permissions="role.additionalPermissions"
:available-permissions="selectedRole.additionalPermissions"
:collaborators-permissions="collaboratorsPermissions"
:class="{ 'oc-mt-s': selectedRole.name === 'advancedRole' }"
@permissionChecked="checkAdditionalPermissions"
/>
</template>
<div v-if="expirationSupported">
<div v-if="expirationSupported" class="oc-mt-m">
<label for="files-collaborators-collaborator-expiration-input">
<translate>Expiration date</translate>
<translate v-if="expirationDateEnforced" tag="em">(required)</translate>
Expand All @@ -40,22 +51,22 @@
/>
</div>
</div>
</oc-grid>
</div>
</template>

<script>
import { mapGetters } from 'vuex'
import moment from 'moment'
import collaboratorsMixins from '../../mixins/collaborators'

import RolesSelect from '../Roles/RolesSelect.vue'
import RoleItem from '../RoleItem.vue'
import AdditionalPermissions from './AdditionalPermissions.vue'

export default {
name: 'CollaboratorsEditOptions',

components: {
RolesSelect,
RoleItem,
AdditionalPermissions
},

Expand Down Expand Up @@ -110,30 +121,6 @@ export default {
return this.selectedRole && this.selectedRole.additionalPermissions
},

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 && 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
},

expirationSupported() {
return this.userExpirationDate && this.groupExpirationDate
},
Expand Down Expand Up @@ -236,6 +223,25 @@ export default {
}
},

watch: {
selectedRole: {
handler: 'publishChange'
}
},

created() {
if (
(this.existingRole && this.existingRole.name === 'advancedRole' && !this.selectedRole) ||
(this.selectedRole && this.selectedRole.name === 'advancedRole')
) {
this.selectedRole = this.advancedRole
} else if (this.existingRole && !this.selectedRole) {
this.selectedRole = this.existingRole
} else {
this.selectedRole = this.roles[0]
}
},

mounted() {
if (this.expirationSupported) {
if (this.editingUser || this.editingGroup) {
Expand All @@ -253,11 +259,6 @@ export default {
},

methods: {
selectRole(role) {
this.selectedRole = role
this.publishChange()
},

checkAdditionalPermissions(permissions) {
this.additionalPermissions = permissions
this.publishChange()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export default {
},

$_originalRole() {
return this.roles[this.collaborator.role.name]
return this.roles.find(r => r.name === this.collaborator.role.name)
},

$_permissionsBitmask() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
:disabled="!$_isValid"
variation="primary"
appearance="filled"
@click="$_ocCollaborators_newCollaboratorsAdd(selectedCollaborators)"
@click="share"
>
<translate>Share</translate>
</oc-button>
Expand Down Expand Up @@ -203,12 +203,12 @@ export default {
this.saving = false
this.close()
},
$_ocCollaborators_newCollaboratorsAdd(collaborators) {
share() {
this.saving = true

const saveQueue = new PQueue({ concurrency: 4 })
const savePromises = []
collaborators.forEach(collaborator => {
this.selectedCollaborators.forEach(collaborator => {
savePromises.push(
saveQueue.add(() =>
this.addShare({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,24 @@
<div class="oc-mb">
<oc-text-input id="oc-files-file-link-name" v-model="name" :label="$gettext('Name')" />
</div>
<oc-grid child-width="1-1" gutter="small">
<roles-select
:roles="$_roles"
:selected-role="$_selectedRole"
mode="file-link"
@roleSelected="$_selectRole"
/>
</oc-grid>
<translate tag="label" for="files-file-link-role-button" class="oc-label">
Role
</translate>
<oc-select
v-model="selectedRole"
input-id="files-file-link-role-button"
:options="roles"
:clearable="false"
label="label"
class="oc-mb files-file-link-role-button-wrapper"
>
<template v-slot:option="option">
<role-item :role="option" />
</template>
<template #no-options v-translate>
No matching role found
</template>
</oc-select>
<div class="oc-mb uk-grid-small uk-flex" uk-grid>
<div v-if="$_expirationDate" class="uk-width-1-1 uk-width-2-5@m">
<div class="uk-position-relative">
Expand Down Expand Up @@ -126,15 +136,12 @@
import { mapGetters, mapActions, mapState, mapMutations } from 'vuex'
import mixins from '../../mixins'
import moment from 'moment'
import filter from 'lodash-es/filter'
import first from 'lodash-es/first'
import values from 'lodash-es/values'
import publicLinkRoles from '../../helpers/publicLinkRolesDefinition'
import RolesSelect from '../Roles/RolesSelect.vue'
import RoleItem from '../RoleItem.vue'

export default {
components: {
RolesSelect
RoleItem
},
mixins: [mixins],
data() {
Expand All @@ -145,11 +152,11 @@ export default {
name: null,
hasPassword: false,
expireDate: null,
permissions: 1,
placeholder: {
mailTo: this.$gettext('Mail recipients'),
mailBody: this.$gettext('Personal note')
}
},
selectedRole: null
}
},
title: $gettext => {
Expand Down Expand Up @@ -180,7 +187,7 @@ export default {
return (
expireDateNow !== expireDateBefore ||
this.name !== this.publicLinkInEdit.name ||
this.permissions !== this.publicLinkInEdit.permissions ||
this.selectedRole.permissions !== this.publicLinkInEdit.permissions ||
(this.publicLinkInEdit.hasPassword
? this.password !== null
: this.password !== null && this.password.trim().length > 0)
Expand All @@ -191,25 +198,14 @@ export default {
return Object.keys(this.capabilities.files_sharing.public.send_mail).length > 0
},

$_roles() {
roles() {
const $gettext = this.$gettext
return publicLinkRoles({
$gettext,
isFolder: this.$_isFolder
})
},

$_selectedRole() {
const permissions = parseInt(this.permissions, 10)
if (permissions) {
const matchingRoles = filter(this.$_roles, r => r.permissions === permissions)
if (matchingRoles.length > 0) {
return first(values(matchingRoles))
}
}
return this.$_roles.viewer
},

$_expirationDate() {
const expireDate = this.capabilities.files_sharing.public.expire_date

Expand Down Expand Up @@ -257,7 +253,7 @@ export default {
},

$_passwordEnforced() {
const permissions = parseInt(this.permissions, 10)
const permissions = parseInt(this.selectedRole.permissions, 10)
const password = this.capabilities.files_sharing.public.password.enforced_for

if (permissions === 1 && password.read_only === '1') {
Expand Down Expand Up @@ -293,22 +289,35 @@ export default {
this.name = this.publicLinkInEdit.name
this.hasPassword = this.publicLinkInEdit.hasPassword
this.expireDate = this.publicLinkInEdit.expireDate
this.permissions = this.publicLinkInEdit.permissions

this.setRole()
},
methods: {
...mapActions('Files', ['addLink', 'updateLink']),
...mapMutations('Files', ['SET_APP_SIDEBAR_ACCORDION_CONTEXT']),

$_selectRole(role) {
this.permissions = role.permissions
setRole() {
const permissions = parseInt(this.publicLinkInEdit.permissions, 10)

if (permissions) {
const role = this.roles.find(r => r.permissions === permissions)

if (role) {
this.selectedRole = role

return
}
}

this.selectedRole = this.roles[0]
},

$_addLink() {
this.saving = true

const params = {
expireDate: this.expireDate,
permissions: this.permissions,
permissions: this.selectedRole.permissions,
name: this.name
}

Expand Down Expand Up @@ -338,7 +347,7 @@ export default {

const params = {
expireDate: this.expireDate,
permissions: this.permissions,
permissions: this.selectedRole.permissions,
name: this.name
}

Expand Down
18 changes: 18 additions & 0 deletions packages/web-app-files/src/components/RoleItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<template>
<span :id="`files-role-${role.name}`" class="roles-select-role-item">
<span class="oc-text-bold uk-display-block uk-width-1-1" v-text="role.label" />
<span class="oc-m-rm" v-text="role.description" />
</span>
</template>

<script>
export default {
name: 'RoleItem',
props: {
role: {
type: Object,
required: true
}
}
}
</script>
Loading