Browse Source

fix: export data block not working in background

Ahmad Kholid 2 years ago
parent
commit
e5aed3ae5c

+ 92 - 83
src/components/newtab/workflow/edit/EditExportData.vue

@@ -6,93 +6,102 @@
       :placeholder="t('common.description')"
       @change="updateData({ description: $event })"
     />
-    <ui-select
-      :model-value="data.dataToExport"
-      :label="t('workflow.blocks.export-data.dataToExport.placeholder')"
-      class="w-full mt-2"
-      @change="updateData({ dataToExport: $event })"
-    >
-      <option v-for="option in dataToExport" :key="option" :value="option">
-        {{ t(`workflow.blocks.export-data.dataToExport.options.${option}`) }}
-      </option>
-    </ui-select>
-    <ui-input
-      v-if="data.dataToExport === 'google-sheets'"
-      :model-value="data.refKey"
-      :title="t('workflow.blocks.export-data.refKey')"
-      :placeholder="t('workflow.blocks.export-data.refKey')"
-      class="w-full mt-2"
-      @change="updateData({ refKey: $event })"
-    />
-    <ui-input
-      v-if="data.dataToExport === 'variable'"
-      :model-value="data.variableName"
-      :title="t('workflow.variables.name')"
-      :placeholder="t('workflow.variables.name')"
-      class="w-full mt-2"
-      @change="updateData({ variableName: $event })"
-    />
-    <edit-autocomplete class="mt-2">
+    <template v-if="!permission.has.downloads">
+      <p class="mt-4">
+        {{ t('workflow.blocks.handle-download.noPermission') }}
+      </p>
+      <ui-button variant="accent" class="mt-2" @click="permission.request">
+        {{ t('workflow.blocks.clipboard.grantPermission') }}
+      </ui-button>
+    </template>
+    <template v-else>
+      <ui-select
+        :model-value="data.dataToExport"
+        :label="t('workflow.blocks.export-data.dataToExport.placeholder')"
+        class="w-full mt-2"
+        @change="updateData({ dataToExport: $event })"
+      >
+        <option v-for="option in dataToExport" :key="option" :value="option">
+          {{ t(`workflow.blocks.export-data.dataToExport.options.${option}`) }}
+        </option>
+      </ui-select>
       <ui-input
-        :model-value="data.name"
-        autocomplete="off"
-        label="File name"
-        class="w-full"
-        placeholder="unnamed"
-        @change="updateData({ name: $event })"
+        v-if="data.dataToExport === 'google-sheets'"
+        :model-value="data.refKey"
+        :title="t('workflow.blocks.export-data.refKey')"
+        :placeholder="t('workflow.blocks.export-data.refKey')"
+        class="w-full mt-2"
+        @change="updateData({ refKey: $event })"
       />
-    </edit-autocomplete>
-    <ui-select
-      v-if="permission.has.downloads"
-      :model-value="data.onConflict"
-      :label="t('workflow.blocks.handle-download.onConflict')"
-      class="mt-2 w-full"
-      @change="updateData({ onConflict: $event })"
-    >
-      <option v-for="item in onConflict" :key="item" :value="item">
-        {{ t(`workflow.blocks.base.downloads.onConflict.${item}`) }}
-      </option>
-    </ui-select>
-    <ui-select
-      :model-value="data.type"
-      :label="t('workflow.blocks.export-data.exportAs')"
-      class="w-full mt-2"
-      @change="updateData({ type: $event })"
-    >
-      <option v-for="type in dataExportTypes" :key="type.id" :value="type.id">
-        {{ type.name }}
-      </option>
-    </ui-select>
-    <ui-expand
-      v-if="data.type === 'csv'"
-      hide-header-icon
-      header-class="flex items-center focus:ring-0 w-full"
-    >
-      <template #header="{ show }">
-        <v-remixicon
-          :rotate="show ? 270 : 180"
-          name="riArrowLeftSLine"
-          class="transition-transform text-gray-600 dark:text-gray-300"
-        />
-        {{ t('common.options') }}
-      </template>
-      <div class="pl-6 mt-1">
-        <ui-checkbox
-          v-if="data.type === 'csv'"
-          :model-value="data.addBOMHeader"
-          @change="updateData({ addBOMHeader: $event })"
-        >
-          {{ t('workflow.blocks.export-data.bomHeader') }}
-        </ui-checkbox>
+      <ui-input
+        v-if="data.dataToExport === 'variable'"
+        :model-value="data.variableName"
+        :title="t('workflow.variables.name')"
+        :placeholder="t('workflow.variables.name')"
+        class="w-full mt-2"
+        @change="updateData({ variableName: $event })"
+      />
+      <edit-autocomplete class="mt-2">
         <ui-input
-          :model-value="data.csvDelimiter"
-          label="Delimiter"
-          class="mt-1"
-          placeholder=","
-          @change="updateData({ csvDelimiter: $event })"
+          :model-value="data.name"
+          autocomplete="off"
+          label="File name"
+          class="w-full"
+          placeholder="unnamed"
+          @change="updateData({ name: $event })"
         />
-      </div>
-    </ui-expand>
+      </edit-autocomplete>
+      <ui-select
+        :model-value="data.onConflict"
+        :label="t('workflow.blocks.handle-download.onConflict')"
+        class="mt-2 w-full"
+        @change="updateData({ onConflict: $event })"
+      >
+        <option v-for="item in onConflict" :key="item" :value="item">
+          {{ t(`workflow.blocks.base.downloads.onConflict.${item}`) }}
+        </option>
+      </ui-select>
+      <ui-select
+        :model-value="data.type"
+        :label="t('workflow.blocks.export-data.exportAs')"
+        class="w-full mt-2"
+        @change="updateData({ type: $event })"
+      >
+        <option v-for="type in dataExportTypes" :key="type.id" :value="type.id">
+          {{ type.name }}
+        </option>
+      </ui-select>
+      <ui-expand
+        v-if="data.type === 'csv'"
+        hide-header-icon
+        header-class="flex items-center focus:ring-0 w-full"
+      >
+        <template #header="{ show }">
+          <v-remixicon
+            :rotate="show ? 270 : 180"
+            name="riArrowLeftSLine"
+            class="transition-transform text-gray-600 dark:text-gray-300"
+          />
+          {{ t('common.options') }}
+        </template>
+        <div class="pl-6 mt-1">
+          <ui-checkbox
+            v-if="data.type === 'csv'"
+            :model-value="data.addBOMHeader"
+            @change="updateData({ addBOMHeader: $event })"
+          >
+            {{ t('workflow.blocks.export-data.bomHeader') }}
+          </ui-checkbox>
+          <ui-input
+            :model-value="data.csvDelimiter"
+            label="Delimiter"
+            class="mt-1"
+            placeholder=","
+            @change="updateData({ csvDelimiter: $event })"
+          />
+        </div>
+      </ui-expand>
+    </template>
   </div>
 </template>
 <script setup>

+ 5 - 2
src/utils/dataExporter.js

@@ -38,7 +38,7 @@ export function generateJSON(keys, data) {
 
 export default function (
   data,
-  { name, type, addBOMHeader, csvOptions, returnUrl },
+  { name, type, addBOMHeader, csvOptions, returnUrl, returnBlob },
   converted
 ) {
   let result = data;
@@ -71,7 +71,10 @@ export default function (
   }
 
   const { mime, ext } = files[type];
-  const blobUrl = URL.createObjectURL(new Blob(payload, { type: mime }));
+  const blob = new Blob(payload, { type: mime });
+  if (returnBlob) return blob;
+
+  const blobUrl = URL.createObjectURL(blob);
 
   if (!returnUrl) fileSaver(`${name || 'unnamed'}${ext}`, blobUrl);
 

+ 16 - 1
src/workflowEngine/blocksHandler/handlerExportData.js

@@ -1,6 +1,14 @@
 import browser from 'webextension-polyfill';
 import { default as dataExporter, files } from '@/utils/dataExporter';
 
+function blobToBase64(blob) {
+  return new Promise((resolve) => {
+    const reader = new FileReader();
+    reader.onloadend = () => resolve(reader.result);
+    reader.readAsDataURL(blob);
+  });
+}
+
 async function exportData({ data, id }, { refData }) {
   const dataToExport = data.dataToExport || 'data-columns';
   let payload = refData.table;
@@ -21,14 +29,21 @@ async function exportData({ data, id }, { refData }) {
   const hasDownloadAccess = await browser.permissions.contains({
     permissions: ['downloads'],
   });
-  const blobUrl = dataExporter(payload, {
+  let blobUrl = dataExporter(payload, {
     ...data,
     csvOptions: {
       delimiter: data.csvDelimiter || ',',
     },
     returnUrl: hasDownloadAccess,
+    returnBlob: !this.engine.isPopup,
   });
 
+  if (!this.engine.isPopup && !hasDownloadAccess) {
+    throw new Error("Don't have download permission");
+  } else if (!this.engine.isPopup) {
+    blobUrl = await blobToBase64(blobUrl);
+  }
+
   if (hasDownloadAccess) {
     const filename = `${data.name || 'unnamed'}${files[data.type].ext}`;
     const options = {