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 2019/05/24 18:28:36 UTC

[airavata-django-portal] branch airavata-3016 updated (2620f18 -> 87f4d83)

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

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


    from 2620f18  AIRAVATA-3034 user storage breadcrumbs
     new 643a55f  AIRAVATA-3034 sorting by name and created time
     new 33f1258  AIRAVATA-3034 File, directory size, with sorting
     new 615713a  AIRAVATA-3034 Fixing double initial load of data
     new bbd90ce  AIRAVATA-3034 UI enhancements to storage browser
     new 68d736e  AIRAVATA-3016 Removing sanitizing usernames
     new 52968ff  AIRAVATA-3034 changed icons, order of storage columns
     new d04ded4  AIRAVATA-3034 Upload files, add new directory
     new 87f4d83  AIRAVATA-3034 Delete directories, path

The 8 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 django_airavata/apps/api/data_products_helper.py   |  15 ++-
 django_airavata/apps/api/datastore.py              |  31 ++++--
 django_airavata/apps/api/serializers.py            |   4 +
 .../api/static/django_airavata_api/js/index.js     |   9 +-
 .../js/models/UserStorageDirectory.js              |   2 +-
 .../js/models/UserStorageFile.js                   |   8 +-
 .../django_airavata_api/js/session/Session.js      |   7 ++
 django_airavata/apps/api/views.py                  |   1 +
 django_airavata/apps/workspace/package.json        |   4 +-
 .../components/storage/UserStoragePathViewer.vue   |  74 ++++++++++++++-
 .../js/containers/UserStorageContainer.vue         | 104 ++++++++++++++++++++-
 .../templates/django_airavata_workspace/base.html  |   2 +-
 django_airavata/static/common/js/entry.js          |   4 +
 django_airavata/static/common/package.json         |   2 +-
 django_airavata/templates/base.html                |   6 ++
 15 files changed, 249 insertions(+), 24 deletions(-)
 create mode 100644 django_airavata/apps/api/static/django_airavata_api/js/session/Session.js


[airavata-django-portal] 07/08: AIRAVATA-3034 Upload files, add new directory

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit d04ded4f156f80e4aab125ef6917d0b5ed9dd9e5
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Fri May 24 12:20:00 2019 -0400

    AIRAVATA-3034 Upload files, add new directory
---
 django_airavata/apps/api/views.py                  |  1 +
 django_airavata/apps/workspace/package.json        |  4 +-
 .../js/containers/UserStorageContainer.vue         | 87 +++++++++++++++++++---
 django_airavata/static/common/package.json         |  2 +-
 4 files changed, 79 insertions(+), 15 deletions(-)

diff --git a/django_airavata/apps/api/views.py b/django_airavata/apps/api/views.py
index 94eed4f..c93df77 100644
--- a/django_airavata/apps/api/views.py
+++ b/django_airavata/apps/api/views.py
@@ -1356,6 +1356,7 @@ class UserStoragePathView(APIView):
         if not data_products_helper.dir_exists(request, user_storage_path):
             data_products_helper.create_user_dir(request, user_storage_path)
 
+        data_product = None
         if 'file' in request.FILES:
             user_file = request.FILES['file']
             data_product = data_products_helper.save(
diff --git a/django_airavata/apps/workspace/package.json b/django_airavata/apps/workspace/package.json
index 833f1dc..2e3fd10 100644
--- a/django_airavata/apps/workspace/package.json
+++ b/django_airavata/apps/workspace/package.json
@@ -14,8 +14,8 @@
     "test:unit:watch": "vue-cli-service test:unit --watch"
   },
   "dependencies": {
-    "bootstrap": "^4.0.0-beta.2",
-    "bootstrap-vue": "^2.0.0-rc.11",
+    "bootstrap": "^4.3.1",
+    "bootstrap-vue": "^2.0.0-rc.20",
     "django-airavata-api": "file:../api",
     "django-airavata-common-ui": "file:../../static/common",
     "django-airavata-workspace-plugin-api": "file:django-airavata-workspace-plugin-api",
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/UserStorageContainer.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/UserStorageContainer.vue
index b198dd2..0674abd 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/UserStorageContainer.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/UserStorageContainer.vue
@@ -1,15 +1,47 @@
 <template>
-  <div class="row">
-    <div class="col">
-      <h1 class="h4">
-        Storage
-      </h1>
-      <p>
-        <small class="text-muted"><i class="fa fa-folder-open"></i> {{ username }}</small>
-      </p>
-      <b-card>
-        <router-view :user-storage-path="userStoragePath"></router-view>
-      </b-card>
+  <div>
+    <div class="row">
+      <div class="col">
+        <h1 class="h4">
+          Storage
+        </h1>
+        <p>
+          <small class="text-muted"><i class="fa fa-folder-open"></i> {{ username }}</small>
+        </p>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col">
+        <b-form-file
+          v-model="file"
+          ref="file-input"
+          placeholder="Add file"
+          @input="fileChanged"
+          class="mb-2"
+        ></b-form-file>
+      </div>
+      <div class="col">
+        <b-input-group>
+          <b-form-input
+            v-model="dirName"
+            placeholder="New directory name"
+            @keydown.native.enter="addDirectory"
+          ></b-form-input>
+          <b-input-group-append>
+            <b-button
+              @click="addDirectory"
+              :disabled="!this.dirName"
+            >Add directory</b-button>
+          </b-input-group-append>
+        </b-input-group>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col">
+        <b-card>
+          <router-view :user-storage-path="userStoragePath"></router-view>
+        </b-card>
+      </div>
     </div>
   </div>
 </template>
@@ -34,7 +66,9 @@ export default {
   },
   data() {
     return {
-      userStoragePath: null
+      userStoragePath: null,
+      file: null,
+      dirName: null
     };
   },
   methods: {
@@ -64,6 +98,35 @@ export default {
           duration: 2
         })
       );
+    },
+    fileChanged() {
+      if (this.file) {
+        let data = new FormData();
+        data.append("file", this.file);
+        utils.FetchUtils.post(
+          "/api/user-storage/" + this.storagePath,
+          data
+        ).then(result => {
+          // this.file = null;
+          this.$refs["file-input"].reset();
+          this.loadUserStoragePath(this.storagePath);
+        });
+      }
+    },
+    addDirectory() {
+      if (this.dirName) {
+        let newDirPath = this.storagePath;
+        if (!newDirPath.endsWith("/")) {
+          newDirPath = newDirPath + "/";
+        }
+        newDirPath = newDirPath + this.dirName;
+        utils.FetchUtils.post("/api/user-storage/" + newDirPath).then(
+          result => {
+            this.dirName = null;
+            this.loadUserStoragePath(this.storagePath);
+          }
+        );
+      }
     }
   },
   created() {
diff --git a/django_airavata/static/common/package.json b/django_airavata/static/common/package.json
index eff789e..c1c7da6 100644
--- a/django_airavata/static/common/package.json
+++ b/django_airavata/static/common/package.json
@@ -14,7 +14,7 @@
   },
   "dependencies": {
     "@fortawesome/fontawesome-free": "^5.6.3",
-    "bootstrap": "^4.2.1",
+    "bootstrap": "^4.3.1",
     "bootstrap-vue": "^2.0.0-rc.11",
     "clipboard": "^2.0.4",
     "django-airavata-api": "file:../../apps/api",


[airavata-django-portal] 01/08: AIRAVATA-3034 sorting by name and created time

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 643a55f6505c7d0cd33eaa2655e95bc72ffd40a9
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Fri May 24 09:33:16 2019 -0400

    AIRAVATA-3034 sorting by name and created time
---
 django_airavata/apps/api/data_products_helper.py   | 11 ++++++--
 django_airavata/apps/api/datastore.py              |  5 ++++
 django_airavata/apps/api/serializers.py            |  2 ++
 .../js/models/UserStorageDirectory.js              |  2 +-
 .../js/models/UserStorageFile.js                   |  7 +++++-
 .../components/storage/UserStoragePathViewer.vue   | 29 +++++++++++++++++++---
 6 files changed, 49 insertions(+), 7 deletions(-)

diff --git a/django_airavata/apps/api/data_products_helper.py b/django_airavata/apps/api/data_products_helper.py
index ef550e4..cdd67b1 100644
--- a/django_airavata/apps/api/data_products_helper.py
+++ b/django_airavata/apps/api/data_products_helper.py
@@ -64,16 +64,23 @@ def listdir(request, path):
             request.user.username, path)
         directories_data = []
         for d in directories:
+            dpath = os.path.join(path, d)
+            created_time = datastore.get_created_time(
+                request.user.username, dpath)
             directories_data.append({'name': d,
-                                     'path': os.path.join(path, d)})
+                                     'path': dpath,
+                                     'created_time': created_time})
         files_data = []
         for f in files:
             user_rel_path = os.path.join(path, f)
+            created_time = datastore.get_created_time(
+                request.user.username, user_rel_path)
             full_path = datastore.path(request.user.username, user_rel_path)
             data_product_uri = _get_data_product_uri(request, full_path)
             files_data.append({'name': f,
                                'path': user_rel_path,
-                               'data-product-uri': data_product_uri})
+                               'data-product-uri': data_product_uri,
+                               'created_time': created_time})
         return directories_data, files_data
     else:
         raise ObjectDoesNotExist("User storage path does not exist")
diff --git a/django_airavata/apps/api/datastore.py b/django_airavata/apps/api/datastore.py
index c1663eb..cfe7f36 100644
--- a/django_airavata/apps/api/datastore.py
+++ b/django_airavata/apps/api/datastore.py
@@ -119,6 +119,11 @@ def list_user_dir(username, file_path):
     return user_data_storage.listdir(file_path)
 
 
+def get_created_time(username, file_path):
+    user_data_storage = _user_data_storage(username)
+    return user_data_storage.get_created_time(file_path)
+
+
 def path(username, file_path):
     return path_(username, file_path)
 
diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
index a37a0ac..8d7cb7b 100644
--- a/django_airavata/apps/api/serializers.py
+++ b/django_airavata/apps/api/serializers.py
@@ -752,6 +752,7 @@ class UserStorageFileSerializer(serializers.Serializer):
     name = serializers.CharField()
     downloadURL = serializers.SerializerMethodField()
     dataProductURI = serializers.CharField(source='data-product-uri')
+    createdTime = serializers.DateTimeField(source='created_time')
 
     def get_downloadURL(self, file):
         """Getter for downloadURL field."""
@@ -765,6 +766,7 @@ class UserStorageFileSerializer(serializers.Serializer):
 class UserStorageDirectorySerializer(serializers.Serializer):
     name = serializers.CharField()
     path = serializers.CharField()
+    createdTime = serializers.DateTimeField(source='created_time')
     url = FullyEncodedHyperlinkedIdentityField(
         view_name='django_airavata_api:user-storage-items',
         lookup_field='path',
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/UserStorageDirectory.js b/django_airavata/apps/api/static/django_airavata_api/js/models/UserStorageDirectory.js
index 8c7f3a0..8108d6e 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/UserStorageDirectory.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/UserStorageDirectory.js
@@ -1,6 +1,6 @@
 import BaseModel from "./BaseModel";
 
-const FIELDS = ["name", "path"];
+const FIELDS = ["name", "path", { name: "createdTime", type: "date" }];
 
 export default class UserStorageDirectory extends BaseModel {
   constructor(data = {}) {
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/UserStorageFile.js b/django_airavata/apps/api/static/django_airavata_api/js/models/UserStorageFile.js
index dfcf55c..42d81b0 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/UserStorageFile.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/UserStorageFile.js
@@ -1,6 +1,11 @@
 import BaseModel from "./BaseModel";
 
-const FIELDS = ["name", "downloadURL", "dataProductURI"];
+const FIELDS = [
+  "name",
+  "downloadURL",
+  "dataProductURI",
+  { name: "createdTime", type: "date" }
+];
 
 export default class UserStorageFile extends BaseModel {
   constructor(data = {}) {
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue
index 5ff9587..1c97824 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue
@@ -7,6 +7,7 @@
     <b-table
       :fields="fields"
       :items="items"
+      sort-by="name"
     >
       <template
         slot="name"
@@ -21,11 +22,18 @@
           :href="data.item.downloadURL"
         >{{ data.item.name }}</b-link>
       </template>
+      <template
+        slot="createdTimestamp"
+        slot-scope="data"
+      >
+        <span :title="data.item.createdTime.toString()">{{ fromNow(data.item.createdTime)}}</span>
+      </template>
     </b-table>
   </div>
 </template>
 <script>
 import UserStoragePathBreadcrumb from "./UserStoragePathBreadcrumb.vue";
+import moment from "moment";
 
 export default {
   name: "user-storage-path-viewer",
@@ -42,7 +50,13 @@ export default {
       return [
         {
           label: "Name",
-          key: "name"
+          key: "name",
+          sortable: true
+        },
+        {
+          label: "Created Time",
+          key: "createdTimestamp",
+          sortable: true
         }
       ];
     },
@@ -52,14 +66,18 @@ export default {
           return {
             name: d.name,
             path: d.path,
-            type: "dir"
+            type: "dir",
+            createdTime: d.createdTime,
+            createdTimestamp: d.createdTime.getTime() // for sorting
           };
         });
         const files = this.userStoragePath.files.map(f => {
           return {
             name: f.name,
             type: "file",
-            downloadURL: f.downloadURL
+            downloadURL: f.downloadURL,
+            createdTime: f.createdTime,
+            createdTimestamp: f.createdTime.getTime() // for sorting
           };
         });
         return dirs.concat(files);
@@ -67,6 +85,11 @@ export default {
         return [];
       }
     }
+  },
+  methods: {
+    fromNow(date) {
+      return moment(date).fromNow();
+    }
   }
 };
 </script>


[airavata-django-portal] 02/08: AIRAVATA-3034 File, directory size, with sorting

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 33f12580728571d2d8c8ba108502062412e3d700
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Fri May 24 10:02:41 2019 -0400

    AIRAVATA-3034 File, directory size, with sorting
---
 django_airavata/apps/api/data_products_helper.py   |  8 ++++++--
 django_airavata/apps/api/datastore.py              | 19 ++++++++++++++++++
 django_airavata/apps/api/serializers.py            |  2 ++
 .../js/models/UserStorageDirectory.js              |  2 +-
 .../js/models/UserStorageFile.js                   |  3 ++-
 .../components/storage/UserStoragePathViewer.vue   | 23 ++++++++++++++++++++--
 6 files changed, 51 insertions(+), 6 deletions(-)

diff --git a/django_airavata/apps/api/data_products_helper.py b/django_airavata/apps/api/data_products_helper.py
index cdd67b1..88d9f4e 100644
--- a/django_airavata/apps/api/data_products_helper.py
+++ b/django_airavata/apps/api/data_products_helper.py
@@ -67,20 +67,24 @@ def listdir(request, path):
             dpath = os.path.join(path, d)
             created_time = datastore.get_created_time(
                 request.user.username, dpath)
+            size = datastore.size(request.user.username, dpath)
             directories_data.append({'name': d,
                                      'path': dpath,
-                                     'created_time': created_time})
+                                     'created_time': created_time,
+                                     'size': size})
         files_data = []
         for f in files:
             user_rel_path = os.path.join(path, f)
             created_time = datastore.get_created_time(
                 request.user.username, user_rel_path)
+            size = datastore.size(request.user.username, user_rel_path)
             full_path = datastore.path(request.user.username, user_rel_path)
             data_product_uri = _get_data_product_uri(request, full_path)
             files_data.append({'name': f,
                                'path': user_rel_path,
                                'data-product-uri': data_product_uri,
-                               'created_time': created_time})
+                               'created_time': created_time,
+                               'size': size})
         return directories_data, files_data
     else:
         raise ObjectDoesNotExist("User storage path does not exist")
diff --git a/django_airavata/apps/api/datastore.py b/django_airavata/apps/api/datastore.py
index cfe7f36..34d858e 100644
--- a/django_airavata/apps/api/datastore.py
+++ b/django_airavata/apps/api/datastore.py
@@ -124,6 +124,15 @@ def get_created_time(username, file_path):
     return user_data_storage.get_created_time(file_path)
 
 
+def size(username, file_path):
+    user_data_storage = _user_data_storage(username)
+    full_path = path_(username, file_path)
+    if os.path.isdir(full_path):
+        return _get_dir_size(full_path)
+    else:
+        return user_data_storage.size(file_path)
+
+
 def path(username, file_path):
     return path_(username, file_path)
 
@@ -141,3 +150,13 @@ def _user_data_storage(username):
     return FileSystemStorage(
         location=os.path.join(settings.GATEWAY_DATA_STORE_DIR,
                               _user_dir_name(username)))
+
+
+# from https://stackoverflow.com/a/1392549
+def _get_dir_size(start_path='.'):
+    total_size = 0
+    for dirpath, dirnames, filenames in os.walk(start_path):
+        for f in filenames:
+            fp = os.path.join(dirpath, f)
+            total_size += os.path.getsize(fp)
+    return total_size
diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
index 8d7cb7b..4e6a0fe 100644
--- a/django_airavata/apps/api/serializers.py
+++ b/django_airavata/apps/api/serializers.py
@@ -753,6 +753,7 @@ class UserStorageFileSerializer(serializers.Serializer):
     downloadURL = serializers.SerializerMethodField()
     dataProductURI = serializers.CharField(source='data-product-uri')
     createdTime = serializers.DateTimeField(source='created_time')
+    size = serializers.IntegerField()
 
     def get_downloadURL(self, file):
         """Getter for downloadURL field."""
@@ -767,6 +768,7 @@ class UserStorageDirectorySerializer(serializers.Serializer):
     name = serializers.CharField()
     path = serializers.CharField()
     createdTime = serializers.DateTimeField(source='created_time')
+    size = serializers.IntegerField()
     url = FullyEncodedHyperlinkedIdentityField(
         view_name='django_airavata_api:user-storage-items',
         lookup_field='path',
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/UserStorageDirectory.js b/django_airavata/apps/api/static/django_airavata_api/js/models/UserStorageDirectory.js
index 8108d6e..83faa77 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/UserStorageDirectory.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/UserStorageDirectory.js
@@ -1,6 +1,6 @@
 import BaseModel from "./BaseModel";
 
-const FIELDS = ["name", "path", { name: "createdTime", type: "date" }];
+const FIELDS = ["name", "path", { name: "createdTime", type: "date" }, "size"];
 
 export default class UserStorageDirectory extends BaseModel {
   constructor(data = {}) {
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/UserStorageFile.js b/django_airavata/apps/api/static/django_airavata_api/js/models/UserStorageFile.js
index 42d81b0..f10f2f4 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/UserStorageFile.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/UserStorageFile.js
@@ -4,7 +4,8 @@ const FIELDS = [
   "name",
   "downloadURL",
   "dataProductURI",
-  { name: "createdTime", type: "date" }
+  { name: "createdTime", type: "date" },
+  "size"
 ];
 
 export default class UserStorageFile extends BaseModel {
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue
index 1c97824..b65f90a 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue
@@ -57,6 +57,12 @@ export default {
           label: "Created Time",
           key: "createdTimestamp",
           sortable: true
+        },
+        {
+          label: "Size",
+          key: "size",
+          sortable: true,
+          formatter: value => this.getFormattedSize(value)
         }
       ];
     },
@@ -68,7 +74,8 @@ export default {
             path: d.path,
             type: "dir",
             createdTime: d.createdTime,
-            createdTimestamp: d.createdTime.getTime() // for sorting
+            createdTimestamp: d.createdTime.getTime(), // for sorting
+            size: d.size
           };
         });
         const files = this.userStoragePath.files.map(f => {
@@ -77,7 +84,8 @@ export default {
             type: "file",
             downloadURL: f.downloadURL,
             createdTime: f.createdTime,
-            createdTimestamp: f.createdTime.getTime() // for sorting
+            createdTimestamp: f.createdTime.getTime(), // for sorting
+            size: f.size
           };
         });
         return dirs.concat(files);
@@ -89,6 +97,17 @@ export default {
   methods: {
     fromNow(date) {
       return moment(date).fromNow();
+    },
+    getFormattedSize(size) {
+      if (size > Math.pow(2, 30)) {
+        return Math.round(size / Math.pow(2,30)) + " GB";
+      } else if (size > Math.pow(2, 20)) {
+        return Math.round(size / Math.pow(2,20)) + " MB";
+      } else if (size > Math.pow(2, 10)) {
+        return Math.round(size / Math.pow(2,10)) + " KB";
+      } else {
+        return size + " bytes";
+      }
     }
   }
 };


[airavata-django-portal] 08/08: AIRAVATA-3034 Delete directories, path

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 87f4d831b83982c636d7911f8c429bebab39ce38
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Fri May 24 12:41:48 2019 -0400

    AIRAVATA-3034 Delete directories, path
---
 .../components/storage/UserStoragePathViewer.vue   | 22 ++++++++++++++++++++++
 .../js/containers/UserStorageContainer.vue         | 19 ++++++++++++++++++-
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue
index 95ba055..a2286f2 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue
@@ -28,11 +28,20 @@
       >
         <span :title="data.item.createdTime.toString()">{{ fromNow(data.item.createdTime)}}</span>
       </template>
+      <template
+        slot="actions"
+        slot-scope="data"
+      >
+        <delete-button @delete="deleteItem(data.item)">
+          Are you sure you want to delete {{ data.item.name }}?
+        </delete-button>
+      </template>
     </b-table>
   </div>
 </template>
 <script>
 import UserStoragePathBreadcrumb from "./UserStoragePathBreadcrumb.vue";
+import { components } from "django-airavata-common-ui";
 import moment from "moment";
 
 export default {
@@ -43,6 +52,7 @@ export default {
     }
   },
   components: {
+    "delete-button": components.DeleteButton,
     UserStoragePathBreadcrumb
   },
   computed: {
@@ -63,6 +73,10 @@ export default {
           label: "Created Time",
           key: "createdTimestamp",
           sortable: true
+        },
+        {
+          label: "Actions",
+          key: "actions"
         }
       ];
     },
@@ -82,6 +96,7 @@ export default {
           return {
             name: f.name,
             type: "file",
+            dataProductURI: f.dataProductURI,
             downloadURL: f.downloadURL,
             createdTime: f.createdTime,
             createdTimestamp: f.createdTime.getTime(), // for sorting
@@ -108,6 +123,13 @@ export default {
       } else {
         return size + " bytes";
       }
+    },
+    deleteItem(item) {
+      if (item.type === "dir") {
+        this.$emit("delete-dir", item.path);
+      } else if (item.type === "file") {
+        this.$emit("delete-file", item.dataProductURI);
+      }
     }
   }
 };
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/UserStorageContainer.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/UserStorageContainer.vue
index 0674abd..809bcb2 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/UserStorageContainer.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/UserStorageContainer.vue
@@ -39,7 +39,11 @@
     <div class="row">
       <div class="col">
         <b-card>
-          <router-view :user-storage-path="userStoragePath"></router-view>
+          <router-view
+            :user-storage-path="userStoragePath"
+            @delete-dir="deleteDir"
+            @delete-file="deleteFile"
+          ></router-view>
         </b-card>
       </div>
     </div>
@@ -127,6 +131,19 @@ export default {
           }
         );
       }
+    },
+    deleteDir(path) {
+      utils.FetchUtils.delete("/api/user-storage/~/" + path).then(result => {
+        this.loadUserStoragePath(this.storagePath);
+      });
+    },
+    deleteFile(dataProductURI) {
+      utils.FetchUtils.delete(
+        "/api/delete-file?data-product-uri=" +
+          encodeURIComponent(dataProductURI)
+      ).then(() => {
+        this.loadUserStoragePath(this.storagePath);
+      });
     }
   },
   created() {


[airavata-django-portal] 06/08: AIRAVATA-3034 changed icons, order of storage columns

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 52968ff761dbea17509da951897d21fd637c96d2
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Fri May 24 11:16:49 2019 -0400

    AIRAVATA-3034 changed icons, order of storage columns
---
 .../js/components/storage/UserStoragePathViewer.vue            | 10 +++++-----
 .../workspace/templates/django_airavata_workspace/base.html    |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue
index b71cc14..95ba055 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue
@@ -54,15 +54,15 @@ export default {
           sortable: true
         },
         {
-          label: "Created Time",
-          key: "createdTimestamp",
-          sortable: true
-        },
-        {
           label: "Size",
           key: "size",
           sortable: true,
           formatter: value => this.getFormattedSize(value)
+        },
+        {
+          label: "Created Time",
+          key: "createdTimestamp",
+          sortable: true
         }
       ];
     },
diff --git a/django_airavata/apps/workspace/templates/django_airavata_workspace/base.html b/django_airavata/apps/workspace/templates/django_airavata_workspace/base.html
index 05fa03b..fe3d726 100644
--- a/django_airavata/apps/workspace/templates/django_airavata_workspace/base.html
+++ b/django_airavata/apps/workspace/templates/django_airavata_workspace/base.html
@@ -18,7 +18,7 @@
             <i class="fa fa-flask"></i> <span class=sr-only>Experiments</span>
         </a>
         <a href="{% url 'django_airavata_workspace:projects' %}" class="c-nav__item {% if request.active_nav_item == 'projects' %}is-active{% endif %}" data-toggle=tooltip data-placement=right title=Projects>
-            <i class="fa fa-folder-open"></i> <span class=sr-only>Projects</span>
+            <i class="fa fa-box"></i> <span class=sr-only>Projects</span>
         </a>
         <a href="{% url 'django_airavata_workspace:storage' %}" class="c-nav__item {% if request.active_nav_item == 'storage' %}is-active{% endif %}" data-toggle=tooltip data-placement=right title=Storage>
             <i class="fa fa-folder-open"></i> <span class=sr-only>Storage</span>


[airavata-django-portal] 05/08: AIRAVATA-3016 Removing sanitizing usernames

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 68d736ec201e18a21187e6f71ff314ac367b560d
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Fri May 24 11:10:46 2019 -0400

    AIRAVATA-3016 Removing sanitizing usernames
    
    Usernames should be safe for directory names already and
    sanitizing them this way will introduce an incompatibility for users
    with usernames that have an @ symbol in them.
---
 django_airavata/apps/api/datastore.py | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/django_airavata/apps/api/datastore.py b/django_airavata/apps/api/datastore.py
index 34d858e..a9b76c6 100644
--- a/django_airavata/apps/api/datastore.py
+++ b/django_airavata/apps/api/datastore.py
@@ -142,14 +142,9 @@ def path_(username, file_path):
     return user_data_storage.path(file_path)
 
 
-def _user_dir_name(username):
-    return Storage().get_valid_name(username)
-
-
 def _user_data_storage(username):
     return FileSystemStorage(
-        location=os.path.join(settings.GATEWAY_DATA_STORE_DIR,
-                              _user_dir_name(username)))
+        location=os.path.join(settings.GATEWAY_DATA_STORE_DIR, username))
 
 
 # from https://stackoverflow.com/a/1392549


[airavata-django-portal] 04/08: AIRAVATA-3034 UI enhancements to storage browser

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit bbd90ce0b183cf323e88103c6c3ba390c7186a29
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Fri May 24 11:08:36 2019 -0400

    AIRAVATA-3034 UI enhancements to storage browser
---
 .../apps/api/static/django_airavata_api/js/index.js   |  9 ++++++++-
 .../static/django_airavata_api/js/session/Session.js  |  7 +++++++
 .../js/components/storage/UserStoragePathViewer.vue   | 10 +++++-----
 .../js/containers/UserStorageContainer.vue            | 19 +++++++++++++++++--
 django_airavata/static/common/js/entry.js             |  4 ++++
 django_airavata/templates/base.html                   |  6 ++++++
 6 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/django_airavata/apps/api/static/django_airavata_api/js/index.js b/django_airavata/apps/api/static/django_airavata_api/js/index.js
index f410066..d332d6c 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/index.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/index.js
@@ -43,6 +43,8 @@ import GridFTPDataMovementService from "./services/GridFTPDataMovementService";
 import UnicoreDataMovementService from "./services/UnicoreDataMovementService";
 import ServiceFactory from "./services/ServiceFactory";
 
+import Session from "./session/Session";
+
 import FetchUtils from "./utils/FetchUtils";
 import PaginationIterator from "./utils/PaginationIterator";
 import StringUtils from "./utils/StringUtils";
@@ -121,6 +123,10 @@ const services = {
   WorkspacePreferencesService: ServiceFactory.service("WorkspacePreferences")
 };
 
+const session = {
+  Session
+};
+
 const utils = {
   FetchUtils,
   PaginationIterator,
@@ -131,7 +137,8 @@ export default {
   errors,
   models,
   services,
+  session,
   utils
 };
 
-export { errors, models, services, utils };
+export { errors, models, services, session, utils };
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/session/Session.js b/django_airavata/apps/api/static/django_airavata_api/js/session/Session.js
new file mode 100644
index 0000000..e27c25c
--- /dev/null
+++ b/django_airavata/apps/api/static/django_airavata_api/js/session/Session.js
@@ -0,0 +1,7 @@
+class Session {
+  init({ username }) {
+    this.username = username;
+  }
+}
+
+export default new Session();
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue
index b65f90a..b71cc14 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/storage/UserStoragePathViewer.vue
@@ -16,11 +16,11 @@
         <router-link
           v-if="data.item.type === 'dir'"
           :to="'/~/' + data.item.path"
-        >{{ data.item.name }}</router-link>
+        > <i class="fa fa-folder-open"></i> {{ data.item.name }}</router-link>
         <b-link
           v-else
           :href="data.item.downloadURL"
-        >{{ data.item.name }}</b-link>
+        > <i class="fa fa-download"></i> {{ data.item.name }}</b-link>
       </template>
       <template
         slot="createdTimestamp"
@@ -100,11 +100,11 @@ export default {
     },
     getFormattedSize(size) {
       if (size > Math.pow(2, 30)) {
-        return Math.round(size / Math.pow(2,30)) + " GB";
+        return Math.round(size / Math.pow(2, 30)) + " GB";
       } else if (size > Math.pow(2, 20)) {
-        return Math.round(size / Math.pow(2,20)) + " MB";
+        return Math.round(size / Math.pow(2, 20)) + " MB";
       } else if (size > Math.pow(2, 10)) {
-        return Math.round(size / Math.pow(2,10)) + " KB";
+        return Math.round(size / Math.pow(2, 10)) + " KB";
       } else {
         return size + " bytes";
       }
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/UserStorageContainer.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/UserStorageContainer.vue
index 4ec51a2..b198dd2 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/UserStorageContainer.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/UserStorageContainer.vue
@@ -1,9 +1,21 @@
 <template>
-  <router-view :user-storage-path="userStoragePath"></router-view>
+  <div class="row">
+    <div class="col">
+      <h1 class="h4">
+        Storage
+      </h1>
+      <p>
+        <small class="text-muted"><i class="fa fa-folder-open"></i> {{ username }}</small>
+      </p>
+      <b-card>
+        <router-view :user-storage-path="userStoragePath"></router-view>
+      </b-card>
+    </div>
+  </div>
 </template>
 
 <script>
-import { services, utils } from "django-airavata-api";
+import { services, session, utils } from "django-airavata-api";
 import { notifications } from "django-airavata-common-ui";
 
 export default {
@@ -15,6 +27,9 @@ export default {
       } else {
         return this.$route.path;
       }
+    },
+    username() {
+      return session.Session.username;
     }
   },
   data() {
diff --git a/django_airavata/static/common/js/entry.js b/django_airavata/static/common/js/entry.js
index 6dac815..8fae546 100644
--- a/django_airavata/static/common/js/entry.js
+++ b/django_airavata/static/common/js/entry.js
@@ -1,6 +1,7 @@
 import Vue from "vue";
 import BootstrapVue from "bootstrap-vue";
 import GlobalErrorHandler from "./errors/GlobalErrorHandler";
+import { session } from "django-airavata-api";
 
 GlobalErrorHandler.init();
 
@@ -19,5 +20,8 @@ export default function entry(entryPointFunction) {
   // Common Vue configuration
   Vue.use(BootstrapVue);
 
+  // Initialize portal session object with data provided by base.html template
+  session.Session.init(window.AiravataPortalSessionData);
+
   entryPointFunction(Vue);
 }
diff --git a/django_airavata/templates/base.html b/django_airavata/templates/base.html
index bff7358..01aeb99 100644
--- a/django_airavata/templates/base.html
+++ b/django_airavata/templates/base.html
@@ -230,6 +230,12 @@
     {% endblock %}
   </div>
 
+  <script>
+    // provide data for initializing api's session.Session
+    window.AiravataPortalSessionData = {
+      username: '{{ request.user.username }}'
+    };
+  </script>
   {% render_bundle 'chunk-vendors' 'js' 'COMMON' %}
   {% render_bundle 'app' 'js' 'COMMON' %}
   {% block scripts %}


[airavata-django-portal] 03/08: AIRAVATA-3034 Fixing double initial load of data

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 615713a4e353d0e46ed24c4aa1fcf22ac8106cc7
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Fri May 24 10:12:04 2019 -0400

    AIRAVATA-3034 Fixing double initial load of data
---
 .../django_airavata_workspace/js/containers/UserStorageContainer.vue   | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/UserStorageContainer.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/UserStorageContainer.vue
index 68fae77..4ec51a2 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/UserStorageContainer.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/UserStorageContainer.vue
@@ -54,8 +54,9 @@ export default {
   created() {
     if (this.$route.path === "/") {
       this.$router.replace("/~/");
+    } else {
+      this.loadUserStoragePath(this.storagePath);
     }
-    this.loadUserStoragePath(this.storagePath);
   },
   watch: {
     $route(to, from) {