diff options
author | Pytal <24800714+Pytal@users.noreply.github.com> | 2023-01-24 18:25:33 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-24 18:25:33 -0800 |
commit | 96a21056c4aa2b7ae11e4414e1427e3941a8de11 (patch) | |
tree | d5ab0764a64f667a66b134d356736bdb02056dd5 /apps/files_sharing | |
parent | 75d7203f579f5761fc921d9506579bec48ebab74 (diff) | |
parent | 0236c9e8cd1162ea8f0b284dfd846c21f7d3a5be (diff) | |
download | nextcloud-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.vue | 117 |
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; } } } |