From a678d7025b7774aecad38b485da69831043adce6 Mon Sep 17 00:00:00 2001
From: Sonia Zorba <sonia.zorba@inaf.it>
Date: Tue, 16 Mar 2021 17:20:43 +0100
Subject: [PATCH] Started Sharing modal implementation

---
 .../src/api/mock/data/nodes/root.json         |   2 +-
 vospace-ui-frontend/src/assets/css/fonts.css  |  12 ++
 vospace-ui-frontend/src/components/Main.vue   |   5 +-
 .../src/components/modal/ShareModal.vue       | 115 ++++++++++++++++++
 vospace-ui-frontend/src/main.js               |   4 +
 vospace-ui-frontend/src/store.js              |  12 +-
 6 files changed, 147 insertions(+), 3 deletions(-)
 create mode 100644 vospace-ui-frontend/src/components/modal/ShareModal.vue

diff --git a/vospace-ui-frontend/src/api/mock/data/nodes/root.json b/vospace-ui-frontend/src/api/mock/data/nodes/root.json
index 6014d41..e0e2b8c 100644
--- a/vospace-ui-frontend/src/api/mock/data/nodes/root.json
+++ b/vospace-ui-frontend/src/api/mock/data/nodes/root.json
@@ -1,4 +1,4 @@
 {
   "writable": true,
-  "htmlTable": "<tbody id=\"nodes\">  <tr>    <td><input type=\"checkbox\" class=\"deletable\" data-node=\"/folder1\" /></td>    <td>      <span class=\"icon folder-icon\"></span>      <a href=\"#/nodes/folder1\">folder1</a>    </td>    <td>0 B</td>    <td>group1</td>    <td>group2</td>    <td>      <span class=\"icon trash-icon pointer\" onclick=\"deleteNode('/folder1')\"></span>    </td>  </tr>  <tr>    <td><input type=\"checkbox\" data-node=\"/file1\" /></td>    <td>      <span class=\"icon file-icon\"></span>      <a href=\"download/file1\">file1</a>    </td>    <td>12 MB</td>    <td>group1</td>    <td>group2</td>    <td></td>  </tr></tbody>"
+  "htmlTable": "<tbody id=\"nodes\">  <tr>    <td><input type=\"checkbox\" class=\"deletable\" data-node=\"/folder1\" /></td>    <td>      <span class=\"icon folder-icon\"></span>      <a href=\"#/nodes/folder1\">folder1</a>    </td>    <td>0 B</td>    <td data-groupread=\"[\"people.group1\",\"group2\"]\"><span class=\"icon person-icon\"></span>group1 <span class=\"icon people-icon\"></span>group2</td>    <td>group2</td>    <td>      <span class=\"icon share-icon pointer\" onclick=\"shareNode('/folder1','group1','people.group2')\"></span> &nbsp; <span class=\"icon trash-icon pointer\" onclick=\"deleteNode('/folder1')\"></span>    </td>  </tr>  <tr>    <td><input type=\"checkbox\" data-node=\"/file1\" /></td>    <td>      <span class=\"icon file-icon\"></span>      <a href=\"download/file1\">file1</a>    </td>    <td>12 MB</td>    <td>group1</td>    <td>group2</td>    <td></td>  </tr></tbody>"
 }
diff --git a/vospace-ui-frontend/src/assets/css/fonts.css b/vospace-ui-frontend/src/assets/css/fonts.css
index 1041dbd..29beec4 100644
--- a/vospace-ui-frontend/src/assets/css/fonts.css
+++ b/vospace-ui-frontend/src/assets/css/fonts.css
@@ -32,3 +32,15 @@
 .folder-link-icon {
   background-image: url("data:image/svg+xml,%3Csvg data-v-41be6633='' viewBox='0 0 16 16' width='1em' height='1em' focusable='false' role='img' aria-label='folder symlink' xmlns='http://www.w3.org/2000/svg' fill='currentColor' class='bi-folder-symlink mx-auto b-icon bi'%3E%3Cg data-v-41be6633=''%3E%3Cpath d='M11.798 8.271l-3.182 1.97c-.27.166-.616-.036-.616-.372V9.1s-2.571-.3-4 2.4c.571-4.8 3.143-4.8 4-4.8v-.769c0-.336.346-.538.616-.371l3.182 1.969c.27.166.27.576 0 .742z'%3E%3C/path%3E%3Cpath d='M.5 3l.04.87a1.99 1.99 0 0 0-.342 1.311l.637 7A2 2 0 0 0 2.826 14h10.348a2 2 0 0 0 1.991-1.819l.637-7A2 2 0 0 0 13.81 3H9.828a2 2 0 0 1-1.414-.586l-.828-.828A2 2 0 0 0 6.172 1H2.5a2 2 0 0 0-2 2zm.694 2.09A1 1 0 0 1 2.19 4h11.62a1 1 0 0 1 .996 1.09l-.636 7a1 1 0 0 1-.996.91H2.826a1 1 0 0 1-.995-.91l-.637-7zM6.172 2a1 1 0 0 1 .707.293L7.586 3H2.19c-.24 0-.47.042-.684.12L1.5 2.98a1 1 0 0 1 1-.98h3.672z'%3E%3C/path%3E%3C/g%3E%3C/svg%3E");
 }
+
+.share-icon {
+  background-image: url("data:image/svg+xml,%3Csvg data-v-41be6633='' viewBox='0 0 16 16' width='1em' height='1em' focusable='false' role='img' aria-label='share' xmlns='http://www.w3.org/2000/svg' fill='%230056b3' class='bi-share mx-auto b-icon bi'%3E%3Cg data-v-41be6633=''%3E%3Cpath d='M13.5 1a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3zM11 2.5a2.5 2.5 0 1 1 .603 1.628l-6.718 3.12a2.499 2.499 0 0 1 0 1.504l6.718 3.12a2.5 2.5 0 1 1-.488.876l-6.718-3.12a2.5 2.5 0 1 1 0-3.256l6.718-3.12A2.5 2.5 0 0 1 11 2.5zm-8.5 4a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3zm11 5.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3z'%3E%3C/path%3E%3C/g%3E%3C/svg%3E");
+}
+
+.people-icon {
+  background-image: url("data:image/svg+xml,%3Csvg data-v-41be6633='' viewBox='0 0 16 16' width='1em' height='1em' focusable='false' role='img' aria-label='people fill' xmlns='http://www.w3.org/2000/svg' fill='currentColor' class='bi-people-fill mx-auto b-icon bi'%3E%3Cg data-v-41be6633=''%3E%3Cpath d='M7 14s-1 0-1-1 1-4 5-4 5 3 5 4-1 1-1 1H7zm4-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6z'%3E%3C/path%3E%3Cpath fill-rule='evenodd' d='M5.216 14A2.238 2.238 0 0 1 5 13c0-1.355.68-2.75 1.936-3.72A6.325 6.325 0 0 0 5 9c-4 0-5 3-5 4s1 1 1 1h4.216z'%3E%3C/path%3E%3Cpath d='M4.5 8a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5z'%3E%3C/path%3E%3C/g%3E%3C/svg%3E");
+}
+
+.person-icon {
+  background-image: url("data:image/svg+xml,%3Csvg data-v-41be6633='' viewBox='0 0 16 16' width='1em' height='1em' focusable='false' role='img' aria-label='person fill' xmlns='http://www.w3.org/2000/svg' fill='currentColor' class='bi-person-fill mx-auto b-icon bi'%3E%3Cg data-v-41be6633=''%3E%3Cpath d='M3 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H3zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6z'%3E%3C/path%3E%3C/g%3E%3C/svg%3E");
+}
diff --git a/vospace-ui-frontend/src/components/Main.vue b/vospace-ui-frontend/src/components/Main.vue
index 2fef31c..4a5af17 100644
--- a/vospace-ui-frontend/src/components/Main.vue
+++ b/vospace-ui-frontend/src/components/Main.vue
@@ -33,6 +33,7 @@
   <CreateFolderModal />
   <UploadFilesModal />
   <ConfirmDeleteModal />
+  <ShareModal />
 </div>
 </template>
 
@@ -41,6 +42,7 @@ import { BIconCheckSquare, BIconSquare } from 'bootstrap-vue'
 import CreateFolderModal from './modal/CreateFolderModal.vue'
 import UploadFilesModal from './modal/UploadFilesModal.vue'
 import ConfirmDeleteModal from './modal/ConfirmDeleteModal.vue'
+import ShareModal from './modal/ShareModal.vue'
 
 export default {
   components: {
@@ -48,7 +50,8 @@ export default {
     BIconSquare,
     CreateFolderModal,
     UploadFilesModal,
-    ConfirmDeleteModal
+    ConfirmDeleteModal,
+    ShareModal
   },
   computed: {
     breadcrumbs() {
diff --git a/vospace-ui-frontend/src/components/modal/ShareModal.vue b/vospace-ui-frontend/src/components/modal/ShareModal.vue
new file mode 100644
index 0000000..ae9c9df
--- /dev/null
+++ b/vospace-ui-frontend/src/components/modal/ShareModal.vue
@@ -0,0 +1,115 @@
+<template>
+<b-modal id="share-modal" :title="'Share ' + node.path" okTitle="Share" @show="reset" @ok="share" size="lg">
+  <h5>Read permissions</h5>
+  <div class="row">
+    <div class="col-2">
+      <label for="user-read-input" class="mt-2 float-right"><strong>Users</strong></label>
+    </div>
+    <div class="col">
+      <b-input-group>
+        <b-form-input list="user-read-list" id="user-read-input" placeholder="Search user..."></b-form-input>
+        <datalist id="user-read-list">
+          <option v-for="user in selectableUserRead" v-bind:key="user.id">{{user.label}}</option>
+        </datalist>
+        <b-input-group-append>
+          <b-button variant="success">Add user</b-button>
+        </b-input-group-append>
+      </b-input-group>
+    </div>
+  </div>
+  <div class="row">
+    <div class="col offset-2">
+      <b-badge variant="light" v-for="user in userRead" v-bind:key="user">{{user}}</b-badge>
+    </div>
+  </div>
+  <div class="row">
+    <div class="col-2">
+      <label for="group-read-input" class="mt-2 float-right"><strong>Groups</strong></label>
+    </div>
+    <div class="col">
+      <b-input-group>
+        <b-form-input list="group-read-list" id="group-read-input" placeholder="Search group..."></b-form-input>
+        <datalist id="group-read-list">
+          <option v-for="group in selectableGroupRead" v-bind:key="group">{{group}}</option>
+        </datalist>
+        <b-input-group-append>
+          <b-button variant="success">Add group</b-button>
+        </b-input-group-append>
+      </b-input-group>
+    </div>
+  </div>
+  <div class="row">
+    <div class="col offset-2">
+      <b-badge variant="primary" v-for="group in groupRead" size="lg" v-bind:key="group">
+        {{group}}
+        <span class="pointer" @click="removeItem(groupRead, group)">&times;</span>
+      </b-badge>
+    </div>
+  </div>
+  <h5 class="mt-3">Write permissions</h5>
+  <b-form inline>
+  </b-form>
+</b-modal>
+</template>
+
+<script>
+export default {
+  computed: {
+    node() { return this.$store.state.nodeToShare; }
+  },
+  data() {
+    return {
+      userReadInput: null,
+      groupReadInput: null,
+      selectableUserRead: [],
+      selectableGroupRead: [],
+      groupRead: [],
+      userRead: [],
+      userWriteInput: null,
+      groupWriteInput: null,
+      selectableUserWrite: [],
+      selectableGroupWrite: [],
+      groupWrite: [],
+      userWrite: []
+    }
+  },
+  methods: {
+    reset() {
+      this.setGroups(this.userRead, this.groupRead, this.node.groupRead);
+      this.setGroups(this.userWrite, this.groupWrite, this.node.groupWrite);
+    },
+    setGroups(userArr, groupArr, nodeArr) {
+      userArr.splice(0, userArr.length);
+      groupArr.splice(0, groupArr.length);
+      for (let group of nodeArr.split(' ')) {
+        if (group.startsWith('people.')) {
+          userArr.push(group.substring('people.'.length).replaceAll('\\\\', '\\'));
+        } else {
+          groupArr.push(group.replaceAll('\\\\', '\\'));
+        }
+      }
+    },
+    addItem(arr, value) {
+      const index = arr.indexOf(value);
+      if (index === -1) {
+        arr.push(value);
+      }
+    },
+    removeItem(arr, value) {
+      const index = arr.indexOf(value);
+      if (index > -1) {
+        arr.splice(index, 1);
+      }
+    },
+    share() {
+      // TODO
+    }
+  }
+}
+</script>
+
+<style>
+#share-modal .badge {
+  font-size: 100%;
+}
+</style>
diff --git a/vospace-ui-frontend/src/main.js b/vospace-ui-frontend/src/main.js
index 4c7c315..7810c50 100644
--- a/vospace-ui-frontend/src/main.js
+++ b/vospace-ui-frontend/src/main.js
@@ -22,6 +22,10 @@ window.deleteNode = function(path) {
   store.commit('setNodesToDelete', [path]);
   vm.$bvModal.show('confirm-delete-modal');
 }
+window.shareNode = function(path, groupRead, groupWrite) {
+  store.commit('setNodeToShare', { path, groupRead, groupWrite });
+  vm.$bvModal.show('share-modal');
+}
 
 export default {
   showError(message) {
diff --git a/vospace-ui-frontend/src/store.js b/vospace-ui-frontend/src/store.js
index 87f5478..13f4791 100644
--- a/vospace-ui-frontend/src/store.js
+++ b/vospace-ui-frontend/src/store.js
@@ -26,7 +26,12 @@ export default new Vuex.Store({
     jobsLoading: true,
     user: 'anonymous',
     nodesToDelete: [],
-    writable: false
+    writable: false,
+    nodeToShare: {
+      path: null,
+      groupRead: null,
+      groupWrite: null
+    }
   },
   mutations: {
     setLoading(state, loading) {
@@ -61,6 +66,11 @@ export default new Vuex.Store({
     },
     setWritable(state, value) {
       state.writable = value;
+    },
+    setNodeToShare(state, data) {
+      state.nodeToShare.path = data.path;
+      state.nodeToShare.groupRead = data.groupRead;
+      state.nodeToShare.groupWrite = data.groupWrite;
     }
   },
   actions: {
-- 
GitLab