Reformatting code. Refactor extended classes. Download method in d4s-storage-folder.

This commit is contained in:
Vincenzo Cestone 2022-04-27 19:40:27 +02:00
parent c2421ec5ab
commit 91d6e6abc6
1 changed files with 250 additions and 212 deletions

View File

@ -3,34 +3,45 @@
*/
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'
#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()
}
constructor() {
super()
this.#boot = document.querySelector('d4s-boot-2')
}
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)
get boot() {
if (this.#boot == null) {
this.#boot = document.querySelector('d4s-boot-2')
if (!this.#boot) {
throw this.#d4smissmsg
}
}
return this.#boot
}
buildListUrl(id) {
return this.#baseurl + '/items/' + id + '/children'
}
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)
}
get baseUrl() {
return this.#baseurl
}
buildListUrl(id) {
return this.#baseurl + '/items/' + id + '/children'
}
set baseUrl(url) {
this.#baseurl = url
this.setAttribute("baseurl", url)
}
get baseUrl() {
return this.#baseurl
}
set baseUrl(url) {
this.#baseurl = url
this.setAttribute("baseurl", url)
}
}
@ -42,178 +53,183 @@ class D4SStorageHtmlElement extends HTMLElement {
*/
window.customElements.define('d4s-storage-tree', class extends D4SStorageHtmlElement {
#storageFilelistId = null
#storageFilelistId = null
#loadedClass = 'loaded'
#selectedClass = 'selected'
#selectedbgcolor = 'lightgray'
#shadowRoot
#boot = null
constructor() {
super()
this.#boot = document.querySelector('d4s-boot-2')
this.#shadowRoot = this.attachShadow({mode: 'open'})
}
#loadedClass = 'loaded'
#selectedClass = 'selected'
#selectedbgcolor = 'lightgray'
#shadowRoot
/*
Notes:
API docs: https://gcube.wiki.gcube-system.org/gcube/StorageHub_REST_API
Preprod: https://accounts.pre.d4science.org
Sample context: %2Fpred4s%2Fpreprod%2FpreVRE
User workspace: https://storagehub.pre.d4science.net/storagehub/workspace
vrefolder: https://storagehub.pre.d4science.net/storagehub/workspace/vrefolder
-> 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)
constructor() {
super()
this.#shadowRoot = this.attachShadow({mode: 'open'})
}
var div = document.createElement('div')
const style = `
<style>
.selected > *:first-child {
background-color: ${this.#selectedbgcolor};
}
ul, li {
list-style-type: none;
}
li {
cursor: pointer;
}
</style>
`
div.innerHTML = style
/*
Notes:
API docs: https://gcube.wiki.gcube-system.org/gcube/StorageHub_REST_API
Preprod: https://accounts.pre.d4science.org
Sample context: %2Fpred4s%2Fpreprod%2FpreVRE
User workspace: https://storagehub.pre.d4science.net/storagehub/workspace
vrefolder: https://storagehub.pre.d4science.net/storagehub/workspace/vrefolder
-> 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)
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=>alert(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)
var div = document.createElement('div')
const style = `
<style>
.selected > *:first-child {
background-color: ${this.#selectedbgcolor};
}
}
ul, li {
list-style-type: none;
}
li {
cursor: pointer;
}
</style>
`
div.innerHTML = style
createListItem(label, id) {
var li = document.createElement('li')
li.setAttribute('data-id', id)
var child = document.createElement('span')
child.innerHTML = label
li.appendChild(child)
this.boot.secureFetch(this.baseUrl + '/vrefolder').then((reply) => {
if (reply.status !== 200) {
throw "Unable to load folder"
}
return reply.json()
li.addEventListener('click', (ev) => {
ev.stopPropagation()
this.select(ev.currentTarget.getAttribute('data-id'))
}).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))
})
return li
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
}
select(id) {
var li = this.shadowRoot.querySelector(`*[data-id='${id}']`)
this.displayPath(li)
this.boot.secureFetch(this.buildListUrl(id)).then(reply => {
if (reply.status !== 200) {
throw "Unable to load folder"
}
return reply.json()
// 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=>alert(err))
}
}).then(data => {
this.parseResponse(li, data)
displayPath(li) {
var curr = li
while (curr.parentElement != null) {
if (curr.parentElement.tagName == 'UL') {
curr.parentElement.style.display = 'block'
}
curr = curr.parentElement
}
}
}).catch(err => console.error(err))
}
toggleULDisplay(li) {
const ul = li.querySelector('ul')
if (ul) {
ul.style.display = (ul.style.display === 'none') ? 'block' : 'none'
}
displayPath(li) {
var curr = li
while (curr.parentElement != null) {
if (curr.parentElement.tagName == 'UL') {
curr.parentElement.style.display = 'block'
}
curr = curr.parentElement
}
}
static get observedAttributes() {
return ["base-url", "filelist-id"];
toggleULDisplay(li) {
const ul = li.querySelector('ul')
if (ul) {
ul.style.display = (ul.style.display === 'none') ? 'block' : 'none'
}
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue !== newValue) {
switch (name) {
case "filelist-id":
this.#storageFilelistId = newValue
break
case "base-url":
this.baseUrl = newValue
break
}
}
}
static get observedAttributes() {
return ["base-url", "filelist-id"]
}
get filelistId() {
return this.#storageFilelistId
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue !== newValue) {
switch (name) {
case "filelist-id":
this.#storageFilelistId = newValue
break
case "base-url":
this.baseUrl = newValue
break
}
}
}
set filelistId(id) {
this.#storageFilelistId = id
this.setAttribute("filelist-id", id)
}
get filelistId() {
return this.#storageFilelistId
}
set filelistId(id) {
this.#storageFilelistId = id
this.setAttribute("filelist-id", id)
}
})
/**
@ -227,11 +243,9 @@ window.customElements.define('d4s-storage-folder', class extends D4SStorageHtmlE
#d4sstorageTree = null
#selectedbgcolor = 'lightgray'
#boot = null;
constructor() {
super()
this.#boot = document.querySelector('d4s-boot-2')
}
connectedCallback() {
@ -240,13 +254,13 @@ window.customElements.define('d4s-storage-folder', class extends D4SStorageHtmlE
const style = document.createElement('style')
style.innerHTML = `
span {
cursor: pointer;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
span {
cursor: pointer;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
`
shadowRoot.appendChild(style)
this.createContainer()
@ -257,7 +271,7 @@ window.customElements.define('d4s-storage-folder', class extends D4SStorageHtmlE
div.classList.add('d4s-folder')
var child = this.shadowRoot.querySelector('.d4s-folder')
if (child) {
this.shadowRoot.removeChild(child)
this.shadowRoot.removeChild(child)
}
this.shadowRoot.appendChild(div)
return div
@ -265,25 +279,29 @@ window.customElements.define('d4s-storage-folder', class extends D4SStorageHtmlE
join(tree) {
if (this.#d4sstorageTree == null) {
this.#d4sstorageTree = tree
this.#d4sstorageTree = tree
}
}
list(folderId) {
this.#boot.secureFetch(this.buildListUrl(folderId)).then(reply=>{
if(reply.status !== 200) throw "Unable to build list url";
return reply.json()
}).then(data=>{
this.boot.secureFetch(this.buildListUrl(folderId)).then(reply => {
if (reply.status !== 200) {
throw "Unable to build list url"
}
return reply.json()
}).then(data => {
this.parseResponse(data)
}).catch(err=>alert(err))
}).catch(err => console.error(err))
}
parseResponse(jresp) {
const root = this.createContainer()
if (jresp.itemlist) {
jresp.itemlist.forEach(item => root.appendChild(this.createFileRow(item)))
jresp.itemlist.forEach(item => root.appendChild(this.createFileRow(item)))
} else {
console.error(jresp)
console.error(jresp)
}
}
@ -296,19 +314,19 @@ window.customElements.define('d4s-storage-folder', class extends D4SStorageHtmlE
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.#boot.download(this.buildDownloadUrl(item.id), item.name)
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)
@ -318,11 +336,11 @@ window.customElements.define('d4s-storage-folder', class extends D4SStorageHtmlE
iconTag(item) {
var i = `<img src="/storage/img/file-earmark.svg"></img>`
if (item['@class'].includes('FolderItem')) {
i = `<img src="/storage/img/folder.svg"></img>`
i = `<img src="/storage/img/folder.svg"></img>`
} else if (item['@class'].includes('ImageFile')) {
i = `<img src="/storage/img/image.svg"></img>`
i = `<img src="/storage/img/image.svg"></img>`
} else if (item['@class'].includes('PDFFileItem')) {
i = `<img src="/storage/img/filetype-pdf.svg"></img>`
i = `<img src="/storage/img/filetype-pdf.svg"></img>`
}
return '<span class="px-2">' + i + '</span>'
}
@ -331,17 +349,37 @@ window.customElements.define('d4s-storage-folder', class extends D4SStorageHtmlE
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
}
switch (name) {
case "base-url":
this.baseUrl = newValue
break
}
}
}