var D4S_STORAGE_SCRIPT = document.currentScript /** * Base class of and */ 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 constructor() { super() this.#boot = document.querySelector('d4s-boot-2') } get boot() { if (this.#boot == null) { this.#boot = document.querySelector('d4s-boot-2') if (!this.#boot) { throw this.#d4smissmsg } } 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 } set baseUrl(url) { this.#baseurl = url this.setAttribute("baseurl", url) } } /** * 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) var div = document.createElement('div') const style = ` ` div.innerHTML = style this.boot.secureFetch(this.baseUrl + '/vrefolder').then((reply) => { if (reply.status !== 200) { throw "Unable to load folder" } return reply.json() }).then(data => { this.parseResponse(div, data) this.#shadowRoot.appendChild(div) }).catch(err => console.error(err)) } parseResponse(parentElement, jresp) { parentElement.classList.add(this.#loadedClass) var ul = document.createElement('ul') ul.classList.add('nested') if (jresp.item) { const itemname = jresp.item.displayName const itemid = jresp.item.id const path = this.buildListUrl(itemid) ul.appendChild(this.createListItem(itemname, itemid)) parentElement.appendChild(ul) } else if (jresp.itemlist) { jresp .itemlist .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) } else { console.error(jresp) } } createListItem(label, id) { var li = document.createElement('li') li.setAttribute('data-id', id) var child = document.createElement('span') child.innerHTML = label li.appendChild(child) li.addEventListener('click', (ev) => { ev.stopPropagation() this.select(ev.currentTarget.getAttribute('data-id')) }) return li } select(id) { var li = this.shadowRoot.querySelector(`*[data-id='${id}']`) this.displayPath(li) // if it was already selected then do nothing if (li.classList.contains(this.#selectedClass)) { this.toggleULDisplay(li) return } // switch selected and lists folder contents if (!li.classList.contains(this.#selectedClass)) { const selected = this.shadowRoot.querySelector('.' + this.#selectedClass) if (selected) { 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.boot.secureFetch(this.buildListUrl(id)).then(reply => { if (reply.status !== 200) { throw "Unable to load folder" } return reply.json() }).then(data => { this.parseResponse(li, data) }).catch(err => console.error(err)) } displayPath(li) { var curr = li while (curr.parentElement != null) { if (curr.parentElement.tagName == 'UL') { curr.parentElement.style.display = 'block' } curr = curr.parentElement } } toggleULDisplay(li) { const ul = li.querySelector('ul') if (ul) { ul.style.display = (ul.style.display === 'none') ? 'block' : 'none' } } static get observedAttributes() { return ["base-url", "filelist-id"] } attributeChangedCallback(name, oldValue, newValue) { if (oldValue !== newValue) { switch (name) { case "filelist-id": this.#storageFilelistId = newValue break case "base-url": this.baseUrl = newValue break } } } get filelistId() { return this.#storageFilelistId } set filelistId(id) { this.#storageFilelistId = id this.setAttribute("filelist-id", id) } }) /** * Lists elements in selected folder * * { if (reply.status !== 200) { throw "Unable to build list url" } return reply.json() }).then(data => { this.parseResponse(data) }).catch(err => console.error(err)) } parseResponse(jresp) { const root = this.createContainer() if (jresp.itemlist) { jresp.itemlist.forEach(item => root.appendChild(this.createFileRow(item))) } else { console.error(jresp) } } createFileRow(item) { var div = document.createElement('div') div.classList.add('row') var filename = document.createElement('div') filename.classList.add('col') var name = `${item.name}` filename.innerHTML = this.iconTag(item) + name const isFolder = item['@class'].includes('FolderItem') filename.addEventListener('click', (ev) => { ev.stopPropagation() if (isFolder) { const span = ev.currentTarget.querySelector(':nth-child(2)') if (span) { span.style = 'background-color: ' + this.#selectedbgcolor } if (this.#d4sstorageTree != null) { this.#d4sstorageTree.select(item.id) } } else { console.info("Download of " + item.id) this.download(this.buildDownloadUrl(item.id), item.name) } }) div.appendChild(filename) return div } iconTag(item) { var i = `` if (item['@class'].includes('FolderItem')) { i = `` } else if (item['@class'].includes('ImageFile')) { i = `` } else if (item['@class'].includes('PDFFileItem')) { i = `` } return '' + i + '' } buildDownloadUrl(id) { return this.baseUrl+ '/items/' + id + '/download' } download(url, name) { this.boot.secureFetch(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 } } } })