SpeciesFileGroup/taxonworks

View on GitHub
app/javascript/vue/tasks/dwc/dashboard/components/Download/DownloadRecent.vue

Summary

Maintainability
Test Coverage
<template>
  <div class="panel content">
    <h2>Recently created DwC Archives</h2>
    <table>
      <thead>
        <tr>
          <th class="w-2" />
          <th
            v-for="header in PROPERTIES"
            :key="header"
          >
            {{ humanize(header) }}
          </th>
          <th>Is public</th>
          <th />
        </tr>
      </thead>
      <tbody>
        <tr
          v-for="(item, index) in store.downloadList"
          :key="item.id"
        >
          <td>
            <RadialNavigator
              :global-id="item.global_id"
              :redirect="false"
              @delete="() => actions.removeDownloadFromList(item)"
            />
          </td>
          <td
            v-for="property in PROPERTIES"
            :key="property"
          >
            {{ item[property] }}
          </td>
          <td>
            <input
              type="checkbox"
              :checked="item.is_public"
              @click="setIsPublic(item, index)"
            />
          </td>
          <td>
            <v-btn
              color="primary"
              medium
              :disabled="!item.ready"
              @click="downloadFile(item.file_url)"
            >
              {{ item.ready ? 'Download' : 'Processing...' }}
            </v-btn>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>
<script setup>
import { inject, onBeforeMount, watch } from 'vue'
import { DOWNLOAD_DWC_ARCHIVE } from '@/constants/index.js'
import { Download } from '@/routes/endpoints'
import { humanize } from '@/helpers/strings'
import RadialNavigator from '@/components/radials/navigation/radial.vue'
import VBtn from '@/components/ui/VBtn/index.vue'

const DEFAULT_WAIT_TIME = 60000
const TIME_BY_RECORDS = {
  1000: 5000,
  10000: 15000,
  100000: 30000
}
const PROPERTIES = [
  'created_at',
  'expires',
  'total_records',
  'times_downloaded'
]

const store = inject('state')
const actions = inject('actions')
const timeoutDownloadIds = []

const refreshDownloadList = (list) => {
  const notReadyList = list.filter(
    (item) => !item.ready && !timeoutDownloadIds.includes(item.id)
  )

  notReadyList.forEach((record) => {
    const timeRequest = getTimeByTotal(record.total_records)

    timeoutDownloadIds.push(record.id)
    refreshDownloadRecord(record, timeRequest)
  })
}

const refreshDownloadRecord = async (record, timeRequest) => {
  Download.find(record.id)
    .then(({ body }) => {
      if (body.ready) {
        const index = store.downloadList.findIndex(
          (item) => item.id === record.id
        )
        const timeoutIndex = timeoutDownloadIds.findIndex(
          (id) => id === record.id
        )

        actions.setDownloadRecord({ index, record: body })
        timeoutDownloadIds.splice(timeoutIndex, 1)
      } else {
        setTimeout(
          () => refreshDownloadRecord(record, timeRequest),
          timeRequest
        )
      }
    })
    .catch(() => {})
}

const getTimeByTotal = (recordTotal) => {
  const maxRecord = Object.keys(TIME_BY_RECORDS).find(
    (recordCount) => recordTotal < recordCount
  )

  return TIME_BY_RECORDS[maxRecord] || DEFAULT_WAIT_TIME
}

const setIsPublic = ({ id, is_public }, index) => {
  const download = {
    id,
    is_public: !is_public
  }

  Download.update(id, { download }).then(({ body }) => {
    actions.setDownloadRecord({
      index,
      record: body
    })
  })
}

const downloadFile = (url) => {
  window.open(url)
}

const sortByDate = (list) =>
  list.sort((a, b) => {
    const dateA = new Date(a.created_at).getTime()
    const dateB = new Date(b.created_at).getTime()

    return dateB - dateA
  })

watch(
  () => store.downloadList,
  (list) => {
    refreshDownloadList(list)
  },
  { deep: true }
)

onBeforeMount(async () => {
  store.downloadList = sortByDate(
    (await Download.where({ download_type: DOWNLOAD_DWC_ARCHIVE })).body
  )
})
</script>