Browse Source

feat: search i18n + ux improvements

NGPixel 1 year ago
parent
commit
17034040ac
4 changed files with 68 additions and 28 deletions
  1. 13 0
      server/locales/en.json
  2. 2 1
      ux/src/components/HeaderNav.vue
  3. 17 0
      ux/src/css/animation.scss
  4. 36 27
      ux/src/pages/Search.vue

+ 13 - 0
server/locales/en.json

@@ -1757,13 +1757,26 @@
   "profile.title": "Profile",
   "profile.title": "Profile",
   "profile.uploadNewAvatar": "Upload New Image",
   "profile.uploadNewAvatar": "Upload New Image",
   "profile.viewPublicProfile": "View Public Profile",
   "profile.viewPublicProfile": "View Public Profile",
+  "search.editorAny": "Any editor",
+  "search.emptyQuery": "Enter a query in the search field above and press Enter.",
+  "search.filterEditor": "Editor",
+  "search.filterLocale": "Locale(s)",
   "search.filterLocaleDisplay": "Any locale | {n} locale only | {count} locales selected",
   "search.filterLocaleDisplay": "Any locale | {n} locale only | {count} locales selected",
+  "search.filterPath": "Path starting with...",
+  "search.filterPublishState": "Publish State",
+  "search.filterTags": "Tags",
   "search.filters": "Filters",
   "search.filters": "Filters",
+  "search.noResults": "No results found for {0} with the current filters.",
+  "search.publishStateAny": "Any publish state",
+  "search.publishStateDraft": "Draft",
+  "search.publishStatePublished": "Published",
+  "search.publishStateScheduled": "Scheduled",
   "search.results": "Search Results",
   "search.results": "Search Results",
   "search.sortBy": "Sort By",
   "search.sortBy": "Sort By",
   "search.sortByLastUpdated": "Last Updated",
   "search.sortByLastUpdated": "Last Updated",
   "search.sortByRelevance": "Relevance",
   "search.sortByRelevance": "Relevance",
   "search.sortByTitle": "Title",
   "search.sortByTitle": "Title",
+  "search.totalResults": "No result | {0} result | {0} results",
   "tags.clearSelection": "Clear Selection",
   "tags.clearSelection": "Clear Selection",
   "tags.currentSelection": "Current Selection",
   "tags.currentSelection": "Current Selection",
   "tags.locale": "Locale",
   "tags.locale": "Locale",

+ 2 - 1
ux/src/components/HeaderNav.vue

@@ -44,7 +44,8 @@ q-header.bg-header.text-white.site-header(
         )
         )
         template(v-slot:prepend)
         template(v-slot:prepend)
           q-circular-progress.q-mr-xs(
           q-circular-progress.q-mr-xs(
-            v-if='siteStore.searchIsLoading'
+            v-if='siteStore.searchIsLoading && route.path !== `/_search`'
+            instant-feedback
             indeterminate
             indeterminate
             rounded
             rounded
             color='primary'
             color='primary'

+ 17 - 0
ux/src/css/animation.scss

@@ -37,6 +37,23 @@
   opacity: 0
   opacity: 0
 }
 }
 
 
+// -> Slide Up Transition
+
+.slide-up-enter-active,
+.slide-up-leave-active {
+  transition: all 0.25s ease-out;
+}
+
+.slide-up-enter-from {
+  opacity: 0;
+  transform: translateY(15px);
+}
+
+.slide-up-leave-to {
+  opacity: 0;
+  transform: translateY(-15px);
+}
+
 // -> fadeIn
 // -> fadeIn
 
 
 @keyframes fadeIn {
 @keyframes fadeIn {

+ 36 - 27
ux/src/pages/Search.vue

@@ -30,7 +30,7 @@ q-layout(view='hHh Lpr lff')
           q-input(
           q-input(
             outlined
             outlined
             dense
             dense
-            placeholder='Path starting with...'
+            :placeholder='t(`search.filterPath`)'
             prefix='/'
             prefix='/'
             v-model='state.params.filterPath'
             v-model='state.params.filterPath'
             )
             )
@@ -39,31 +39,31 @@ q-layout(view='hHh Lpr lff')
           q-input.q-mt-sm(
           q-input.q-mt-sm(
             outlined
             outlined
             dense
             dense
-            placeholder='Tags'
+            :placeholder='t(`search.filterTags`)'
             )
             )
             template(v-slot:prepend)
             template(v-slot:prepend)
               q-icon(name='las la-hashtag', size='xs')
               q-icon(name='las la-hashtag', size='xs')
-          q-input.q-mt-sm(
-            outlined
-            dense
-            placeholder='Last updated...'
-            )
-            template(v-slot:prepend)
-              q-icon(name='las la-calendar', size='xs')
-          q-input.q-mt-sm(
-            outlined
-            dense
-            placeholder='Last edited by...'
-            )
-            template(v-slot:prepend)
-              q-icon(name='las la-user-edit', size='xs')
+          //- q-input.q-mt-sm(
+          //-   outlined
+          //-   dense
+          //-   placeholder='Last updated...'
+          //-   )
+          //-   template(v-slot:prepend)
+          //-     q-icon(name='las la-calendar', size='xs')
+          //- q-input.q-mt-sm(
+          //-   outlined
+          //-   dense
+          //-   placeholder='Last edited by...'
+          //-   )
+          //-   template(v-slot:prepend)
+          //-     q-icon(name='las la-user-edit', size='xs')
           q-select.q-mt-sm(
           q-select.q-mt-sm(
             outlined
             outlined
             v-model='state.params.filterLocale'
             v-model='state.params.filterLocale'
             emit-value
             emit-value
             map-options
             map-options
             dense
             dense
-            :aria-label='t(`admin.groups.ruleLocales`)'
+            :aria-label='t(`search.filterLocale`)'
             :options='siteStore.locales.active'
             :options='siteStore.locales.active'
             option-value='code'
             option-value='code'
             option-label='name'
             option-label='name'
@@ -85,7 +85,7 @@ q-layout(view='hHh Lpr lff')
             emit-value
             emit-value
             map-options
             map-options
             dense
             dense
-            aria-label='Editor'
+            :aria-label='t(`search.filterEditor`)'
             :options='editors'
             :options='editors'
             )
             )
             template(v-slot:prepend)
             template(v-slot:prepend)
@@ -96,7 +96,7 @@ q-layout(view='hHh Lpr lff')
             emit-value
             emit-value
             map-options
             map-options
             dense
             dense
-            aria-label='Publish State'
+            :aria-label='t(`search.filterPublishState`)'
             :options='publishStates'
             :options='publishStates'
             )
             )
             template(v-slot:prepend)
             template(v-slot:prepend)
@@ -105,10 +105,19 @@ q-layout(view='hHh Lpr lff')
         .text-header.flex
         .text-header.flex
           span {{t('search.results')}}
           span {{t('search.results')}}
           q-space
           q-space
-          span.text-caption #[strong {{ state.total }}] results
+          transition(name='slide-up', mode='out-in')
+            i18n-t(
+              v-if='!siteStore.searchIsLoading'
+              keypath='search.totalResults'
+              tag='span'
+              class='text-caption'
+              :plural='state.total'
+              )
+              strong {{ state.total }}
         .q-pa-lg(v-if='state.results.length < 1')
         .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.
+          i18n-t(keypath='search.noResults', tag='span', v-if='siteStore.search && siteStore.searchLastQuery')
+            strong {{ siteStore.searchLastQuery }}
+          span(v-else): em {{ t('search.emptyQuery') }}
         q-list(separator)
         q-list(separator)
           q-item(
           q-item(
             v-for='item of state.results'
             v-for='item of state.results'
@@ -209,7 +218,7 @@ const orderByOptions = computed(() => {
 
 
 const editors = computed(() => {
 const editors = computed(() => {
   return [
   return [
-    { label: 'Any editor', value: '' },
+    { label: t('search.editorAny'), value: '' },
     { label: 'AsciiDoc', value: 'asciidoc' },
     { label: 'AsciiDoc', value: 'asciidoc' },
     { label: 'Markdown', value: 'markdown' },
     { label: 'Markdown', value: 'markdown' },
     { label: 'Visual Editor', value: 'wysiwyg' }
     { label: 'Visual Editor', value: 'wysiwyg' }
@@ -218,10 +227,10 @@ const editors = computed(() => {
 
 
 const publishStates = computed(() => {
 const publishStates = computed(() => {
   return [
   return [
-    { label: 'Any publish state', value: '' },
-    { label: 'Draft', value: 'draft' },
-    { label: 'Published', value: 'published' },
-    { label: 'Scheduled', value: 'scheduled' }
+    { label: t('search.publishStateAny'), value: '' },
+    { label: t('search.publishStateDraft'), value: 'draft' },
+    { label: t('search.publishStatePublished'), value: 'published' },
+    { label: t('search.publishStateScheduled'), value: 'scheduled' }
   ]
   ]
 })
 })