Browse Source

Port files sharing selector

Signed-off-by: Christopher Ng <chrng8@gmail.com>
tags/v26.0.0beta1
Christopher Ng 1 year ago
parent
commit
0236c9e8cd

+ 61
- 56
apps/files_sharing/src/components/SharingInput.vue View File

@@ -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;
}
}
}

+ 2
- 2
dist/core-common.js
File diff suppressed because it is too large
View File


+ 1
- 1
dist/core-common.js.map
File diff suppressed because it is too large
View File


+ 2
- 2
dist/files_sharing-files_sharing_tab.js
File diff suppressed because it is too large
View File


+ 1
- 1
dist/files_sharing-files_sharing_tab.js.map
File diff suppressed because it is too large
View File


+ 3
- 4
tests/acceptance/features/bootstrap/FilesAppSharingContext.php View File

@@ -41,7 +41,7 @@ class FilesAppSharingContext implements Context, ActorAwareInterface {
* @return Locator
*/
public static function shareWithInput() {
return Locator::forThe()->css(".sharing-search__input .multiselect__input")->
return Locator::forThe()->css(".sharing-search__input input")->
descendantOf(FilesAppContext::detailsView())->
describedAs("Share with input in the details view in Files app");
}
@@ -50,8 +50,7 @@ class FilesAppSharingContext implements Context, ActorAwareInterface {
* @return Locator
*/
public static function shareWithInputResults() {
return Locator::forThe()->css(".sharing-search__input .multiselect__content-wrapper")->
descendantOf(FilesAppContext::detailsView())->
return Locator::forThe()->css(".vs__dropdown-menu")->
describedAs("Share with input results list in the details view in Files app");
}

@@ -59,7 +58,7 @@ class FilesAppSharingContext implements Context, ActorAwareInterface {
* @return Locator
*/
public static function shareWithInputResult($result) {
return Locator::forThe()->xpath("//li[contains(concat(' ', normalize-space(@class), ' '), ' multiselect__element ')]//span[normalize-space() = '$result']/ancestor::li")->
return Locator::forThe()->xpath("//li//span[normalize-space() = '$result']/ancestor::li")->
descendantOf(self::shareWithInputResults())->
describedAs("Share with input result from the results list in the details view in Files app");
}

Loading…
Cancel
Save