From 9a1a3b6c916f4dfde251cc85de0f3dbd45eeb4b2 Mon Sep 17 00:00:00 2001 From: Vincenzo Cestone Date: Wed, 30 Mar 2022 11:42:08 +0200 Subject: [PATCH] Implemented d4s storage tree and folder web components --- storage/d4s-storage.js | 360 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 storage/d4s-storage.js diff --git a/storage/d4s-storage.js b/storage/d4s-storage.js new file mode 100644 index 0000000..ed7a860 --- /dev/null +++ b/storage/d4s-storage.js @@ -0,0 +1,360 @@ +/** + * Base class of and + */ +class D4SStorageHtmlElement extends HTMLElement { + + #d4s = null + #d4smissmsg = 'Required d4s-boot-2 component not found' + + //#baseurl = 'https://api.dev.d4science.org' + #baseurl = 'https://storagehub.pre.d4science.net/storagehub/workspace' + + constructor() { + super() + } + + 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') + const linkElem2 = document.createElement('link') + linkElem2.setAttribute('rel', 'stylesheet') + linkElem2.setAttribute('href', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css') + root.appendChild(linkElem1) + root.appendChild(linkElem2) + } + + get d4s() { + if (this.#d4s == null) { + this.#d4s = document.querySelector('d4s-boot-2') + if (!this.#d4s) { + console.error(this.#d4smissmsg) + } + } + return this.#d4s + } + + 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() { + const shadowRoot = this.attachShadow({mode: 'open'}) + this.appendStylesheets(shadowRoot) + + var div = document.createElement('div') + const style = ` + + ` + div.innerHTML = style + + this.d4s.service( + this.baseUrl + '/vrefolder', + 'GET', null, + (resp) => { + this.parseResponse(div, resp) + shadowRoot.appendChild(div) + }, + (err) => { alert(err) } + ) + } + + parseResponse(parentElement, response) { + parentElement.classList.add(this.#loadedClass) + var ul = document.createElement('ul') + ul.classList.add('nested') + var jresp = JSON.parse(response) + 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.d4s.service( + this.buildListUrl(id), + 'GET', null, + (resp) => this.parseResponse(li, resp), + (err) => { alert(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 + * + * this.parseResponse(resp), + (err) => { alert(err) } + ) + } + + parseResponse(response) { + const root = this.createContainer() + var jresp = JSON.parse(response) + 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.d4s.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' + } + + static get observedAttributes() { + return ["base-url"]; + } + + attributeChangedCallback(name, oldValue, newValue) { + if (oldValue !== newValue) { + switch (name) { + case "base-url": + this.baseUrl = newValue + break + } + } + } + +}) \ No newline at end of file