|
@@ -6,21 +6,25 @@ q-layout(view='hHh Lpr lff')
|
|
.layout-search-sd
|
|
.layout-search-sd
|
|
.text-header {{ t('search.sortBy') }}
|
|
.text-header {{ t('search.sortBy') }}
|
|
q-list(dense, padding)
|
|
q-list(dense, padding)
|
|
- q-item(clickable, active)
|
|
|
|
|
|
+ q-item(
|
|
|
|
+ v-for='item of orderByOptions'
|
|
|
|
+ clickable
|
|
|
|
+ :active='item.value === state.params.orderBy'
|
|
|
|
+ @click='setOrderBy(item.value)'
|
|
|
|
+ )
|
|
q-item-section(side)
|
|
q-item-section(side)
|
|
- q-icon(name='las la-stream', color='primary')
|
|
|
|
|
|
+ q-icon(:name='item.icon', :color='item.value === state.params.orderBy ? `primary` : ``')
|
|
q-item-section
|
|
q-item-section
|
|
- q-item-label Relevance
|
|
|
|
- q-item-section(side)
|
|
|
|
- q-icon(name='mdi-chevron-double-down', size='sm', color='primary')
|
|
|
|
- q-item(clickable)
|
|
|
|
- q-item-section(side)
|
|
|
|
- q-icon(name='las la-heading')
|
|
|
|
- q-item-section Title
|
|
|
|
- q-item(clickable)
|
|
|
|
- q-item-section(side)
|
|
|
|
- q-icon(name='las la-calendar')
|
|
|
|
- q-item-section Last Updated
|
|
|
|
|
|
+ q-item-label {{ item.label }}
|
|
|
|
+ q-item-section(
|
|
|
|
+ v-if='item.value === state.params.orderBy'
|
|
|
|
+ side
|
|
|
|
+ )
|
|
|
|
+ q-icon(
|
|
|
|
+ :name='state.params.orderByDirection === `desc` ? `mdi-chevron-double-down` : `mdi-chevron-double-up`'
|
|
|
|
+ size='sm'
|
|
|
|
+ color='primary'
|
|
|
|
+ )
|
|
.text-header {{ t('search.filters') }}
|
|
.text-header {{ t('search.filters') }}
|
|
.q-pa-sm
|
|
.q-pa-sm
|
|
q-input(
|
|
q-input(
|
|
@@ -28,7 +32,7 @@ q-layout(view='hHh Lpr lff')
|
|
dense
|
|
dense
|
|
placeholder='Path starting with...'
|
|
placeholder='Path starting with...'
|
|
prefix='/'
|
|
prefix='/'
|
|
- v-model='state.filterPath'
|
|
|
|
|
|
+ v-model='state.params.filterPath'
|
|
)
|
|
)
|
|
template(v-slot:prepend)
|
|
template(v-slot:prepend)
|
|
q-icon(name='las la-caret-square-right', size='xs')
|
|
q-icon(name='las la-caret-square-right', size='xs')
|
|
@@ -55,7 +59,7 @@ q-layout(view='hHh Lpr lff')
|
|
q-icon(name='las la-user-edit', size='xs')
|
|
q-icon(name='las la-user-edit', size='xs')
|
|
q-select.q-mt-sm(
|
|
q-select.q-mt-sm(
|
|
outlined
|
|
outlined
|
|
- v-model='state.filterLocale'
|
|
|
|
|
|
+ v-model='state.params.filterLocale'
|
|
emit-value
|
|
emit-value
|
|
map-options
|
|
map-options
|
|
dense
|
|
dense
|
|
@@ -63,14 +67,21 @@ q-layout(view='hHh Lpr lff')
|
|
:options='siteStore.locales.active'
|
|
:options='siteStore.locales.active'
|
|
option-value='code'
|
|
option-value='code'
|
|
option-label='name'
|
|
option-label='name'
|
|
|
|
+ options-dense
|
|
multiple
|
|
multiple
|
|
- :display-value='t(`admin.groups.selectedLocales`, { n: state.filterLocale.length > 0 ? state.filterLocale[0].toUpperCase() : state.filterLocale.length }, state.filterLocale.length)'
|
|
|
|
|
|
+ :display-value='t(`search.filterLocaleDisplay`, { n: state.params.filterLocale.length > 0 ? state.params.filterLocale[0].toUpperCase() : state.params.filterLocale.length }, state.params.filterLocale.length)'
|
|
)
|
|
)
|
|
template(v-slot:prepend)
|
|
template(v-slot:prepend)
|
|
q-icon(name='las la-language', size='xs')
|
|
q-icon(name='las la-language', size='xs')
|
|
|
|
+ template(v-slot:option='scope')
|
|
|
|
+ q-item(v-bind='scope.itemProps')
|
|
|
|
+ q-item-section(side)
|
|
|
|
+ q-checkbox(:model-value='scope.selected', @update:model-value='scope.toggleOption(scope.opt)')
|
|
|
|
+ q-item-section
|
|
|
|
+ q-item-label(v-html='scope.opt.name')
|
|
q-select.q-mt-sm(
|
|
q-select.q-mt-sm(
|
|
outlined
|
|
outlined
|
|
- v-model='state.filterEditor'
|
|
|
|
|
|
+ v-model='state.params.filterEditor'
|
|
emit-value
|
|
emit-value
|
|
map-options
|
|
map-options
|
|
dense
|
|
dense
|
|
@@ -81,7 +92,7 @@ q-layout(view='hHh Lpr lff')
|
|
q-icon(name='las la-pen-nib', size='xs')
|
|
q-icon(name='las la-pen-nib', size='xs')
|
|
q-select.q-mt-sm(
|
|
q-select.q-mt-sm(
|
|
outlined
|
|
outlined
|
|
- v-model='state.filterPublishState'
|
|
|
|
|
|
+ v-model='state.params.filterPublishState'
|
|
emit-value
|
|
emit-value
|
|
map-options
|
|
map-options
|
|
dense
|
|
dense
|
|
@@ -95,6 +106,9 @@ q-layout(view='hHh Lpr lff')
|
|
span {{t('search.results')}}
|
|
span {{t('search.results')}}
|
|
q-space
|
|
q-space
|
|
span.text-caption #[strong {{ state.total }}] results
|
|
span.text-caption #[strong {{ state.total }}] results
|
|
|
|
+ .q-pa-lg(v-if='state.results.length < 1')
|
|
|
|
+ span(v-if='siteStore.search && siteStore.searchLastQuery') No results found for #[strong "{{ siteStore.searchLastQuery }}"] with the current filters.
|
|
|
|
+ span(v-else): em Enter a query in the search field above and press Enter.
|
|
q-list(separator)
|
|
q-list(separator)
|
|
q-item(
|
|
q-item(
|
|
v-for='item of state.results'
|
|
v-for='item of state.results'
|
|
@@ -105,8 +119,8 @@ q-layout(view='hHh Lpr lff')
|
|
q-avatar(color='primary' text-color='white' rounded :icon='item.icon')
|
|
q-avatar(color='primary' text-color='white' rounded :icon='item.icon')
|
|
q-item-section
|
|
q-item-section
|
|
q-item-label {{ item.title }}
|
|
q-item-label {{ item.title }}
|
|
- q-item-label(caption) {{ item.description }}
|
|
|
|
- q-item-label.text-highlight(caption, v-html='item.highlight')
|
|
|
|
|
|
+ q-item-label(v-if='item.description', caption) {{ item.description }}
|
|
|
|
+ q-item-label.text-highlight(v-if='item.highlight', caption, v-html='item.highlight')
|
|
q-item-section(side)
|
|
q-item-section(side)
|
|
.flex
|
|
.flex
|
|
q-chip(
|
|
q-chip(
|
|
@@ -129,10 +143,10 @@ q-layout(view='hHh Lpr lff')
|
|
<script setup>
|
|
<script setup>
|
|
import { useI18n } from 'vue-i18n'
|
|
import { useI18n } from 'vue-i18n'
|
|
import { useMeta, useQuasar } from 'quasar'
|
|
import { useMeta, useQuasar } from 'quasar'
|
|
-import { computed, onMounted, reactive, watch } from 'vue'
|
|
|
|
|
|
+import { computed, onMounted, onUnmounted, reactive, watch } from 'vue'
|
|
import { useRouter, useRoute } from 'vue-router'
|
|
import { useRouter, useRoute } from 'vue-router'
|
|
import gql from 'graphql-tag'
|
|
import gql from 'graphql-tag'
|
|
-import { cloneDeep } from 'lodash-es'
|
|
|
|
|
|
+import { cloneDeep, debounce } from 'lodash-es'
|
|
import { DateTime } from 'luxon'
|
|
import { DateTime } from 'luxon'
|
|
|
|
|
|
import { useFlagsStore } from 'src/stores/flags'
|
|
import { useFlagsStore } from 'src/stores/flags'
|
|
@@ -172,15 +186,27 @@ useMeta({
|
|
|
|
|
|
const state = reactive({
|
|
const state = reactive({
|
|
loading: 0,
|
|
loading: 0,
|
|
- filterPath: '',
|
|
|
|
- filterTags: [],
|
|
|
|
- filterLocale: ['en'],
|
|
|
|
- filterEditor: '',
|
|
|
|
- filterPublishState: '',
|
|
|
|
|
|
+ params: {
|
|
|
|
+ filterPath: '',
|
|
|
|
+ filterTags: [],
|
|
|
|
+ filterLocale: [],
|
|
|
|
+ filterEditor: '',
|
|
|
|
+ filterPublishState: '',
|
|
|
|
+ orderBy: 'relevancy',
|
|
|
|
+ orderByDirection: 'desc'
|
|
|
|
+ },
|
|
results: [],
|
|
results: [],
|
|
total: 0
|
|
total: 0
|
|
})
|
|
})
|
|
|
|
|
|
|
|
+const orderByOptions = computed(() => {
|
|
|
|
+ return [
|
|
|
|
+ { label: t('search.sortByRelevance'), value: 'relevancy', icon: 'las la-stream' },
|
|
|
|
+ { label: t('search.sortByTitle'), value: 'title', icon: 'las la-heading' },
|
|
|
|
+ { label: t('search.sortByLastUpdated'), value: 'updatedAt', icon: 'las la-calendar' }
|
|
|
|
+ ]
|
|
|
|
+})
|
|
|
|
+
|
|
const editors = computed(() => {
|
|
const editors = computed(() => {
|
|
return [
|
|
return [
|
|
{ label: 'Any editor', value: '' },
|
|
{ label: 'Any editor', value: '' },
|
|
@@ -208,6 +234,8 @@ watch(() => route.query, async (newQueryObj) => {
|
|
}
|
|
}
|
|
}, { immediate: true })
|
|
}, { immediate: true })
|
|
|
|
|
|
|
|
+watch(() => state.params, debounce(performSearch, 500), { deep: true })
|
|
|
|
+
|
|
// METHODS
|
|
// METHODS
|
|
|
|
|
|
function pageStyle (offset, height) {
|
|
function pageStyle (offset, height) {
|
|
@@ -220,6 +248,15 @@ function humanizeDate (val) {
|
|
return DateTime.fromISO(val).toFormat(userStore.preferredDateFormat)
|
|
return DateTime.fromISO(val).toFormat(userStore.preferredDateFormat)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+function setOrderBy (val) {
|
|
|
|
+ if (val === state.params.orderBy) {
|
|
|
|
+ state.params.orderByDirection = state.params.orderByDirection === 'desc' ? 'asc' : 'desc'
|
|
|
|
+ } else {
|
|
|
|
+ state.params.orderBy = val
|
|
|
|
+ state.params.orderByDirection = val === 'title' ? 'asc' : 'desc'
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
async function performSearch () {
|
|
async function performSearch () {
|
|
siteStore.searchIsLoading = true
|
|
siteStore.searchIsLoading = true
|
|
try {
|
|
try {
|
|
@@ -268,7 +305,13 @@ async function performSearch () {
|
|
`,
|
|
`,
|
|
variables: {
|
|
variables: {
|
|
siteId: siteStore.id,
|
|
siteId: siteStore.id,
|
|
- query: siteStore.search
|
|
|
|
|
|
+ query: siteStore.search,
|
|
|
|
+ path: state.params.filterPath,
|
|
|
|
+ locale: state.params.filterLocale,
|
|
|
|
+ editor: state.params.filterEditor,
|
|
|
|
+ publishState: state.params.filterPublishState || null,
|
|
|
|
+ orderBy: state.params.orderBy,
|
|
|
|
+ orderByDirection: state.params.orderByDirection
|
|
},
|
|
},
|
|
fetchPolicy: 'network-only'
|
|
fetchPolicy: 'network-only'
|
|
})
|
|
})
|
|
@@ -277,6 +320,7 @@ async function performSearch () {
|
|
}
|
|
}
|
|
state.results = cloneDeep(resp.data.searchPages.results)
|
|
state.results = cloneDeep(resp.data.searchPages.results)
|
|
state.total = resp.data.searchPages.totalHits
|
|
state.total = resp.data.searchPages.totalHits
|
|
|
|
+ siteStore.searchLastQuery = siteStore.search
|
|
} catch (err) {
|
|
} catch (err) {
|
|
$q.notify({
|
|
$q.notify({
|
|
type: 'negative',
|
|
type: 'negative',
|
|
@@ -290,13 +334,17 @@ async function performSearch () {
|
|
// MOUNTED
|
|
// MOUNTED
|
|
|
|
|
|
onMounted(() => {
|
|
onMounted(() => {
|
|
- if (siteStore.search) {
|
|
|
|
- // performSearch()
|
|
|
|
- } else {
|
|
|
|
|
|
+ if (!siteStore.search) {
|
|
siteStore.searchIsLoading = false
|
|
siteStore.searchIsLoading = false
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
|
|
|
|
+onUnmounted(() => {
|
|
|
|
+ siteStore.search = ''
|
|
|
|
+ siteStore.searchLastQuery = ''
|
|
|
|
+ siteStore.searchIsLoading = false
|
|
|
|
+})
|
|
|
|
+
|
|
</script>
|
|
</script>
|
|
|
|
|
|
<style lang="scss">
|
|
<style lang="scss">
|
|
@@ -386,7 +434,6 @@ onMounted(() => {
|
|
|
|
|
|
> b {
|
|
> b {
|
|
background-color: rgba($yellow-7, .5);
|
|
background-color: rgba($yellow-7, .5);
|
|
- padding: 0 3px;
|
|
|
|
border-radius: 3px;
|
|
border-radius: 3px;
|
|
}
|
|
}
|
|
}
|
|
}
|