diff options
Diffstat (limited to 'core/src/components')
-rw-r--r-- | core/src/components/GlobalSearch/SearchResult.vue | 169 | ||||
-rw-r--r-- | core/src/components/UnifiedSearch/CustomDateRangeModal.vue (renamed from core/src/components/GlobalSearch/CustomDateRangeModal.vue) | 14 | ||||
-rw-r--r-- | core/src/components/UnifiedSearch/LegacySearchResult.vue | 259 | ||||
-rw-r--r-- | core/src/components/UnifiedSearch/SearchFilterChip.vue (renamed from core/src/components/GlobalSearch/SearchFilterChip.vue) | 0 | ||||
-rw-r--r-- | core/src/components/UnifiedSearch/SearchResult.vue | 286 | ||||
-rw-r--r-- | core/src/components/UnifiedSearch/SearchableList.vue (renamed from core/src/components/GlobalSearch/SearchableList.vue) | 0 |
6 files changed, 364 insertions, 364 deletions
diff --git a/core/src/components/GlobalSearch/SearchResult.vue b/core/src/components/GlobalSearch/SearchResult.vue deleted file mode 100644 index a746a5751b7..00000000000 --- a/core/src/components/GlobalSearch/SearchResult.vue +++ /dev/null @@ -1,169 +0,0 @@ -<template> - <NcListItem class="result-items__item" - :name="title" - :bold="false" - :href="resourceUrl" - target="_self"> - <template #icon> - <div aria-hidden="true" - class="result-items__item-icon" - :class="{ - 'result-items__item-icon--rounded': rounded, - 'result-items__item-icon--no-preview': !isValidIconOrPreviewUrl(thumbnailUrl), - 'result-items__item-icon--with-thumbnail': isValidIconOrPreviewUrl(thumbnailUrl), - [icon]: !isValidIconOrPreviewUrl(icon), - }" - :style="{ - backgroundImage: isValidIconOrPreviewUrl(icon) ? `url(${icon})` : '', - }"> - <img v-if="isValidIconOrPreviewUrl(thumbnailUrl) && !thumbnailHasError" - :src="thumbnailUrl" - @error="thumbnailErrorHandler"> - </div> - </template> - <template #subname> - {{ subline }} - </template> - </NcListItem> -</template> - -<script> -import NcListItem from '@nextcloud/vue/dist/Components/NcListItem.js' - -export default { - name: 'SearchResult', - components: { - NcListItem, - }, - props: { - thumbnailUrl: { - type: String, - default: null, - }, - title: { - type: String, - required: true, - }, - subline: { - type: String, - default: null, - }, - resourceUrl: { - type: String, - default: null, - }, - icon: { - type: String, - default: '', - }, - rounded: { - type: Boolean, - default: false, - }, - query: { - type: String, - default: '', - }, - - /** - * Only used for the first result as a visual feedback - * so we can keep the search input focused but pressing - * enter still opens the first result - */ - focused: { - type: Boolean, - default: false, - }, - }, - data() { - return { - thumbnailHasError: false, - } - }, - watch: { - thumbnailUrl() { - this.thumbnailHasError = false - }, - }, - methods: { - isValidIconOrPreviewUrl(url) { - return /^https?:\/\//.test(url) || url.startsWith('/') - }, - thumbnailErrorHandler() { - this.thumbnailHasError = true - }, - }, -} -</script> - -<style lang="scss" scoped> -@use "sass:math"; -$clickable-area: 44px; -$margin: 10px; - -.result-items { - &__item { - - ::v-deep a { - border-radius: 12px; - border: 2px solid transparent; - border-radius: var(--border-radius-large) !important; - - &--focused { - background-color: var(--color-background-hover); - } - - &:active, - &:hover, - &:focus { - background-color: var(--color-background-hover); - border: 2px solid var(--color-border-maxcontrast); - } - - * { - cursor: pointer; - } - - } - - &-icon { - overflow: hidden; - width: $clickable-area; - height: $clickable-area; - border-radius: var(--border-radius); - background-repeat: no-repeat; - background-position: center center; - background-size: 32px; - - &--rounded { - border-radius: math.div($clickable-area, 2); - } - - &--no-preview { - background-size: 32px; - } - - &--with-thumbnail { - background-size: cover; - } - - &--with-thumbnail:not(&--rounded) { - // compensate for border - max-width: $clickable-area - 2px; - max-height: $clickable-area - 2px; - border: 1px solid var(--color-border); - } - - img { - // Make sure to keep ratio - width: 100%; - height: 100%; - - object-fit: cover; - object-position: center; - } - } - - } -} -</style> diff --git a/core/src/components/GlobalSearch/CustomDateRangeModal.vue b/core/src/components/UnifiedSearch/CustomDateRangeModal.vue index 0ba6ddca015..ec592732a8d 100644 --- a/core/src/components/GlobalSearch/CustomDateRangeModal.vue +++ b/core/src/components/UnifiedSearch/CustomDateRangeModal.vue @@ -1,6 +1,6 @@ <template> <NcModal v-if="isModalOpen" - id="global-search" + id="unified-search" :name="t('core', 'Custom date range')" :show.sync="isModalOpen" :size="'small'" @@ -8,19 +8,19 @@ :title="t('core', 'Custom date range')" @close="closeModal"> <!-- Custom date range --> - <div class="global-search-custom-date-modal"> + <div class="unified-search-custom-date-modal"> <h1>{{ t('core', 'Custom date range') }}</h1> - <div class="global-search-custom-date-modal__pickers"> - <NcDateTimePicker :id="'globalsearch-custom-date-range-start'" + <div class="unified-search-custom-date-modal__pickers"> + <NcDateTimePicker :id="'unifiedsearch-custom-date-range-start'" v-model="dateFilter.startFrom" :label="t('core', 'Pick start date')" type="date" /> - <NcDateTimePicker :id="'globalsearch-custom-date-range-end'" + <NcDateTimePicker :id="'unifiedsearch-custom-date-range-end'" v-model="dateFilter.endAt" :label="t('core', 'Pick end date')" type="date" /> </div> - <div class="global-search-custom-date-modal__footer"> + <div class="unified-search-custom-date-modal__footer"> <NcButton @click="applyCustomRange"> {{ t('core', 'Search in date range') }} <template #icon> @@ -80,7 +80,7 @@ export default { </script> <style lang="scss" scoped> -.global-search-custom-date-modal { +.unified-search-custom-date-modal { padding: 10px 20px 10px 20px; h1 { diff --git a/core/src/components/UnifiedSearch/LegacySearchResult.vue b/core/src/components/UnifiedSearch/LegacySearchResult.vue new file mode 100644 index 00000000000..01f48a36709 --- /dev/null +++ b/core/src/components/UnifiedSearch/LegacySearchResult.vue @@ -0,0 +1,259 @@ + <!-- + - @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com> + - + - @author John Molakvoæ <skjnldsv@protonmail.com> + - + - @license GNU AGPL version 3 or any later version + - + - This program is free software: you can redistribute it and/or modify + - it under the terms of the GNU Affero General Public License as + - published by the Free Software Foundation, either version 3 of the + - License, or (at your option) any later version. + - + - This program is distributed in the hope that it will be useful, + - but WITHOUT ANY WARRANTY; without even the implied warranty of + - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + - GNU Affero General Public License for more details. + - + - You should have received a copy of the GNU Affero General Public License + - along with this program. If not, see <http://www.gnu.org/licenses/>. + - + --> +<template> + <a :href="resourceUrl || '#'" + class="unified-search__result" + :class="{ + 'unified-search__result--focused': focused, + }" + @click="reEmitEvent" + @focus="reEmitEvent"> + + <!-- Icon describing the result --> + <div class="unified-search__result-icon" + :class="{ + 'unified-search__result-icon--rounded': rounded, + 'unified-search__result-icon--no-preview': !hasValidThumbnail && !loaded, + 'unified-search__result-icon--with-thumbnail': hasValidThumbnail && loaded, + [icon]: !loaded && !isIconUrl, + }" + :style="{ + backgroundImage: isIconUrl ? `url(${icon})` : '', + }"> + + <img v-if="hasValidThumbnail" + v-show="loaded" + :src="thumbnailUrl" + alt="" + @error="onError" + @load="onLoad"> + </div> + + <!-- Title and sub-title --> + <span class="unified-search__result-content"> + <span class="unified-search__result-line-one" :title="title"> + <NcHighlight :text="title" :search="query" /> + </span> + <span v-if="subline" class="unified-search__result-line-two" :title="subline">{{ subline }}</span> + </span> + </a> +</template> + +<script> +import NcHighlight from '@nextcloud/vue/dist/Components/NcHighlight.js' + +export default { + name: 'LegacySearchResult', + + components: { + NcHighlight, + }, + + props: { + thumbnailUrl: { + type: String, + default: null, + }, + title: { + type: String, + required: true, + }, + subline: { + type: String, + default: null, + }, + resourceUrl: { + type: String, + default: null, + }, + icon: { + type: String, + default: '', + }, + rounded: { + type: Boolean, + default: false, + }, + query: { + type: String, + default: '', + }, + + /** + * Only used for the first result as a visual feedback + * so we can keep the search input focused but pressing + * enter still opens the first result + */ + focused: { + type: Boolean, + default: false, + }, + }, + + data() { + return { + hasValidThumbnail: this.thumbnailUrl && this.thumbnailUrl.trim() !== '', + loaded: false, + } + }, + + computed: { + isIconUrl() { + // If we're facing an absolute url + if (this.icon.startsWith('/')) { + return true + } + + // Otherwise, let's check if this is a valid url + try { + // eslint-disable-next-line no-new + new URL(this.icon) + } catch { + return false + } + return true + }, + }, + + watch: { + // Make sure to reset state on change even when vue recycle the component + thumbnailUrl() { + this.hasValidThumbnail = this.thumbnailUrl && this.thumbnailUrl.trim() !== '' + this.loaded = false + }, + }, + + methods: { + reEmitEvent(e) { + this.$emit(e.type, e) + }, + + /** + * If the image fails to load, fallback to iconClass + */ + onError() { + this.hasValidThumbnail = false + }, + + onLoad() { + this.loaded = true + }, + }, +} +</script> + +<style lang="scss" scoped> +@use "sass:math"; + +$clickable-area: 44px; +$margin: 10px; + +.unified-search__result { + display: flex; + align-items: center; + height: $clickable-area; + padding: $margin; + border: 2px solid transparent; + border-radius: var(--border-radius-large) !important; + + &--focused { + background-color: var(--color-background-hover); + } + + &:active, + &:hover, + &:focus { + background-color: var(--color-background-hover); + border: 2px solid var(--color-border-maxcontrast); + } + + * { + cursor: pointer; + } + + &-icon { + overflow: hidden; + width: $clickable-area; + height: $clickable-area; + border-radius: var(--border-radius); + background-repeat: no-repeat; + background-position: center center; + background-size: 32px; + &--rounded { + border-radius: math.div($clickable-area, 2); + } + &--no-preview { + background-size: 32px; + } + &--with-thumbnail { + background-size: cover; + } + &--with-thumbnail:not(&--rounded) { + // compensate for border + max-width: $clickable-area - 2px; + max-height: $clickable-area - 2px; + border: 1px solid var(--color-border); + } + + img { + // Make sure to keep ratio + width: 100%; + height: 100%; + + object-fit: cover; + object-position: center; + } + } + + &-icon, + &-actions { + flex: 0 0 $clickable-area; + } + + &-content { + display: flex; + align-items: center; + flex: 1 1 100%; + flex-wrap: wrap; + // Set to minimum and gro from it + min-width: 0; + padding-left: $margin; + } + + &-line-one, + &-line-two { + overflow: hidden; + flex: 1 1 100%; + margin: 1px 0; + white-space: nowrap; + text-overflow: ellipsis; + // Use the same color as the `a` + color: inherit; + font-size: inherit; + } + &-line-two { + opacity: .7; + font-size: var(--default-font-size); + } +} + +</style> diff --git a/core/src/components/GlobalSearch/SearchFilterChip.vue b/core/src/components/UnifiedSearch/SearchFilterChip.vue index 8342e9e256d..8342e9e256d 100644 --- a/core/src/components/GlobalSearch/SearchFilterChip.vue +++ b/core/src/components/UnifiedSearch/SearchFilterChip.vue diff --git a/core/src/components/UnifiedSearch/SearchResult.vue b/core/src/components/UnifiedSearch/SearchResult.vue index 03496fc5d92..a746a5751b7 100644 --- a/core/src/components/UnifiedSearch/SearchResult.vue +++ b/core/src/components/UnifiedSearch/SearchResult.vue @@ -1,73 +1,40 @@ - <!-- - - @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com> - - - - @author John Molakvoæ <skjnldsv@protonmail.com> - - - - @license GNU AGPL version 3 or any later version - - - - This program is free software: you can redistribute it and/or modify - - it under the terms of the GNU Affero General Public License as - - published by the Free Software Foundation, either version 3 of the - - License, or (at your option) any later version. - - - - This program is distributed in the hope that it will be useful, - - but WITHOUT ANY WARRANTY; without even the implied warranty of - - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - - GNU Affero General Public License for more details. - - - - You should have received a copy of the GNU Affero General Public License - - along with this program. If not, see <http://www.gnu.org/licenses/>. - - - --> <template> - <a :href="resourceUrl || '#'" - class="unified-search__result" - :class="{ - 'unified-search__result--focused': focused, - }" - @click="reEmitEvent" - @focus="reEmitEvent"> - - <!-- Icon describing the result --> - <div class="unified-search__result-icon" - :class="{ - 'unified-search__result-icon--rounded': rounded, - 'unified-search__result-icon--no-preview': !hasValidThumbnail && !loaded, - 'unified-search__result-icon--with-thumbnail': hasValidThumbnail && loaded, - [icon]: !loaded && !isIconUrl, - }" - :style="{ - backgroundImage: isIconUrl ? `url(${icon})` : '', - }"> - - <img v-if="hasValidThumbnail" - v-show="loaded" - :src="thumbnailUrl" - alt="" - @error="onError" - @load="onLoad"> - </div> - - <!-- Title and sub-title --> - <span class="unified-search__result-content"> - <span class="unified-search__result-line-one" :title="title"> - <NcHighlight :text="title" :search="query" /> - </span> - <span v-if="subline" class="unified-search__result-line-two" :title="subline">{{ subline }}</span> - </span> - </a> + <NcListItem class="result-items__item" + :name="title" + :bold="false" + :href="resourceUrl" + target="_self"> + <template #icon> + <div aria-hidden="true" + class="result-items__item-icon" + :class="{ + 'result-items__item-icon--rounded': rounded, + 'result-items__item-icon--no-preview': !isValidIconOrPreviewUrl(thumbnailUrl), + 'result-items__item-icon--with-thumbnail': isValidIconOrPreviewUrl(thumbnailUrl), + [icon]: !isValidIconOrPreviewUrl(icon), + }" + :style="{ + backgroundImage: isValidIconOrPreviewUrl(icon) ? `url(${icon})` : '', + }"> + <img v-if="isValidIconOrPreviewUrl(thumbnailUrl) && !thumbnailHasError" + :src="thumbnailUrl" + @error="thumbnailErrorHandler"> + </div> + </template> + <template #subname> + {{ subline }} + </template> + </NcListItem> </template> <script> -import NcHighlight from '@nextcloud/vue/dist/Components/NcHighlight.js' +import NcListItem from '@nextcloud/vue/dist/Components/NcListItem.js' export default { name: 'SearchResult', - components: { - NcHighlight, + NcListItem, }, - props: { thumbnailUrl: { type: String, @@ -108,54 +75,22 @@ export default { default: false, }, }, - data() { return { - hasValidThumbnail: this.thumbnailUrl && this.thumbnailUrl.trim() !== '', - loaded: false, + thumbnailHasError: false, } }, - - computed: { - isIconUrl() { - // If we're facing an absolute url - if (this.icon.startsWith('/')) { - return true - } - - // Otherwise, let's check if this is a valid url - try { - // eslint-disable-next-line no-new - new URL(this.icon) - } catch { - return false - } - return true - }, - }, - watch: { - // Make sure to reset state on change even when vue recycle the component thumbnailUrl() { - this.hasValidThumbnail = this.thumbnailUrl && this.thumbnailUrl.trim() !== '' - this.loaded = false + this.thumbnailHasError = false }, }, - methods: { - reEmitEvent(e) { - this.$emit(e.type, e) - }, - - /** - * If the image fails to load, fallback to iconClass - */ - onError() { - this.hasValidThumbnail = false + isValidIconOrPreviewUrl(url) { + return /^https?:\/\//.test(url) || url.startsWith('/') }, - - onLoad() { - this.loaded = true + thumbnailErrorHandler() { + this.thumbnailHasError = true }, }, } @@ -163,97 +98,72 @@ export default { <style lang="scss" scoped> @use "sass:math"; - $clickable-area: 44px; $margin: 10px; -.unified-search__result { - display: flex; - align-items: center; - height: $clickable-area; - padding: $margin; - border: 2px solid transparent; - border-radius: var(--border-radius-large) !important; - - &--focused { - background-color: var(--color-background-hover); - } - - &:active, - &:hover, - &:focus { - background-color: var(--color-background-hover); - border: 2px solid var(--color-border-maxcontrast); - } - - * { - cursor: pointer; - } - - &-icon { - overflow: hidden; - width: $clickable-area; - height: $clickable-area; - border-radius: var(--border-radius); - background-repeat: no-repeat; - background-position: center center; - background-size: 32px; - &--rounded { - border-radius: math.div($clickable-area, 2); - } - &--no-preview { - background-size: 32px; - } - &--with-thumbnail { - background-size: cover; - } - &--with-thumbnail:not(&--rounded) { - // compensate for border - max-width: $clickable-area - 2px; - max-height: $clickable-area - 2px; - border: 1px solid var(--color-border); - } - - img { - // Make sure to keep ratio - width: 100%; - height: 100%; - - object-fit: cover; - object-position: center; - } - } - - &-icon, - &-actions { - flex: 0 0 $clickable-area; - } - - &-content { - display: flex; - align-items: center; - flex: 1 1 100%; - flex-wrap: wrap; - // Set to minimum and gro from it - min-width: 0; - padding-left: $margin; - } - - &-line-one, - &-line-two { - overflow: hidden; - flex: 1 1 100%; - margin: 1px 0; - white-space: nowrap; - text-overflow: ellipsis; - // Use the same color as the `a` - color: inherit; - font-size: inherit; - } - &-line-two { - opacity: .7; - font-size: var(--default-font-size); - } +.result-items { + &__item { + + ::v-deep a { + border-radius: 12px; + border: 2px solid transparent; + border-radius: var(--border-radius-large) !important; + + &--focused { + background-color: var(--color-background-hover); + } + + &:active, + &:hover, + &:focus { + background-color: var(--color-background-hover); + border: 2px solid var(--color-border-maxcontrast); + } + + * { + cursor: pointer; + } + + } + + &-icon { + overflow: hidden; + width: $clickable-area; + height: $clickable-area; + border-radius: var(--border-radius); + background-repeat: no-repeat; + background-position: center center; + background-size: 32px; + + &--rounded { + border-radius: math.div($clickable-area, 2); + } + + &--no-preview { + background-size: 32px; + } + + &--with-thumbnail { + background-size: cover; + } + + &--with-thumbnail:not(&--rounded) { + // compensate for border + max-width: $clickable-area - 2px; + max-height: $clickable-area - 2px; + border: 1px solid var(--color-border); + } + + img { + // Make sure to keep ratio + width: 100%; + height: 100%; + + object-fit: cover; + object-position: center; + } + } + + } } - </style> diff --git a/core/src/components/GlobalSearch/SearchableList.vue b/core/src/components/UnifiedSearch/SearchableList.vue index 43f7ace1b64..43f7ace1b64 100644 --- a/core/src/components/GlobalSearch/SearchableList.vue +++ b/core/src/components/UnifiedSearch/SearchableList.vue |