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> <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)">×</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