summaryrefslogtreecommitdiffstats
path: root/apps/files_sharing
diff options
context:
space:
mode:
authorPytal <24800714+Pytal@users.noreply.github.com>2023-01-24 18:25:33 -0800
committerGitHub <noreply@github.com>2023-01-24 18:25:33 -0800
commit96a21056c4aa2b7ae11e4414e1427e3941a8de11 (patch)
treed5ab0764a64f667a66b134d356736bdb02056dd5 /apps/files_sharing
parent75d7203f579f5761fc921d9506579bec48ebab74 (diff)
parent0236c9e8cd1162ea8f0b284dfd846c21f7d3a5be (diff)
downloadnextcloud-server-96a21056c4aa2b7ae11e4414e1427e3941a8de11.tar.gz
nextcloud-server-96a21056c4aa2b7ae11e4414e1427e3941a8de11.zip
Merge pull request #36055 from nextcloud/enh/a11y-sharing-select
Port files sharing selector
Diffstat (limited to 'apps/files_sharing')
-rw-r--r--apps/files_sharing/src/components/SharingInput.vue117
1 files changed, 61 insertions, 56 deletions
diff --git a/apps/files_sharing/src/components/SharingInput.vue b/apps/files_sharing/src/components/SharingInput.vue
index 27d08f77a29..46c495d8279 100644
--- a/apps/files_sharing/src/components/SharingInput.vue
+++ b/apps/files_sharing/src/components/SharingInput.vue
@@ -23,32 +23,23 @@
<template>
<div class="sharing-search">
<label for="sharing-search-input">{{ t('files_sharing', 'Search for share recipients') }}</label>
- <NcMultiselect ref="multiselect"
+ <NcSelect ref="select"
id="sharing-search-input"
class="sharing-search__input"
- :clear-on-select="true"
:disabled="!canReshare"
- :hide-selected="true"
- :internal-search="false"
:loading="loading"
- :options="options"
+ :filterable="false"
:placeholder="inputPlaceholder"
- :preselect-first="true"
- :preserve-search="true"
- :searchable="true"
+ :clear-search-on-blur="() => false"
:user-select="true"
- open-direction="below"
- label="displayName"
- track-by="id"
- @search-change="asyncFind"
- @select="addShare">
- <template #noOptions>
- {{ t('files_sharing', 'No recommendations. Start typing.') }}
- </template>
- <template #noResult>
- {{ noResultText }}
+ :options="options"
+ v-model="value"
+ @search="asyncFind"
+ @option:selected="addShare">
+ <template #no-options="{ search }">
+ {{ search ? noResultText : t('files_sharing', 'No recommendations. Start typing.') }}
</template>
- </NcMultiselect>
+ </NcSelect>
</div>
</template>
@@ -57,7 +48,7 @@ import { generateOcsUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
import axios from '@nextcloud/axios'
import debounce from 'debounce'
-import NcMultiselect from '@nextcloud/vue/dist/Components/NcMultiselect'
+import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js'
import Config from '../services/ConfigService'
import GeneratePassword from '../utils/GeneratePassword'
@@ -69,7 +60,7 @@ export default {
name: 'SharingInput',
components: {
- NcMultiselect,
+ NcSelect,
},
mixins: [ShareTypes, ShareRequests],
@@ -108,6 +99,7 @@ export default {
recommendations: [],
ShareSearch: OCA.Sharing.ShareSearch.state,
suggestions: [],
+ value: null,
}
},
@@ -161,7 +153,7 @@ export default {
},
methods: {
- async asyncFind(query, id) {
+ async asyncFind(query) {
// save current query to check if we display
// recommendations or search results
this.query = query.trim()
@@ -391,21 +383,38 @@ export default {
// themselves from it, so let's not display the user icon
// case this.SHARE_TYPES.SHARE_TYPE_REMOTE:
// case this.SHARE_TYPES.SHARE_TYPE_USER:
- return 'icon-user'
+ return {
+ icon: 'icon-user',
+ iconTitle: t('files_sharing', 'Guest'),
+ }
case this.SHARE_TYPES.SHARE_TYPE_REMOTE_GROUP:
case this.SHARE_TYPES.SHARE_TYPE_GROUP:
- return 'icon-group'
+ return {
+ icon: 'icon-group',
+ iconTitle: t('files_sharing', 'Group'),
+ }
case this.SHARE_TYPES.SHARE_TYPE_EMAIL:
- return 'icon-mail'
+ return {
+ icon: 'icon-mail',
+ iconTitle: t('files_sharing', 'Email'),
+ }
case this.SHARE_TYPES.SHARE_TYPE_CIRCLE:
- return 'icon-circle'
+ return {
+ icon: 'icon-circle',
+ iconTitle: t('files_sharing', 'Circle'),
+ }
case this.SHARE_TYPES.SHARE_TYPE_ROOM:
- return 'icon-room'
+ return {
+ icon: 'icon-room',
+ iconTitle: t('files_sharing', 'Talk conversation'),
+ }
case this.SHARE_TYPES.SHARE_TYPE_DECK:
- return 'icon-deck'
-
+ return {
+ icon: 'icon-deck',
+ iconTitle: t('files_sharing', 'Deck board'),
+ }
default:
- return ''
+ return {}
}
},
@@ -438,7 +447,7 @@ export default {
displayName: result.name || result.label,
subtitle,
shareWithDisplayNameUnique: result.shareWithDisplayNameUnique || '',
- icon: this.shareTypeToIcon(result.value.shareType),
+ ...this.shareTypeToIcon(result.value.shareType),
}
},
@@ -448,12 +457,15 @@ export default {
* @param {object} value the multiselect option
*/
async addShare(value) {
+ // Clear the displayed selection
+ this.value = null
+
if (value.lookup) {
await this.getSuggestions(this.query, true)
- // focus the input again
this.$nextTick(() => {
- this.$refs.multiselect.$el.querySelector('.multiselect__input').focus()
+ // open the dropdown again
+ this.$refs.select.$children[0].open = true
})
return true
}
@@ -501,19 +513,12 @@ export default {
this.$emit('add:share', share)
}
- // reset the search string when done
- // FIXME: https://github.com/shentao/vue-multiselect/issues/633
- if (this.$refs.multiselect?.$refs?.VueMultiselect?.search) {
- this.$refs.multiselect.$refs.VueMultiselect.search = ''
- }
-
await this.getRecommendations()
} catch (error) {
- // focus back if any error
- const input = this.$refs.multiselect.$el.querySelector('input')
- if (input) {
- input.focus()
- }
+ this.$nextTick(() => {
+ // open the dropdown again on error
+ this.$refs.select.$children[0].open = true
+ })
this.query = value.shareWith
console.error('Error while adding new share', error)
} finally {
@@ -537,19 +542,19 @@ export default {
&__input {
width: 100%;
margin: 10px 0;
+ }
+}
- // properly style the lookup entry
- .multiselect__option {
- span[lookup] {
- .avatardiv {
- background-image: var(--icon-search-white);
- background-repeat: no-repeat;
- background-position: center;
- background-color: var(--color-text-maxcontrast) !important;
- div {
- display: none;
- }
- }
+.vs__dropdown-menu {
+ // properly style the lookup entry
+ span[lookup] {
+ .avatardiv {
+ background-image: var(--icon-search-white);
+ background-repeat: no-repeat;
+ background-position: center;
+ background-color: var(--color-text-maxcontrast) !important;
+ div {
+ display: none;
}
}
}