Explorar el Código

refactor download logic into a component

Olivier Massot hace 3 años
padre
commit
d231a817c5
Se han modificado 2 ficheros con 125 adiciones y 44 borrados
  1. 113 0
      components/Ui/Downloader.vue
  2. 12 44
      pages/cmf_licence/organization.vue

+ 113 - 0
components/Ui/Downloader.vue

@@ -0,0 +1,113 @@
+<!--
+Wrapper to allow an UI element to trigger a file download
+
+The only required property is the File entity to download. It has to be in READY state.
+Trigger the download by calling `scope.download` on the event you like.
+If you want to display a loading animation while the download request is submitted, you can achieve this with `scope.downloading`
+
+Usage (default button) :
+
+    <UiDownloader :file="file"></UiDownloader>
+
+Usage (custom button) :
+
+    <UiDownloader :file="file" v-slot="scope">
+        <v-btn color="primary" :loading="scope.downloading" @click="scope.download">
+            {{ $t('download') }}
+        </v-btn>
+    </UiDownloader>
+-->
+
+<template>
+<!--  <div @download="download(file)">-->
+  <div>
+    <slot :download="download" :downloading="downloading">
+      <v-btn :loading="downloading" :disabled="downloading" @click="download">
+        {{ $t('download') }}
+      </v-btn>
+    </slot>
+  </div>
+</template>
+
+<script lang="ts">
+
+import {defineComponent, ref, Ref, useContext} from "@nuxtjs/composition-api";
+import {QUERY_TYPE} from "~/types/enums";
+import {DataProviderArgs} from "~/types/interfaces";
+import {File} from "~/models/Core/File";
+import {Bool} from "@vuex-orm/core";
+
+export default defineComponent({
+  props: {
+    file: {
+      type: File,
+      required: true
+    },
+    target: {
+      type: String,
+      required: false,
+      default: '_blank'
+    }
+  },
+  setup (props) {
+
+    const { $dataProvider } = useContext()
+
+    let { file, target } = props
+    let downloading: Ref<Boolean> = ref(false)
+
+    const download = async () => {
+      if (!file) {
+        console.error("File is not defined yet, impossible to download")
+        return
+      }
+      if (file.status === 'PENDING') {
+        console.error("File is not ready yet, impossible to download")
+        return
+      }
+      if (file.status === 'ERROR') {
+        console.error("An error occurred wilie generating the file, impossible to download")
+        return
+      }
+      if (file.status !== 'READY') {
+        console.error("File status is not correctly defined")
+        return
+      }
+      if (downloading.value) {
+        console.error("A download request is already being processed")
+        return
+      }
+
+      downloading.value = true
+
+      const response = await $dataProvider.invoke(
+        {
+          type: QUERY_TYPE.FILE,
+          fileArgs: { fileId: file.id }
+        } as DataProviderArgs
+      )
+
+      downloading.value = false
+
+      const blob = new Blob([response.data], { type: response.data.type })
+
+      const url = window.URL.createObjectURL(blob)
+
+      const link = document.createElement('a')
+      link.href = url
+      link.download = file.name ?? 'document'
+      link.target = target
+      link.click()
+
+      link.remove()
+      window.URL.revokeObjectURL(url)
+
+    }
+
+    return {
+      download: () => download(),
+      downloading
+    }
+  }
+})
+</script>

+ 12 - 44
pages/cmf_licence/organization.vue

@@ -20,16 +20,17 @@
           {{ $t('generate') }}
         </v-btn>
 
-        <v-btn
-          v-else
-          color="primary"
-          :loading="pending"
-          :disabled="pending"
-          target="_blank"
-          @click="download"
-        >
-          {{ $t('download') }}
-        </v-btn>
+        <UiDownloader v-else :file="file" v-slot="scope">
+          <v-btn
+            color="primary"
+            :loading="pending || scope.downloading"
+            :disabled="pending"
+            @click="scope.download"
+          >
+            {{ $t('download') }}
+          </v-btn>
+        </UiDownloader>
+
       </div>
     </v-form>
   </div>
@@ -69,7 +70,6 @@ export default defineComponent({
     const query: Query = repository.query()
 
     const submit = async () => {
-
       const response = await context.$dataPersister.invoke(
         {
           url: '/api/export/cmf-licence/organization',
@@ -87,42 +87,10 @@ export default defineComponent({
       repositoryHelper.persist(File, response.data)
     }
 
-    const download = async () => {
-      if (file.value === null) {
-        console.error("File is not defined yet, impossible to download")
-        return
-      }
-      if (pending.value) {
-        console.error("File is still pending, impossible to download")
-        return
-      }
-
-      const response = await context.$dataProvider.invoke(
-        {
-          type: QUERY_TYPE.FILE,
-          fileArgs: { fileId: file.value.id }
-        } as DataProviderArgs
-      )
-
-      const blob = new Blob([response.data], { type: response.data.type })
-
-      const url = window.URL.createObjectURL(blob)
-
-      const link = document.createElement('a')
-      link.href = url
-      link.download = file.value.name ?? 'unknown'
-      link.target = '_blank'
-      link.click()
-
-      link.remove()
-      window.URL.revokeObjectURL(url)
-    }
-
     return {
       submit,
       pending,
-      file,
-      download: () => download()
+      file
     }
   },
   beforeDestroy() {