Skip to content
Snippets Groups Projects
SearchBar.vue 7.73 KiB
Newer Older
  • Learn to ignore specific revisions
  • <template>
      <div class="ui fluid category search">
    
    Georg Krause's avatar
    Georg Krause committed
        <slot /><div class="ui icon input">
          <input
            ref="search"
            :aria-label="labels.searchContent"
            type="search"
            class="prompt"
            name="search"
            :placeholder="labels.placeholder"
            @keydown.esc="$event.target.blur()"
          >
          <i class="search icon" />
    
    Georg Krause's avatar
    Georg Krause committed
        <div class="results" />
        <slot name="after" />
    
        <GlobalEvents
          @keydown.shift.f.prevent.exact="focusSearch"
        />
    
      </div>
    </template>
    
    <script>
    import jQuery from 'jquery'
    import router from '@/router'
    
    import lodash from '@/lodash'
    
    Ciaran Ainsworth's avatar
    Ciaran Ainsworth committed
    import GlobalEvents from '@/components/utils/global-events.vue'
    
    Georg Krause's avatar
    Georg Krause committed
        GlobalEvents
    
    Eliot Berriot's avatar
    Eliot Berriot committed
      computed: {
        labels () {
          return {
    
            placeholder: this.$pgettext('Sidebar/Search/Input.Placeholder', 'Search for artists, albums, tracks…'),
            searchContent: this.$pgettext('Sidebar/Search/Input.Label', 'Search for content')
    
    Georg Krause's avatar
    Georg Krause committed
        const artistLabel = this.$pgettext('*/*/*/Noun', 'Artist')
        const albumLabel = this.$pgettext('*/*/*', 'Album')
        const trackLabel = this.$pgettext('*/*/*/Noun', 'Track')
        const tagLabel = this.$pgettext('*/*/*/Noun', 'Tag')
        const self = this
        let searchQuery
    
    Georg Krause's avatar
    Georg Krause committed
        jQuery(this.$el).keypress(function (e) {
          if (e.which === 13) {
    
            // Cancel any API search request to backend…
    
    Georg Krause's avatar
    Georg Krause committed
            jQuery(this.$el).search('cancel query')
    
            // Go direct to the artist page…
    
    Georg Krause's avatar
    Georg Krause committed
            router.push(`/search?q=${searchQuery}&type=artists`)
          }
        })
    
        jQuery(this.$el).search({
          type: 'category',
          minCharacters: 3,
    
          showNoResults: true,
          error: {
            noResultsHeader: this.$pgettext('Sidebar/Search/Error', 'No matches found'),
            noResults: this.$pgettext('Sidebar/Search/Error.Label', 'Sorry, there are no results for this search')
          },
    
    Georg Krause's avatar
    Georg Krause committed
            jQuery(self.$el).search('set value', searchQuery)
    
    Georg Krause's avatar
    Georg Krause committed
            jQuery(self.$el).search('hide results')
    
            return false
    
          onSearchQuery (query) {
            self.$emit('search')
    
          apiSettings: {
            beforeXHR: function (xhrObject) {
    
              if (!self.$store.state.auth.authenticated) {
                return xhrObject
              }
    
    
              if (self.$store.state.auth.oauth.accessToken) {
                xhrObject.setRequestHeader('Authorization', self.$store.getters['auth/header'])
              }
    
              return xhrObject
            },
            onResponse: function (initialResponse) {
    
    Georg Krause's avatar
    Georg Krause committed
              const objId = self.extractObjId(searchQuery)
              const results = {}
    
              let isEmptyResults = true
    
    Georg Krause's avatar
    Georg Krause committed
              const categories = [
    
                {
                  code: 'federation',
    
    Georg Krause's avatar
    Georg Krause committed
                  name: self.$pgettext('*/*/*', 'Federation')
    
    Georg Krause's avatar
    Georg Krause committed
                  name: self.$pgettext('*/*/*', 'Podcasts')
    
                  route: 'library.artists.detail',
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                  name: artistLabel,
    
                  getTitle (r) {
                    return r.name
                  },
                  getDescription (r) {
                    return ''
    
                  },
                  getId (t) {
                    return t.id
    
                  route: 'library.albums.detail',
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                  name: albumLabel,
    
                  getTitle (r) {
                    return r.title
                  },
                  getDescription (r) {
    
                  },
                  getId (t) {
                    return t.id
    
                  route: 'library.tracks.detail',
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                  name: trackLabel,
    
                  getTitle (r) {
                    return r.title
                  },
                  getDescription (r) {
    
                    if (r.album) {
                      return `${r.album.artist.name} - ${r.album.title}`
                    } else {
                      return r.artist.name
                    }
    
                  },
                  getId (t) {
                    return t.id
                  }
                },
                {
                  code: 'tags',
                  route: 'library.tags.detail',
                  name: tagLabel,
                  getTitle (r) {
    
                  },
                  getDescription (r) {
                    return ''
                  },
                  getId (t) {
                    return t.name
    
    Agate's avatar
    Agate committed
                },
                {
                  code: 'more',
    
    Georg Krause's avatar
    Georg Krause committed
                  name: ''
                }
    
              ]
              categories.forEach(category => {
                results[category.code] = {
                  name: category.name,
                  results: []
                }
    
                if (category.code === 'federation') {
                  if (objId) {
                    isEmptyResults = false
    
    Georg Krause's avatar
    Georg Krause committed
                    const searchMessage = self.$pgettext('Search/*/*', 'Search on the fediverse')
                    results.federation = {
    
                      name: self.$pgettext('*/*/*', 'Federation'),
                      results: [{
                        title: searchMessage,
                        routerUrl: {
                          name: 'search',
                          query: {
    
    Georg Krause's avatar
    Georg Krause committed
                            id: objId
    
    Georg Krause's avatar
    Georg Krause committed
                } else if (category.code === 'podcasts') {
    
                  if (objId) {
                    isEmptyResults = false
    
    Georg Krause's avatar
    Georg Krause committed
                    const searchMessage = self.$pgettext('Search/*/*', 'Subscribe to podcast via RSS')
                    results.podcasts = {
    
                      name: self.$pgettext('*/*/*', 'Podcasts'),
                      results: [{
                        title: searchMessage,
                        routerUrl: {
                          name: 'search',
                          query: {
                            id: objId,
    
    Georg Krause's avatar
    Georg Krause committed
                            type: 'rss'
    
    Georg Krause's avatar
    Georg Krause committed
                } else if (category.code === 'more') {
                  const searchMessage = self.$pgettext('Search/*/*', 'More results 🡒')
                  results.more = {
    
    Agate's avatar
    Agate committed
                    name: '',
                    results: [{
                      title: searchMessage,
                      routerUrl: {
                        name: 'search',
                        query: {
    
    Georg Krause's avatar
    Georg Krause committed
                          type: 'artists',
    
    Agate's avatar
    Agate committed
                          q: searchQuery
                        }
                      }
                    }]
                  }
    
    Georg Krause's avatar
    Georg Krause committed
                } else {
    
                  initialResponse[category.code].forEach(result => {
                    isEmptyResults = false
    
    Georg Krause's avatar
    Georg Krause committed
                    const id = category.getId(result)
    
                    results[category.code].results.push({
                      title: category.getTitle(result),
                      id,
                      routerUrl: {
                        name: category.route,
                        params: {
                          id
                        }
                      },
                      description: category.getDescription(result)
                    })
    
                results: isEmptyResults ? {} : results
              }
    
            url: this.$store.getters['instance/absoluteUrl']('api/v1/search?query={query}')
    
      },
      methods: {
        focusSearch () {
          this.$refs.search.focus()
        },
    
        extractObjId (query) {
          query = lodash.trim(query)
          query = lodash.trim(query, '@')
          if (query.indexOf(' ') > -1) {
            return
          }
          if (query.startsWith('http://') || query.startsWith('https://')) {
            return query
          }
          if (query.split('@').length > 1) {
            return query
          }
        }