diff --git a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/service/NodeInfo.java b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/service/NodeInfo.java index 74254a4f76914a9a8fa8daee13a00bedeab661ed..82d66fd030b6b9cb055ae41b4a423d9196989861 100644 --- a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/service/NodeInfo.java +++ b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/service/NodeInfo.java @@ -13,24 +13,25 @@ public class NodeInfo { private final String authority; - private final Node node; - private final String path; private final String name; private final String size; + private final String type; private final String groupRead; private final String groupWrite; private final boolean isPublic; + private final boolean asyncTrans; public NodeInfo(Node node, String authority) { this.authority = authority; - this.node = node; this.path = getPath(node); this.name = path.substring(path.lastIndexOf("/") + 1); this.size = getSize(node); + this.type = node.getType(); this.groupRead = getGroupRead(node); this.groupWrite = getGroupWrite(node); this.isPublic = isPublic(node); + this.asyncTrans = isAsyncTrans(node); } private String getPath(Node node) { @@ -55,7 +56,11 @@ public class NodeInfo { } private boolean isPublic(Node node) { - return Boolean.parseBoolean(getProperty(node, "ivo://ivoa.net/vospace/core#ispublic").orElse("false")); + return getProperty(node, "ivo://ivoa.net/vospace/core#ispublic").map(value -> "t".equals(value)).orElse(false); + } + + private boolean isAsyncTrans(Node node) { + return getProperty(node, "urn:async_trans").map(value -> "t".equals(value)).orElse(false); } private Optional<String> getProperty(Node node, String uri) { @@ -97,8 +102,12 @@ public class NodeInfo { return String.format("%.1f %cB", bytes / 1024f, " kMGTPE".charAt(u)); } - public String getType() { - return node.getType(); + public boolean isFolder() { + return "vos:ContainerNode".equals(type); + } + + public boolean isFile() { + return !"vos:ContainerNode".equals(type); } public String getPath() { @@ -124,4 +133,8 @@ public class NodeInfo { public boolean isPublic() { return isPublic; } + + public boolean isAsyncTrans() { + return asyncTrans; + } } diff --git a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/service/NodesService.java b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/service/NodesService.java index 8f5e6c6842d9e7a4c4478db09e63e9503d5685d8..b7aa7fb888c24caa27dd6b4cfc3e9a8be562aa98 100644 --- a/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/service/NodesService.java +++ b/vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/service/NodesService.java @@ -54,7 +54,11 @@ public class NodesService { } String html = "<tr>"; - html += "<td><input type=\"checkbox\" data-node=\"" + nodeInfo.getPath() + "\" /></td>"; + html += "<td><input type=\"checkbox\" data-node=\"" + nodeInfo.getPath() + "\" "; + if (nodeInfo.isAsyncTrans()) { + html += "class=\"async\""; + } + html += "/></td>"; html += "<td>" + getIcon(nodeInfo) + getLink(nodeInfo) + "</td>"; html += "<td>" + nodeInfo.getSize() + "</td>"; html += "<td>" + nodeInfo.getGroupRead() + "</td>"; @@ -65,18 +69,21 @@ public class NodesService { private String getIcon(NodeInfo nodeInfo) { String html = "<span class=\"icon "; - if ("vos:ContainerNode".equals(nodeInfo.getType())) { + if (nodeInfo.isFolder()) { html += "folder"; } else { html += "file"; } + if (nodeInfo.isAsyncTrans()) { + html += "-x"; + } html += "-icon\"></span> "; return html; } private String getLink(NodeInfo nodeInfo) { if (isDownloadable(nodeInfo)) { - if ("vos:ContainerNode".equals(nodeInfo.getType())) { + if (nodeInfo.isFolder()) { return "<a href=\"#/nodes" + nodeInfo.getPath() + "\">" + nodeInfo.getName() + "</a>"; } else { return "<a href=\"download" + nodeInfo.getPath() + "\" target=\"blank_\">" + nodeInfo.getName() + "</a>"; @@ -86,6 +93,9 @@ public class NodesService { } private boolean isDownloadable(NodeInfo nodeInfo) { + if (nodeInfo.isFile() && nodeInfo.isAsyncTrans()) { + return false; + } if (nodeInfo.isPublic()) { return true; } diff --git a/vospace-ui-frontend/src/api/mock/data/nodes/folder1.html b/vospace-ui-frontend/src/api/mock/data/nodes/folder1.html index ee2b379d89422fb314d982e9994b2cbf500cb2fb..3b878bdb8a97d2aac055c5f4d751fcdc5c5d7a36 100644 --- a/vospace-ui-frontend/src/api/mock/data/nodes/folder1.html +++ b/vospace-ui-frontend/src/api/mock/data/nodes/folder1.html @@ -1,6 +1,6 @@ <tbody id="nodes"> <tr> - <td><input type="checkbox" class="tape" data-node="/folder1/folder2" /></td> + <td><input type="checkbox" class="async" data-node="/folder1/folder2" /></td> <td> <span class="icon folder-x-icon"></span> <a href="#/nodes/folder1/folder2">folder2</a> @@ -20,7 +20,7 @@ <td>group2</td> </tr> <tr> - <td><input type="checkbox" class="tape" data-node="/folder1/file3" /></td> + <td><input type="checkbox" class="async" data-node="/folder1/file3" /></td> <td> <span class="icon file-x-icon"></span> file3 diff --git a/vospace-ui-frontend/src/api/mock/data/nodes/folder2.html b/vospace-ui-frontend/src/api/mock/data/nodes/folder2.html index b861b45707302c0210ff5dc45b595d7922f8ee36..24ac8b8461651c6d94e40c38467a50b68c157747 100644 --- a/vospace-ui-frontend/src/api/mock/data/nodes/folder2.html +++ b/vospace-ui-frontend/src/api/mock/data/nodes/folder2.html @@ -1,6 +1,6 @@ <tbody id="nodes"> <tr> - <td><input type="checkbox" class="tape" data-node="/folder1/folder2/file4" /></td> + <td><input type="checkbox" class="async" data-node="/folder1/folder2/file4" /></td> <td> <span class="icon file-x-icon"></span> file4 @@ -10,7 +10,7 @@ <td>group2</td> </tr> <tr> - <td><input type="checkbox" class="tape" data-node="/folder1/folder2/file5" /></td> + <td><input type="checkbox" class="async" data-node="/folder1/folder2/file5" /></td> <td> <span class="icon file-x-icon"></span> file5 diff --git a/vospace-ui-frontend/src/api/mock/index.js b/vospace-ui-frontend/src/api/mock/index.js index c0e10792f1eac713cdc4e987842f98d866b1bd63..7130ca50a19a857a26d46ab3cea9a06890ccc519 100644 --- a/vospace-ui-frontend/src/api/mock/index.js +++ b/vospace-ui-frontend/src/api/mock/index.js @@ -37,7 +37,7 @@ export default { } return fetch(response); }, - startRecallFromTapeJob() { + startAsyncRecallJob() { return fetch(job); }, loadJobs() { diff --git a/vospace-ui-frontend/src/api/server/index.js b/vospace-ui-frontend/src/api/server/index.js index dcba84eefa26c683bf972c42efecfa69de637234..92845514d34110c95902e7c091a65de4eff2aa3b 100644 --- a/vospace-ui-frontend/src/api/server/index.js +++ b/vospace-ui-frontend/src/api/server/index.js @@ -73,7 +73,7 @@ export default { } }, false, false); }, - startRecallFromTapeJob(paths) { + startAsyncRecallJob(paths) { let url = BASE_API_URL + 'recall'; return apiRequest({ method: 'POST', diff --git a/vospace-ui-frontend/src/components/Main.vue b/vospace-ui-frontend/src/components/Main.vue index 8f2ea80e629f59886349b9afa4f880c3a8899d2e..3b8fc6f971721b17d6992c0e2587e5bebf5de239 100644 --- a/vospace-ui-frontend/src/components/Main.vue +++ b/vospace-ui-frontend/src/components/Main.vue @@ -4,7 +4,7 @@ <div class="mb-3"> <b-button variant="success" class="mr-2" :disabled="false" v-b-modal.create-folder-modal>New folder</b-button> <b-button variant="success" class="mr-2" :disabled="false" v-b-modal.upload-files-modal>Upload files</b-button> - <b-button variant="primary" class="mr-2" v-if="tapeButtonEnabled" @click="startRecallFromTapeJob">Recall from tape</b-button> + <b-button variant="primary" class="mr-2" v-if="asyncButtonEnabled" @click="startAsyncRecallJob">Async recall</b-button> </div> <b-card> <table class="table b-table table-striped table-hover"> @@ -62,8 +62,8 @@ export default { } return items; }, - tapeButtonEnabled() { - return this.$store.state.tapeButtonEnabled || true; // temporary always true + asyncButtonEnabled() { + return this.$store.state.asyncButtonEnabled; } }, created() { @@ -88,8 +88,8 @@ export default { this.$store.dispatch('computeButtonVisibility'); }); }, - startRecallFromTapeJob() { - this.$store.dispatch('startRecallFromTapeJob'); + startAsyncRecallJob() { + this.$store.dispatch('startAsyncRecallJob'); } } } diff --git a/vospace-ui-frontend/src/store.js b/vospace-ui-frontend/src/store.js index b1b108f22f73daf8890056bfc6c754183c80cda3..848ce4567e58b3c48a6f54aef83e5111d4e0fb47 100644 --- a/vospace-ui-frontend/src/store.js +++ b/vospace-ui-frontend/src/store.js @@ -11,7 +11,7 @@ export default new Vuex.Store({ state: { path: '', loading: true, - tapeButtonEnabled: false, + asyncButtonEnabled: false, jobs: [], user: 'anonymous' }, @@ -25,8 +25,8 @@ export default new Vuex.Store({ } state.path = value; }, - setTapeButtonEnabled(state, value) { - state.tapeButtonEnabled = value; + setAsyncButtonEnabled(state, value) { + state.asyncButtonEnabled = value; }, setJobs(state, jobs) { // empty the array @@ -59,15 +59,15 @@ export default new Vuex.Store({ }); }, computeButtonVisibility({ commit }) { - commit('setTapeButtonEnabled', document.querySelectorAll('#nodes input.tape:checked').length > 0); + commit('setAsyncButtonEnabled', document.querySelectorAll('#nodes input.async:checked').length > 0); }, - startRecallFromTapeJob({ commit }) { - let tapeCheckboxes = document.querySelectorAll('#nodes input:checked'); // temporary: it should be input.tape + startAsyncRecallJob({ commit }) { + let asyncCheckboxes = document.querySelectorAll('#nodes input.async:checked'); let paths = []; - for (let i = 0; i < tapeCheckboxes.length; i++) { - paths.push(tapeCheckboxes[i].getAttribute('data-node')); + for (let i = 0; i < asyncCheckboxes.length; i++) { + paths.push(asyncCheckboxes[i].getAttribute('data-node')); } - client.startRecallFromTapeJob(paths) + client.startAsyncRecallJob(paths) .then(job => { main.showInfo('Job started'); commit('addJob', job);