diff --git a/storage/d4s-storage.js b/storage/d4s-storage.js index 8694320..618b3f8 100644 --- a/storage/d4s-storage.js +++ b/storage/d4s-storage.js @@ -5,168 +5,306 @@ var D4S_STORAGE_SCRIPT = document.currentScript */ class D4SStorageHtmlElement extends HTMLElement { - #d4smissmsg = 'Required d4s-boot-2 component not found' - #baseurl = 'https://api.d4science.org/workspace' - //#baseurl = 'https://workspace-repository.dev.d4science.org/storagehub/workspace' - #boot = null - #d4sworkspace = null; - #showroot = false; // To show WS root folder by default set it to true + #srcbaseurl = null + + constructor() { + super() + if (D4S_STORAGE_SCRIPT && D4S_STORAGE_SCRIPT.src) { + this.#srcbaseurl = D4S_STORAGE_SCRIPT.src.substring(0, D4S_STORAGE_SCRIPT.src.lastIndexOf('/')); + } + this.attachShadow({mode: 'open'}) + } + + static appendBootstrapStylesheets(root) { + let linkElem = document.createElement('link'); + linkElem.setAttribute('rel', 'stylesheet'); + linkElem.setAttribute('href', 'https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css'); + root.appendChild(linkElem); + } + + get srcBaseURL() { + return this.#srcbaseurl; + } + +} + +class D4SStorageToolbar extends HTMLElement { + + static toolbar_event_name = "d4s-toolbar"; + + static refresh_folder = "refresh-folder"; + static create_folder = "create-folder"; + static delete_folder = "delete-folder"; + static download = "download"; + static upload_file = "upload-file"; + static upload_archive = "upload-archive"; + + #last_action = null; constructor() { super() - this.#boot = document.querySelector('d4s-boot-2') - this.#d4sworkspace = new D4SWorkspace(this.#baseurl, this.#boot) + this.attachShadow({mode: 'open'}) + } + + connectedCallback() { + D4SStorageHtmlElement.appendBootstrapStylesheets(this.shadowRoot); + + var div = document.createElement('div'); + div.innerHTML = /*html*/` +
+ Refresh folder contents + Create new folder + Delete folder + Download folder as ZIP + Upload file + Upload archive +
`; + div.querySelector("#refresh").addEventListener('click', (ev) => { + ev.stopPropagation(); + this.actionPerformed(D4SStorageToolbar.refresh_folder); + }); + div.querySelector("#create").addEventListener('click', (ev) => { + ev.stopPropagation(); + this.actionPerformed(D4SStorageToolbar.create_folder); + }); + div.querySelector("#delete").addEventListener('click', (ev) => { + ev.stopPropagation(); + this.actionPerformed(D4SStorageToolbar.delete_folder); + }); + div.querySelector("#download").addEventListener('click', (ev) => { + ev.stopPropagation(); + this.actionPerformed(D4SStorageToolbar.download); + }); + div.querySelector("#upload-file").addEventListener('click', (ev) => { + ev.stopPropagation(); + this.actionPerformed(D4SStorageToolbar.upload_file); + }); + div.querySelector("#upload-archive").addEventListener('click', (ev) => { + ev.stopPropagation(); + this.actionPerformed(D4SStorageToolbar.upload_archive); + }); + this.shadowRoot.appendChild(div); + } + + actionPerformed(action) { + this.#last_action = action; + this.dispatchEvent(new CustomEvent(D4SStorageToolbar.toolbar_event_name, {detail: action})); + } + + get lastAction() { + return this.#last_action; + } + +} + +class D4SStorageTree extends D4SStorageHtmlElement { + + static tree_event_name = "d4s-toolbar"; + static folder_data_event_name = "d4s-folder-data"; + + static dataid_attr = 'data-id'; + static dataname_attr = 'data-name'; + static parentid_attr = 'parent-id'; + + #loadedClass = 'loaded' + #selectedClass = 'selected' + #selectedbgcolor = 'lightgray' + + #boot = null + #baseurl = 'https://api.d4science.org/workspace' + #d4sworkspace = null; + #foldersMap = {}; + #currentid = null; + + constructor() { + super() + this.#boot = document.querySelector('d4s-boot-2'); + this.#d4sworkspace = new D4SWorkspace(this.#baseurl, this.#boot); } get boot() { - if (this.#boot == null) { - this.#boot = document.querySelector('d4s-boot-2') - if (!this.#boot) { - throw this.#d4smissmsg - } - } - return this.#boot + return this.#boot; } - - appendStylesheets(root) { - const linkElem1 = document.createElement('link') - linkElem1.setAttribute('rel', 'stylesheet') - linkElem1.setAttribute('href', 'https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css') - root.appendChild(linkElem1) - } - - buildListUrl(id) { - return this.#baseurl + '/items/' + id + '/children' - } - get baseUrl() { - return this.#baseurl + return this.#baseurl; } set baseUrl(url) { - this.#baseurl = url - this.setAttribute("baseurl", url) - this.#d4sworkspace = new D4SWorkspace(this.#baseurl, this.#boot) + this.#baseurl = url; + // this.setAttribute("baseurl", url) + this.#d4sworkspace = new D4SWorkspace(this.#baseurl, this.#boot); } get d4sWorkspace() { return this.#d4sworkspace; } - get showRoot() { - return this.#showroot; + set currentId(id) { + this.#currentid = id; } - set showRoot(show) { - this.#showroot = show; + get currentId() { + return this.#currentid; } -} - - -/** - * Builds storagehub VREFolder tree - * and if "id": "e0cd15d2-0071-43ca-bc42-aef8d80660fe", - the tree dir of vrefolder: https://storagehub.pre.d4science.net/storagehub/workspace/items/e0cd15d2-0071-43ca-bc42-aef8d80660fe/children - download of a file (domenica.jpg): https://storagehub.pre.d4science.net/storagehub/workspace/items/a5086811-59d1-4230-99fa-98431e820cf1/download - */ connectedCallback() { - this.appendStylesheets(this.#shadowRoot) + D4SStorageHtmlElement.appendBootstrapStylesheets(this.shadowRoot) var div = document.createElement('div') - const style = ` + div.innerHTML = /*css*/` - ` - div.innerHTML = style + `; - const initalFolderFunction = (cond) => {if (cond) return this.d4sWorkspace.getWorkspace(); else return this.d4sWorkspace.getVREFolder();} - initalFolderFunction(this.showRoot).then(data => { - this.parseResponse(div, data); - this.#shadowRoot.appendChild(div); + this.shadowRoot.appendChild(div); + + this.d4sWorkspace.getWorkspace().then(data => { + this.parseItemsData(div, data); + }).catch(err => console.error(err)); + + this.d4sWorkspace.getVREFolder().then(data => { + this.parseItemsData(div, data); }).catch(err => console.error(err)) - } - parseResponse(parentElement, data) { - parentElement.classList.add(this.#loadedClass); - var ul = document.createElement('ul'); - ul.classList.add('nested'); - if (Array.isArray(data)) { - data - .filter(item => item['@class'].includes('FolderItem')) - .forEach(item => { - const itemName = item.name; - const itemId = item.id; - const path = this.buildListUrl(itemId); - ul.appendChild(this.createListItem(itemName, itemId)); - }) - parentElement.appendChild(ul); + this.addEventListener(D4SStorageTree.tree_event_name, this.localEventHandler); + this.addEventListener(D4SStorageTree.folder_data_event_name, this.folderDataEventHandler); + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", this.registerOtherListeners.bind(this)); } else { - const itemName = data.displayName ? data.displayName : data.name; - const itemId = data.id; - const path = this.buildListUrl(itemId); - ul.appendChild(this.createListItem(itemName, itemId)); - parentElement.appendChild(ul); + this.registerListeners(); } } - createListItem(label, id) { - var li = document.createElement('li') - li.setAttribute('data-id', id) - var child = document.createElement('span') - child.innerHTML = label - li.appendChild(child) + disconnectedCallback() { + this.removeEventListener(D4SStorageTree.tree_event_name); + this.removeEventListener(D4SStorageTree.folder_data_event_name); + const toolbar = document.querySelector("d4s-storage-tool"); + if (toolbar) toolbar.removeEventListener(D4SStorageToolbar.toolbar_event_name); + const folder = document.querySelector("d4s-storage-folder"); + if (folder) folder.removeEventListener(D4SStorageFolder.selected_event_name); + } - li.addEventListener('click', (ev) => { - ev.stopPropagation() - this.select(ev.currentTarget.getAttribute('data-id')) - }) - return li + registerOtherListeners(event) { + const toolbar = document.querySelector("d4s-storage-tool"); + if (toolbar) toolbar.addEventListener(D4SStorageToolbar.toolbar_event_name, this.toolbarEventHandler.bind(this)); + const folder = document.querySelector("d4s-storage-folder"); + if (folder) folder.addEventListener(D4SStorageFolder.selected_event_name, this.folderEventHandler.bind(this)); + } + + localEventHandler(event) { + this.select(event.detail); + } + + folderDataEventHandler(event) { + if (event.detail === this.currentId) { + this.fillWithContent(this.shadowRoot.querySelector(`*[${D4SStorageTree.dataid_attr}='${this.currentId}']`)) + } + } + + toolbarEventHandler(event) { + switch (event.detail) { + case D4SStorageToolbar.refresh_folder: + if (this.currentId) { + this.refreshFolder(this.currentId); + } + break; + case D4SStorageToolbar.create_folder: + if (this.currentId) { + this.createNewFolderIn(this.currentId); + } + break; + case D4SStorageToolbar.delete_folder: + if (this.currentId) { + this.delete(this.currentId); + } + break; + case D4SStorageToolbar.download: + if (this.currentId) { + const name = this.shadowRoot.querySelector(`*[${D4SStorageTree.dataid_attr}='${this.currentId}']`).getAttribute(D4SStorageTree.dataname_attr); + this.d4sWorkspace.download(this.currentId, name); + } + break; + case D4SStorageToolbar.upload_file: + var file = document.createElement('input'); + file.type = 'file'; + file.addEventListener('change', (ev) => { + const selectedFile = file.files[0]; + if (selectedFile) { + this.uploadFile(this.currentId, selectedFile); + } + }); + file.click(); + break; + case D4SStorageToolbar.upload_archive: + var file = document.createElement('input'); + file.type = 'file'; + file.addEventListener('change', (ev) => { + const selectedFile = file.files[0]; + if (selectedFile) { + this.uploadArchive(this.currentId, selectedFile); + } + }); + file.click(); + break; + default: + console.error('Unexpected event action: ' + event.action); + break; + } + } + + folderEventHandler(event) { + switch (event.detail.itemtype) { + case D4SStorageFolder.file_selected_detail_itemtype: + console.info("Download of file: " + event.detail.name + " [" + event.detail.id + "]"); + this.d4sWorkspace.download(event.detail.id, event.detail.name).catch(err => {alert(err)}); + break; + case D4SStorageFolder.folder_selected_detail_itemtype: + this.select(event.detail.id); + break; + default: + console.warn("Unexpected folder event: " + event.detail.itemtype); + break; + } } select(id) { - var li = this.shadowRoot.querySelector(`*[data-id='${id}']`) - this.displayPath(li) + this.currentId = id; + var li = this.shadowRoot.querySelector(`*[${D4SStorageTree.dataid_attr}='${id}']`); + this.displayPath(li); - // if it was already selected then do nothing if (li.classList.contains(this.#selectedClass)) { - this.toggleULDisplay(li) - return + this.toggleULDisplay(li); } // switch selected and lists folder contents if (!li.classList.contains(this.#selectedClass)) { @@ -175,19 +313,73 @@ window.customElements.define('d4s-storage-tree', class extends D4SStorageHtmlEle selected.classList.remove(this.#selectedClass) } li.classList.add(this.#selectedClass) - if (this.#storageFilelistId) { - var folder = document.getElementById(this.#storageFilelistId) - folder.join(this) - folder.list(id) - } } if (li.classList.contains(this.#loadedClass)) { return } - this.d4sWorkspace.listFolder(id).then(data => { - this.parseResponse(li, data) - }).catch(err => console.error(err)) + this.fillWithContent(li); + } + + refreshContents(element) { + [...element.querySelectorAll(`ul`)].forEach(ul => { + ul.remove(); + }); + this.fillWithContent(element); + } + + fillWithContent(element) { + const id = element.getAttribute(D4SStorageTree.dataid_attr); + if (this.#foldersMap[id]) { + this.parseItemsData(element, this.#foldersMap[id]); + } else { + this.d4sWorkspace.listFolder(id).then(data => { + this.setFolderItems(id, data); + }).catch(err => console.error(err)); + } + } + + parseItemsData(parentElement, data) { + parentElement.classList.add(this.#loadedClass); + const parentId = parentElement.getAttribute(D4SStorageTree.dataid_attr); + var ul = document.createElement('ul'); + ul.classList.add('nested'); + if (!parentId) { + ul.classList.add('root'); + } + if (Array.isArray(data)) { + data + .filter(item => item['@class'].includes('FolderItem')) + .forEach(item => { + ul.appendChild(this.createListItem(item.name, item.id, parentId)); + }) + } else { + ul.appendChild(this.createListItem(data.displayName ? data.displayName : data.name, data.id, parentId)); + } + parentElement.appendChild(ul); + } + + createListItem(label, id, parentId) { + const li = document.createElement('li'); + li.setAttribute(D4SStorageTree.dataname_attr, label); + li.setAttribute(D4SStorageTree.dataid_attr, id); + if (parentId) { + li.setAttribute(D4SStorageTree.parentid_attr, parentId); + } + var child = document.createElement('span'); + child.innerHTML = /*html*/`` + label; + li.appendChild(child) + + li.addEventListener('click', (ev) => { + ev.stopPropagation(); + this.dispatchEvent( + new CustomEvent( + D4SStorageTree.tree_event_name, + {detail: ev.currentTarget.getAttribute(D4SStorageTree.dataid_attr)} + ) + ); + }) + return li; } displayPath(li) { @@ -208,60 +400,98 @@ window.customElements.define('d4s-storage-tree', class extends D4SStorageHtmlEle } static get observedAttributes() { - return ["base-url", "filelist-id", "show-root"] + return ["base-url"]; } attributeChangedCallback(name, oldValue, newValue) { if (oldValue !== newValue) { switch (name) { - case "filelist-id": - this.#storageFilelistId = newValue - break case "base-url": this.baseUrl = newValue break - case "show-root": - this.showRoot = newValue; + default: + console.warn("Unexpected attribute changed: " + name); } } } - get filelistId() { - return this.#storageFilelistId + refreshFolder(id) { + const folder = this.shadowRoot.querySelector(`*[${D4SStorageTree.dataid_attr}='${id}']`); + console.log("Refreshing folder: " + folder.getAttribute(D4SStorageTree.dataname_attr)); + this.refreshContents(folder); + this.select(id); } - set filelistId(id) { - this.#storageFilelistId = id - this.setAttribute("filelist-id", id) - } -}) - -/** - * Lists elements in selected folder - * - * { + window.setTimeout(()=>{ + this.refreshContents(this.shadowRoot.querySelector(`*[${D4SStorageTree.dataid_attr}='${id}']`)); + this.select(id); + }, 2000); + }).catch(err => { + alert(err); + }) } } + delete(id) { + const currentLI = this.shadowRoot.querySelector(`*[${D4SStorageTree.dataid_attr}='${id}']`); + const name = currentLI.getAttribute(D4SStorageTree.dataname_attr); + if (currentLI.getAttribute(D4SStorageTree.parentid_attr)) { + if (confirm(`Do you really want to delete folder '${name}'?`)) { + if(this.d4sWorkspace.deleteItem(id)) { + window.setTimeout(()=>{ + const parentFolderId = currentLI.getAttribute(D4SStorageTree.parentid_attr); + this.refreshContents(this.shadowRoot.querySelector(`*[${D4SStorageTree.dataid_attr}='${parentFolderId}']`)); + this.select(parentFolderId); + }, 2000); + } else { + alert(err); + } + } + } else { + alert("You cannot delete ROOT folder: "+ name); + } + } + + uploadFile(targetFolderId, file) { + if (this.d4sWorkspace.uploadFile(targetFolderId, file.name, "", file, file.type)) { + window.setTimeout(()=>{ + this.select(targetFolderId); + }, 2000); + } + } + + uploadArchive(targetFolderId, file) { + if (this.d4sWorkspace.uploadArchive(targetFolderId, file.name.substring(0, file.name.lastIndexOf(".")), file)) { + window.setTimeout(()=>{ + this.refreshContents(this.shadowRoot.querySelector(`*[${D4SStorageTree.dataid_attr}='${targetFolderId}']`)); + this.select(targetFolderId); + }, 3000); + } + } + +} + +class D4SStorageFolder extends D4SStorageHtmlElement { + + static selected_event_name = "d4s-folder-selected"; + + static folder_selected_detail_itemtype = "folder_selected"; + static file_selected_detail_itemtype = "file_selected"; + + #selectedbgcolor = 'lightgray' + + constructor() { + super() + } + connectedCallback() { - const shadowRoot = this.attachShadow({mode: 'open'}) - this.appendStylesheets(shadowRoot) + D4SStorageHtmlElement.appendBootstrapStylesheets(this.shadowRoot); const style = document.createElement('style') - style.innerHTML = ` + style.innerHTML = /*css*/` span { cursor: pointer; user-select: none; @@ -270,8 +500,48 @@ window.customElements.define('d4s-storage-folder', class extends D4SStorageHtmlE -ms-user-select: none; } ` - shadowRoot.appendChild(style) - this.createContainer() + this.shadowRoot.appendChild(style); + this.createContainer(); + + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", this.registerOtherListeners.bind(this)); + } else { + this.registerListeners(); + } + } + + disconnectedCallback() { + const tree = document.querySelector("d4s-storage-tree"); + if (tree) { + tree.removeEventListener(D4SStorageTree.tree_event_name); + tree.removeEventListener(D4SStorageTree.folder_data_event_name); + } + } + + registerOtherListeners(event) { + const tree = document.querySelector("d4s-storage-tree"); + if (tree) { + tree.addEventListener(D4SStorageTree.tree_event_name, this.treeEventHandler.bind(this)); + tree.addEventListener(D4SStorageTree.folder_data_event_name, this.folderDataEventHandler.bind(this)); + } + } + + treeEventHandler(event) { + const folderItems = event.target.getFolderItems(event.detail); + if (folderItems) { + // It's first time folder is selected, data is stil not loaded, + // they will be loaded by the folderDataEventHandler() function when available + this.parseItemsData(folderItems); + } + } + + folderDataEventHandler(event) { + if (event.detail === event.target.currentId) { + const folderItems = event.target.getFolderItems(event.detail); + if (folderItems) { + this.parseItemsData(folderItems); + } + } } createContainer() { @@ -285,19 +555,7 @@ window.customElements.define('d4s-storage-folder', class extends D4SStorageHtmlE return div } - join(tree) { - if (this.#d4sstorageTree == null) { - this.#d4sstorageTree = tree - } - } - - list(folderId) { - this.d4sWorkspace.listFolder(folderId).then(data => { - this.parseResponse(data); - }).catch(err => console.error(err)); - } - - parseResponse(data) { + parseItemsData(data) { const root = this.createContainer(); if (Array.isArray(data)) { data.forEach(item => root.appendChild(this.createFileRow(item))); @@ -311,8 +569,8 @@ window.customElements.define('d4s-storage-folder', class extends D4SStorageHtmlE div.classList.add('row') var filename = document.createElement('div') filename.classList.add('col') - var name = `${item.name}` - filename.innerHTML = this.iconTag(item) + name + var spanAndName = /*html*/`${item.name}` + filename.innerHTML = this.iconTag(item) + spanAndName const isFolder = item['@class'].includes('FolderItem') filename.addEventListener('click', (ev) => { ev.stopPropagation() @@ -321,12 +579,19 @@ window.customElements.define('d4s-storage-folder', class extends D4SStorageHtmlE if (span) { span.style = 'background-color: ' + this.#selectedbgcolor } - if (this.#d4sstorageTree != null) { - this.#d4sstorageTree.select(item.id) - } + this.dispatchEvent( + new CustomEvent( + D4SStorageFolder.selected_event_name, + {detail: {itemtype: D4SStorageFolder.folder_selected_detail_itemtype, id: item.id, name: item.name}} + ) + ); } else { - console.info("Download of " + item.id) - this.d4sWorkspace.download(item.id, item.name).catch(err => {alert(err)}); + this.dispatchEvent( + new CustomEvent( + D4SStorageFolder.selected_event_name, + {detail: {itemtype: D4SStorageFolder.file_selected_detail_itemtype, id: item.id, name: item.name}} + ) + ); } }) @@ -335,56 +600,18 @@ window.customElements.define('d4s-storage-folder', class extends D4SStorageHtmlE } iconTag(item) { - var i = `` + var i = /*html*/`` if (item['@class'].includes('FolderItem')) { - i = `` + i = /*html*/`` } else if (item['@class'].includes('ImageFile')) { - i = `` + i = /*html*/`` } else if (item['@class'].includes('PDFFileItem')) { - i = `` + i = /*html*/`` } return '' + i + '' } - // buildDownloadUrl(id) { - // return this.baseUrl+ '/items/' + id + '/download' - // } - - // download(url, name) { - // this.d4sWorkspace.download(url).then(reply => { - // if (reply.status !== 200) { - // throw "Unable to download" - // } - // return reply.blob() - - // }).then(blob => { - // const objectURL = URL.createObjectURL(blob) - // var tmplnk = document.createElement("a") - // tmplnk.download = name - // tmplnk.href = objectURL - // //tmplnk.target="_blank" - // document.body.appendChild(tmplnk) - // tmplnk.click() - // document.body.removeChild(tmplnk) - - // }).catch(err => console.error(err)) - // } - - static get observedAttributes() { - return ["base-url"]; - } - - attributeChangedCallback(name, oldValue, newValue) { - if (oldValue !== newValue) { - switch (name) { - case "base-url": - this.baseUrl = newValue - break - } - } - } - -}) +} /** * Class that helps the interaction with the D4Science's Workspace via API and user's token as bearer authentication @@ -432,7 +659,7 @@ class D4SWorkspace { * @param {*} body the payload to send * @param {*} mime the mime type of the payload * @param {*} extraHeaders extra HTTP headers to send - * @returns the reponse payload as a promise, JSON data promise if the returned data is "application/json", a String data promise if "text/*" or a blob data promise in other cases + * @returns the reponse payload as a Blob() promise * @throws the error as string, if occurred */ #callWorkspace(method, uri, body, mime, extraHeaders) { @@ -461,14 +688,7 @@ class D4SWorkspace { return this.#d4sboot.secureFetch(url, req) .then(resp => { if (resp.ok) { - const contentType = resp.headers.get("content-type"); - if (contentType && contentType.indexOf("application/json") !== -1) { - return resp.json(); - } else if (contentType && contentType.indexOf("text/") !== -1) { - return resp.text(); - } else { - return resp.blob(); - } + return resp.blob(); } else { throw "Cannot invoke workspace via secure fetch for URL: " + url; } @@ -486,8 +706,10 @@ class D4SWorkspace { */ getWorkspace(extraHeaders) { return this.#callWorkspace("GET", null, null, null, extraHeaders) - .then(json => { - return json.item; + .then(blob => { + return blob.text().then(text => { + return JSON.parse(text).item; + }) }).catch(err => { const msg = "Cannot get workspace root ID. Error message: " + err; console.error(msg); @@ -518,8 +740,10 @@ class D4SWorkspace { listFolder(folderId, extraHeaders) { const uri = "/items/" + folderId + "/children"; return this.#callWorkspace("GET", uri, null, null, extraHeaders) - .then(json => { - return json.itemlist; + .then(blob => { + return blob.text().then(text => { + return JSON.parse(text).itemlist; + }); }).catch(err => { const msg = "Cannot get folder's content list. Error message: " + err; console.error(msg); @@ -535,8 +759,10 @@ class D4SWorkspace { */ getVREFolder(extraHeaders) { return this.#callWorkspace("GET", "/vrefolder", null, null, extraHeaders) - .then(json => { - return json.item; + .then(blob => { + return blob.text().then(text => { + return JSON.parse(text).item; + }); }).catch(err => { const msg = "Cannot get VRE folder ID. Error message: " + err; console.error(msg); @@ -584,20 +810,23 @@ class D4SWorkspace { console.log("Checking existance of folder: " + name); let uri = baseURI + "/items/" + name; return this.#callWorkspace("GET", uri, null, null, extraHeaders) - .then(json => { - if (json.itemlist[0]) { - const id = json.itemlist[0].id; - console.log("'" + name + "' folder exists with and has id: " + id); - return id; - } else { - console.info("'" + name + "' folder doesn't exist, creating it: " + name); - uri = baseURI + "/create/FOLDER"; - const params = new URLSearchParams({ name : name, description : description, hidden : false }); - return this.#callWorkspace("POST", uri, params.toString(), "application/x-www-form-urlencoded", extraHeaders).then(id => { - console.log("New '" + name + "' folder successfully created with id: " + id); - return id - }); - } + .then(blob => { + return blob.text().then(text => { + const json = JSON.parse(text); + if (json.itemlist[0]) { + const id = json.itemlist[0].id; + console.log("'" + name + "' folder exists with and has id: " + id); + return id; + } else { + console.info("'" + name + "' folder doesn't exist, creating it: " + name); + uri = baseURI + "/create/FOLDER"; + const params = new URLSearchParams({ name : name, description : description, hidden : false }); + return this.#callWorkspace("POST", uri, params.toString(), "application/x-www-form-urlencoded", extraHeaders).then(id => { + console.log("New '" + name + "' folder successfully created with id: " + id); + return id + }); + } + }); }); }; @@ -608,7 +837,7 @@ class D4SWorkspace { * @returns true if the file has been correctly created, false otherwise */ deleteItem(itemId, extraHeaders) { - return this.#callWorkspace("DELETE", "/workspace/items/" + itemId, null, null, extraHeaders) + return this.#callWorkspace("DELETE", "/items/" + itemId, null, null, extraHeaders) .then(results => { return true; }).catch(err => { @@ -623,7 +852,7 @@ class D4SWorkspace { * @param {string} name the name of the file to use for the download, if null the id is used * @param {boolean} skipLocalDownload if provided and true returns the data to function caller, otherwise it also downloads it locally. * @param {map} extraHeaders extra HTTP headers to be used for the request - * @returns the file's content if item is a file or a ZIP compressed archive if the item represents a folder + * @returns the file's content, if item is a file, or a ZIP compressed archive if the item represents a folder, as a Blob object * @throws the error as string, if occurred */ download(itemId, name, skipLocalDownload, extraHeaders) { @@ -671,15 +900,16 @@ class D4SWorkspace { }) ); return this.#callWorkspace("POST", uri, request, null, extraHeaders) - .then(item => { - const id = item.id; - console.info("File '" + name + "' successfully uploaded and its id is: " + id); - return true; + .then(blob => { + return blob.text().then(id => { + console.info("File '" + name + "' successfully uploaded and its id is: " + id); + return true; + }) }).catch(err => { console.error("Cannot upload file '" + name + "'. Error: " + err); return false; }); - }; + } /** * Uploads a new archive and stores its content into the folder represented by its id @@ -689,7 +919,7 @@ class D4SWorkspace { * @param {map} extraHeaders extra HTTP headers to be used for the request * @returns true if the file has been correctly created, false otherwise */ - uploadArchive(folderId, parentFolderName, description, data, extraHeaders) { + uploadArchive(folderId, parentFolderName, data, extraHeaders) { const uri = "/items/" + folderId + "/create/ARCHIVE"; const request = new FormData(); request.append("parentFolderName", parentFolderName); @@ -700,15 +930,16 @@ class D4SWorkspace { }) ); return this.#callWorkspace("POST", uri, request, null, extraHeaders) - .then(item => { - const id = item.id; - console.info("Archive file successfully uploaded and extracted into the '" + parentFolderName + "' folder, its id is: " + id); - return true; + .then(blob => { + return blob.text().then(id => { + console.info("Archive file successfully uploaded and extracted into the '" + parentFolderName + "' folder, its id is: " + id); + return true; + }) }).catch(err => { console.error("Cannot upload archive file. Error: " + err); return false; }); - }; + } /** * Returns the public URL of a file @@ -724,8 +955,10 @@ class D4SWorkspace { uri += "version=" + version; } return this.#callWorkspace("GET", uri, null, null, extraHeaders) - .then(publicURL => { - return publicURL; + .then(blob => { + return blob.text().then(publicURL => { + return publicURL; + }) }).catch(err => { const message = "Cannot retrieve the item's public URL. Error message: " + err; console.error(message); @@ -745,12 +978,32 @@ class D4SWorkspace { findByName(folderId, pattern, extraHeaders) { const uri = "/items/" + folderId + "/items/" + pattern; return this.#callWorkspace("GET", uri, null, null, extraHeaders) - .then(json => { - return json.itemlist; + .then(blob => { + return blob.text().then(text => { + return JSON.parse(text).itemlist; + }); }).catch(err => { const msg = "Cannot get folder's content list. Error message: " + err; console.error(msg); throw msg; }); } -} \ No newline at end of file +} + +/** + * Builds storagehub toolbar and raises an event for each selected tool item + * + */ +window.customElements.define('d4s-storage-tool', D4SStorageToolbar); + +/** + * Builds storagehub VRE folder or Workspace root tree, linked to toolbar and foldr list by events + * + */ +window.customElements.define('d4s-storage-folder', D4SStorageFolder);