Skip to content
Snippets Groups Projects
Suggestions.vue 6.11 KiB
Newer Older
  • Learn to ignore specific revisions
  • <template>
      <div>
        <ul class="collection with-header">
          <li class="collection-header">
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            <router-link to="/connect" class="secondary-content">Add another account</router-link>
            <h5>Connected accounts</h5>
    
          </li>
          <li class="collection-item avatar" v-for="account in accounts" :key="account.id">
            <img v-if="account._source.getAvatar(account)" :src="account._source.getAvatar(account)" alt="" class="circle">
            <span class="title">{{ account._source.getDisplayName(account) }}</span>
            <p>{{ account._source.label }}</p>
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            <div v-if="isLoading && results[account.id] && results[account.id].results.isLoading">
              <div class="progress">
                <div v-if="results[account.id].results.progress === 'indeterminate'" :class="indeterminate"></div>
                <div v-else class="determinate" :style="{width: `${results[account.id].results.progress}%`}"></div>
              </div>
              {{ results[account.id].results.status }}
            </div>
            <a @click="fetch(account.id)" class="secondary-content"><i class="material-icons">refresh</i></a>
    
        <h2>
          Suggestions
          <button
            @click="fetch()"
            :class="['waves-effect', 'waves-light', {disabled: isLoading}, 'btn-small']" :disabled="isLoading">
            <i class="material-icons left">refresh</i>Fetch data
          </button>
        </h2>
    
        <div v-if="isLoading" class="progress">
          <div class="indeterminate"></div>
        </div>
    
        <ul class="collection">
          <li class="collection-item avatar" v-for="suggestion in filteredSuggestions" :key="suggestion.fullId">
            <img v-if="suggestion.avatar" :src="suggestion.avatar" alt="" class="circle">
            <a target="_blank" rel="noopener noreferrer" :href="suggestion.url" class="title">{{ suggestion.name }}</a>
            <p>Score: {{ suggestion.weight }}</p>
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            <a v-if="retributeProfiles[suggestion.fullId] === undefined" @click="lookup(suggestion.fullId)" class="secondary-content"><i class="material-icons">search</i></a>
            <div v-else-if="retributeProfiles[suggestion.fullId]">
              <h6>Donation platforms</h6>
              <!-- {{ retributeProfiles[suggestion.fullId] }} -->
              <template v-for="mean in retributeProfiles[suggestion.fullId].means">
                <a
                  :href="mean.url"
                  :key="mean.id"
                  target="_blank"
                  rel="noopener noreferrer"
                  :class="['waves-effect', 'waves-light', 'btn-small']">
                  <span :title="mean.summary">{{ mean.provider }}</span>
                </a>
    
              </template>
            </div>
            <div v-else>No retribute information found for this account</div>
    
          </li>
        </ul>
    
      </div>
    
    </template>
    
    <script>
    import sources from '@/sources'
    
    import orderBy from 'lodash/orderBy'
    
    Eliot Berriot's avatar
    Eliot Berriot committed
    import chunk from 'lodash/chunk'
    import axios from 'axios'
    
    export default {
      data () {
        return {
          isLoading: false,
    
          results: {},
    
    Eliot Berriot's avatar
    Eliot Berriot committed
          aggregatedSuggestions: this.$store.state.cache.aggregatedSuggestions || {},
          retributeProfiles: this.$store.state.cache.retributeProfiles || {},
    
        }
      },
      computed: {
        accounts () {
          return this.$store.getters.sortedAccounts.map((a) => {
            a._source = sources.sources[a.source]
            return a
          })
    
        },
        filteredSuggestions () {
          return orderBy(Object.values(this.aggregatedSuggestions), ['weight', 'id'], ['desc', 'asc'])
        },
    
        aggregateSuggestions (results) {
          const aggregated = {}
          Object.keys(results).forEach((account) => {
            let r = results[account]
            if (!r.results || !r.results.accounts) {
    
            } else {
              Object.keys(r.results.accounts).forEach((key) => {
                if (aggregated[key]) {
                  aggregated[key].weight += r.results.accounts[key].weight
                  aggregated[key].accounts.push(account)
                } else {
                  aggregated[key] = {...r.results.accounts[key], accounts: [account], fullId: key}
                }
              })
            }
          })
          return aggregated
        },
    
    Eliot Berriot's avatar
    Eliot Berriot committed
        async fetch (id) {
          let accounts
          if (id) {
            accounts = this.accounts.filter((a) => {
              return a.id == id
            })
          } else {
            accounts = this.accounts
          }
    
          this.isLoading = true
    
    Eliot Berriot's avatar
    Eliot Berriot committed
          accounts.forEach((a) => {
            let r = {isLoading: true, progress: 'indeterminate', status: ''}
    
            let promise = a._source.fetch({account: a, store: this.$store, results: r, vue: this})
            this.$set(this.results, a.id, {account: a, promise, results: r})
          })
          const keys = Object.keys(this.results)
          for(let i = 0; i < keys.length; i++){
            await this.results[keys[i]].promise
          }
    
    Eliot Berriot's avatar
    Eliot Berriot committed
          await this.lookupAll()
    
          this.isLoading = false
    
    Eliot Berriot's avatar
    Eliot Berriot committed
        },
        async lookupAll () {
          const toLookup = this.filteredSuggestions.filter((s) => {
            return this.retributeProfiles[s.fullId] === undefined
          })
          const chunkSize = 5
          const chunks = chunk(toLookup, chunkSize)
          for (let i = 0; i < chunks.length; i++){
            let chunk = chunks[i]
            let ids = chunk.map((s) => {
              return s.fullId
            })
            await this.lookups(ids)
          }
    
        },
        async lookups(ids) {
          const tasks = ids.map((i) => {
            return this.lookup(i)
          })
          for (let i = 0; i < tasks.length; i++){
            await tasks[i]
          }
    
        },
        async lookup (id) {
          const client = axios.create({timeout: 5000})
          let url = `http://localhost:8000/api/v1/search/${id}`
          try {
            const response = await client.get(url)
            this.$set(this.retributeProfiles, id, response.data)
          } catch {
            this.$set(this.retributeProfiles, id, null)
            return
          }
    
      },
      watch: {
        results: {
          handler (v) {
            this.aggregatedSuggestions = this.aggregateSuggestions(v)
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            this.$store.commit('setRecursiveState', {key: 'cache.aggregatedSuggestions', value: this.aggregatedSuggestions})
    
          },
          deep: true,
    
    Eliot Berriot's avatar
    Eliot Berriot committed
        },
        retributeProfiles: {
          handler (v) {
            this.$store.commit('setRecursiveState', {key: 'cache.retributeProfiles', value: this.retributeProfiles})
          },
          deep: true