You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2021/04/28 22:10:20 UTC

[airavata-django-portal] 02/02: AIRAVATA-3458 Check filesize before loading file in editor

This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit d5cf437b3cbfc8cd5697d861295921efb40564b8
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Wed Apr 28 18:05:31 2021 -0400

    AIRAVATA-3458 Check filesize before loading file in editor
---
 django_airavata/apps/api/serializers.py            | 10 +++
 .../django_airavata_api/js/models/DataProduct.js   |  1 +
 .../storage-edit/UserStorageTextEditViewer.vue     | 78 ++++++++++++++++------
 3 files changed, 69 insertions(+), 20 deletions(-)

diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
index ba1884b..9436fe1 100644
--- a/django_airavata/apps/api/serializers.py
+++ b/django_airavata/apps/api/serializers.py
@@ -462,6 +462,7 @@ class DataProductSerializer(
     replicaLocations = DataReplicaLocationSerializer(many=True)
     downloadURL = serializers.SerializerMethodField()
     isInputFileUpload = serializers.SerializerMethodField()
+    filesize = serializers.SerializerMethodField()
 
     def get_downloadURL(self, data_product):
         """Getter for downloadURL field."""
@@ -476,6 +477,15 @@ class DataProductSerializer(
         request = self.context['request']
         return user_storage.is_input_file(request, data_product)
 
+    def get_filesize(self, data_product):
+        request = self.context['request']
+        # For backwards compatibility with older user_storage, can be eventually removed
+        if hasattr(user_storage, 'get_data_product_metadata'):
+            metadata = user_storage.get_data_product_metadata(request, data_product)
+            return metadata['size']
+        else:
+            return 0
+
 
 # TODO move this into airavata_sdk?
 class FullExperiment:
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/DataProduct.js b/django_airavata/apps/api/static/django_airavata_api/js/models/DataProduct.js
index 724c18a..34c1e14 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/DataProduct.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/DataProduct.js
@@ -28,6 +28,7 @@ const FIELDS = [
   },
   "downloadURL",
   "isInputFileUpload",
+  "filesize",
 ];
 
 const FILENAME_REGEX = /[^/]+$/;
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/storage-edit/UserStorageTextEditViewer.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/storage-edit/UserStorageTextEditViewer.vue
index 35cf11d..1cd824e 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/storage-edit/UserStorageTextEditViewer.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/storage-edit/UserStorageTextEditViewer.vue
@@ -1,16 +1,31 @@
 <template>
   <div>
     <div class="user-storage-file-edit-viewer-status">
-      <div class="user-storage-file-edit-viewer-status-message">
+      <div
+        class="user-storage-file-edit-viewer-status-message"
+        v-if="editAvailable"
+      >
         <span v-if="saved">All the changes are saved.</span>
         <span v-if="!saved">Changes are not saved.</span>
       </div>
       <div class="user-storage-file-edit-viewer-status-actions">
-        <user-storage-download-button :data-product-uri="dataProductUri" :file-name="fileName"/>
-        <b-button :disabled="saved" @click="fileContentChanged">Save</b-button>
+        <user-storage-download-button
+          :data-product-uri="dataProductUri"
+          :file-name="fileName"
+        />
+        <b-button
+          v-if="editAvailable"
+          :disabled="saved"
+          @click="fileContentChanged"
+          >Save</b-button
+        >
       </div>
     </div>
     <div style="width: 100%" ref="editor"></div>
+    <div class="edit-not-available" v-if="!editAvailable">
+      Inline edit not available. Click the <strong>Download</strong> button to
+      download the file.
+    </div>
   </div>
 </template>
 
@@ -18,9 +33,11 @@
 import CodeMirror from "codemirror";
 import "codemirror/lib/codemirror.css";
 import "codemirror/theme/abcdef.css";
-import {utils} from "django-airavata-api";
+import { services, utils } from "django-airavata-api";
 import UserStorageDownloadButton from "./UserStorageDownloadButton";
 
+const MAX_EDIT_FILESIZE = 1024 * 1024;
+
 export default {
   name: "user-storage-file-edit-viewer",
   props: {
@@ -35,7 +52,7 @@ export default {
     },
     downloadUrl: {
       required: true,
-    }
+    },
   },
   components: {
     UserStorageDownloadButton: UserStorageDownloadButton,
@@ -45,6 +62,7 @@ export default {
       fileContent: "",
       saved: true,
       editor: null,
+      dataProduct: null,
     };
   },
   mounted() {
@@ -53,31 +71,51 @@ export default {
   destroyed() {
     this.editor.getWrapperElement().remove();
   },
+  computed: {
+    editAvailable() {
+      return !this.dataProduct || this.dataProduct.filesize < MAX_EDIT_FILESIZE;
+    },
+  },
   methods: {
     fileContentChanged() {
       const changedFileContent = this.editor.getDoc().getValue();
       if (changedFileContent) {
-        utils.FetchUtils.put(`/api/data-products?product-uri=${this.dataProductUri}`, {
-          fileContentText: changedFileContent,
-        }).then(() => {
+        utils.FetchUtils.put(
+          `/api/data-products?product-uri=${this.dataProductUri}`,
+          {
+            fileContentText: changedFileContent,
+          }
+        ).then(() => {
           this.$emit("file-content-changed", changedFileContent);
         });
       }
 
       this.saved = true;
     },
+    loadDataProduct() {
+      return services.DataProductService.retrieve({
+        lookup: this.dataProductUri,
+      }).then((dataProduct) => {
+        this.dataProduct = dataProduct;
+        return dataProduct;
+      });
+    },
     setFileContent() {
-      utils.FetchUtils.get(
-        this.downloadUrl,
-        "",
-        {
-          ignoreErrors: false,
-          showSpinner: true,
-        },
-        "text"
-      ).then((res) => {
-        this.fileContent = res;
-        this.setFileContentEditor(this.fileContent);
+      this.loadDataProduct().then(() => {
+        if (this.editAvailable) {
+          utils.FetchUtils.get(
+            this.downloadUrl,
+            "",
+            {
+              ignoreErrors: false,
+              showSpinner: true,
+            },
+            "text"
+          ).then((res) => {
+            this.fileContent = res;
+            this.setFileContentEditor(this.fileContent);
+          });
+        }
       });
     },
     setFileContentEditor(value = "") {
@@ -87,7 +125,7 @@ export default {
         lineNumbers: true,
         lineWrapping: true,
         scrollbarStyle: "native",
-        extraKeys: {"Ctrl-Space": "autocomplete"},
+        extraKeys: { "Ctrl-Space": "autocomplete" },
         value: value,
       });
       this.editor.on("change", () => {