Skip to content

Commit

Permalink
Merge pull request #4247 from nextcloud/enh/3743/use-ncselect-in-ncri…
Browse files Browse the repository at this point in the history
…chtext
  • Loading branch information
raimund-schluessler committed Jun 23, 2023
2 parents b932834 + 0748718 commit 68b3f9e
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 52 deletions.
3 changes: 3 additions & 0 deletions l10n/messages.pot
Expand Up @@ -167,6 +167,9 @@ msgstr ""
msgid "Previous"
msgstr ""

msgid "Provider icon"
msgstr ""

msgid "Raw link {options}"
msgstr ""

Expand Down
37 changes: 21 additions & 16 deletions src/components/NcRichText/NcReferencePicker/NcProviderList.vue
@@ -1,32 +1,33 @@
<template>
<div class="provider-list">
<NcMultiselect ref="provider-select"
<NcSelect ref="provider-select"
v-model="selectedProvider"
class="provider-list--select"
track-by="id"
input-id="provider-select-input"
label="title"
:placeholder="multiselectPlaceholder"
:options="options"
:internal-search="false"
:clear-on-select="true"
:preserve-search="true"
:option-height="44"
@search-change="query = $event"
:append-to-body="false"
:clear-search-on-select="true"
:clear-search-on-blur="() => false"
:filterable="false"
@search="onSearch"
@input="onProviderSelected">
<template #option="{option}">
<template #option="option">
<div v-if="option.isLink" class="provider">
<LinkVariantIcon class="link-icon" :size="20" />
<span>{{ option.title }}</span>
</div>
<div v-else class="provider">
<img class="provider-icon"
:src="option.icon_url">
:src="option.icon_url"
:alt="providerIconAlt">
<NcHighlight class="option-text"
:search="query"
:text="option.title" />
</div>
</template>
</NcMultiselect>
</NcSelect>
<NcEmptyContent class="provider-list--empty-content">
<template #icon>
<LinkVariantIcon />
Expand All @@ -40,15 +41,15 @@ import { searchProvider } from './providerHelper.js'
import { isUrl } from './utils.js'
import NcEmptyContent from '../../NcEmptyContent/index.js'
import NcHighlight from '../../NcHighlight/index.js'
import NcMultiselect from '../../NcMultiselect/index.js'
import NcSelect from '../../NcSelect/index.js'
import { t } from '../../../l10n.js'
import LinkVariantIcon from 'vue-material-design-icons/LinkVariant.vue'
export default {
name: 'NcProviderList',
components: {
NcMultiselect,
NcSelect,
NcHighlight,
NcEmptyContent,
LinkVariantIcon,
Expand All @@ -62,6 +63,7 @@ export default {
selectedProvider: null,
query: '',
multiselectPlaceholder: t('Select provider'),
providerIconAlt: t('Provider icon'),
}
},
computed: {
Expand All @@ -80,9 +82,9 @@ export default {
},
methods: {
focus() {
this.$nextTick(() => {
this.$refs['provider-select']?.$el?.focus()
})
setTimeout(() => {
this.$refs['provider-select']?.$el?.querySelector('#provider-select-input')?.focus()
}, 300)
},
onProviderSelected(p) {
if (p !== null) {
Expand All @@ -94,14 +96,17 @@ export default {
this.selectedProvider = null
}
},
onSearch(query, loading) {
this.query = query
},
},
}
</script>
<style lang="scss" scoped>
.provider-list {
width: 100%;
min-height: 350px;
min-height: 400px;
padding: 0 16px 16px 16px;
display: flex;
flex-direction: column;
Expand Down
77 changes: 41 additions & 36 deletions src/components/NcRichText/NcReferencePicker/NcSearch.vue
@@ -1,21 +1,24 @@
<template>
<div class="smart-picker-search" :class="{ 'with-empty-content': showEmptyContent }">
<NcMultiselect ref="search-select"
<NcSelect ref="search-select"
v-model="selectedResult"
class="smart-picker-search--select"
track-by="resourceUrl"
input-id="search-select-input"
label="name"
:placeholder="mySearchPlaceholder"
:options="options"
:internal-search="false"
:clear-on-select="false"
:append-to-body="false"
:close-on-select="false"
:preserve-search="true"
:clear-search-on-select="false"
:clear-search-on-blur="() => false"
:reset-focus-on-options-change="false"
:filterable="false"
:autoscroll="true"
:reset-on-options-change="false"
:loading="searching"
:multiple="false"
:option-height="60"
@search-change="onSearchInput"
@search="onSearchInput"
@input="onSelectResultSelected">
<template #option="{option}">
<template #option="option">
<div v-if="option.isRawLink" class="custom-option">
<LinkVariantIcon class="option-simple-icon" :size="20" />
<span class="option-text">
Expand All @@ -42,20 +45,16 @@
</span>
</span>
</template>
<template #noOptions>
<MagnifyIcon class="option-simple-icon" :size="20" />
{{ t('Start typing to search') }}
<template #no-options>
{{ noOptionsText }}
</template>
<template #noResult>
<MagnifyIcon class="option-simple-icon" :size="20" />
{{ t('Start typing to search') }}
</template>
</NcMultiselect>
</NcSelect>
<NcEmptyContent v-if="showEmptyContent"
class="smart-picker-search--empty-content">
<template #icon>
<img v-if="provider.icon_url"
class="provider-icon"
:alt="providerIconAlt"
:src="provider.icon_url">
<LinkVariantIcon v-else />
</template>
Expand All @@ -67,7 +66,7 @@
import NcSearchResult from './NcSearchResult.vue'
import { isUrl, delay } from './utils.js'
import NcEmptyContent from '../../NcEmptyContent/index.js'
import NcMultiselect from '../../NcMultiselect/index.js'
import NcSelect from '../../NcSelect/index.js'
import { t } from '../../../l10n.js'
Expand All @@ -76,7 +75,6 @@ import { generateOcsUrl } from '@nextcloud/router'
import DotsHorizontalIcon from 'vue-material-design-icons/DotsHorizontal.vue'
import LinkVariantIcon from 'vue-material-design-icons/LinkVariant.vue'
import MagnifyIcon from 'vue-material-design-icons/Magnify.vue'
const LIMIT = 5
Expand All @@ -85,9 +83,8 @@ export default {
components: {
LinkVariantIcon,
DotsHorizontalIcon,
MagnifyIcon,
NcEmptyContent,
NcMultiselect,
NcSelect,
NcSearchResult,
},
props: {
Expand Down Expand Up @@ -118,6 +115,8 @@ export default {
searching: false,
searchingMoreOf: null,
abortController: null,
noOptionsText: t('Start typing to search'),
providerIconAlt: t('Provider icon'),
}
},
computed: {
Expand All @@ -141,6 +140,7 @@ export default {
},
rawLinkEntry() {
return {
id: 'rawLinkEntry',
resourceUrl: this.searchQuery,
isRawLink: true,
}
Expand All @@ -152,14 +152,22 @@ export default {
// don't show group name entry if there is only one search provider and one result
if (this.searchProviderIds.length > 1 || this.resultsBySearchProvider[pid].entries.length > 1) {
results.push({
id: 'groupTitle-' + pid,
name: this.resultsBySearchProvider[pid].name,
isCustomGroupTitle: true,
providerId: pid,
})
}
results.push(...this.resultsBySearchProvider[pid].entries)
const providerEntriesWithId = this.resultsBySearchProvider[pid].entries.map((entry, index) => {
return {
id: 'provider-' + pid + '-entry-' + index,
...entry,
}
})
results.push(...providerEntriesWithId)
if (this.resultsBySearchProvider[pid].isPaginated) {
results.push({
id: 'moreOf-' + pid,
name: this.resultsBySearchProvider[pid].name,
isMore: true,
providerId: pid,
Expand Down Expand Up @@ -189,14 +197,16 @@ export default {
this.resultsBySearchProvider = resultsBySearchProvider
},
focus() {
this.$refs['search-select']?.$el?.focus()
setTimeout(() => {
this.$refs['search-select']?.$el?.querySelector('#search-select-input')?.focus()
}, 300)
},
cancelSearchRequests() {
if (this.abortController) {
this.abortController.abort()
}
},
onSearchInput(query) {
onSearchInput(query, loading) {
this.searchQuery = query
delay(() => {
this.updateSearch()
Expand All @@ -208,16 +218,17 @@ export default {
this.cancelSearchRequests()
this.$emit('submit', item.resourceUrl)
} else if (item.isMore) {
this.searchMoreOf(item.providerId)
this.searchMoreOf(item.providerId).then(() => {
// allow clicking twice on the same "more" item
this.selectedResult = null
})
}
}
// avoid showing something in the singleLabel slot (selected item)
this.selectedResult = null
},
searchMoreOf(searchProviderId) {
this.searchingMoreOf = searchProviderId
this.cancelSearchRequests()
this.searchProviders(searchProviderId)
return this.searchProviders(searchProviderId)
},
updateSearch() {
this.cancelSearchRequests()
Expand All @@ -227,7 +238,7 @@ export default {
return
}
this.searchProviders()
return this.searchProviders()
},
searchProviders(searchProviderId = null) {
this.abortController = new AbortController()
Expand Down Expand Up @@ -279,7 +290,7 @@ export default {
flex-direction: column;
padding: 0 16px 16px 16px;
&.with-empty-content {
min-height: 350px;
min-height: 400px;
}
&--empty-content {
Expand Down Expand Up @@ -320,12 +331,6 @@ export default {
text-overflow: ellipsis;
white-space: nowrap;
}
// multiselect dropdown is wider than the select input
// this avoids overflow
:deep(.multiselect__content-wrapper) {
width: calc(100% - 4px) !important;
}
}
}
</style>

0 comments on commit 68b3f9e

Please sign in to comment.