mirror of
https://github.com/nextcloud/server.git
synced 2026-04-24 15:53:36 -04:00
Port files sharing selector
Signed-off-by: Christopher Ng <chrng8@gmail.com>
This commit is contained in:
parent
75d7203f57
commit
0236c9e8cd
6 changed files with 70 additions and 66 deletions
|
|
@ -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.') }}
|
||||
:options="options"
|
||||
v-model="value"
|
||||
@search="asyncFind"
|
||||
@option:selected="addShare">
|
||||
<template #no-options="{ search }">
|
||||
{{ search ? noResultText : t('files_sharing', 'No recommendations. Start typing.') }}
|
||||
</template>
|
||||
<template #noResult>
|
||||
{{ noResultText }}
|
||||
</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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
dist/core-common.js
vendored
4
dist/core-common.js
vendored
File diff suppressed because one or more lines are too long
2
dist/core-common.js.map
vendored
2
dist/core-common.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/files_sharing-files_sharing_tab.js
vendored
4
dist/files_sharing-files_sharing_tab.js
vendored
File diff suppressed because one or more lines are too long
2
dist/files_sharing-files_sharing_tab.js.map
vendored
2
dist/files_sharing-files_sharing_tab.js.map
vendored
File diff suppressed because one or more lines are too long
|
|
@ -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…
Reference in a new issue