Added select button for storage tree, added icons for well-known file types, corrected bug with direct input to ws link input field

This commit is contained in:
dcore94 2024-04-17 14:52:36 +02:00
parent 78a3009573
commit cc752abe40
3 changed files with 102 additions and 23 deletions

View File

@ -12,16 +12,18 @@
<link href="css/common.css" rel="stylesheet"> <link href="css/common.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.cloud-dev.d4science.org/common/js/bss-min-1.2.6.js"></script> <script src="https://cdn.cloud-dev.d4science.org/common/js/bss-min-1.2.6.js"></script>
<script src="https://cdn.cloud-dev.d4science.org/storage/d4s-storage.js"></script> <script src="../storage/d4s-storage.js"></script>
</head> </head>
<body class="m-4"> <body class="m-4">
<d4s-boot-2 clientid="https://next.dev.d4science.org" context="%2Fgcube%2Fdevsec%2FCCP" gateway="next.dev.d4science.org" redirect-url="http://localhost:8080/ccp/index.html" url="https://accounts.dev.d4science.org/auth"> <script src="https://cdn.dev.d4science.org/boot/d4s-boot.js"></script> </d4s-boot-2> <d4s-boot-2 clientid="https://next.dev.d4science.org" context="%2Fgcube%2Fdevsec%2FCCP" gateway="next.dev.d4science.org" redirect-url="http://localhost:8080/ccp/index.html" url="https://accounts.dev.d4science.org/auth"> <script src="https://cdn.dev.d4science.org/boot/d4s-boot.js"></script> </d4s-boot-2>
<span class="badge badge-info material-icons">&#xe415;</span>
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<d4s-ccp-methodlist serviceurl="https://ccp.cloud-dev.d4science.org"></d4s-ccp-methodlist> <d4s-ccp-methodlist serviceurl="https://ccp.cloud-dev.d4science.org" allow-edit="true"></d4s-ccp-methodlist>
</div> </div>
<div class="col"> <div class="col">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<d4s-ccp-methodeditor serviceurl="https://ccp.cloud-dev.d4science.org"></d4s-ccp-methodeditor> <d4s-ccp-methodeditor serviceurl="https://ccp.cloud-dev.d4science.org"></d4s-ccp-methodeditor>
</div> </div>
<div class="col"> <div class="col">

View File

@ -289,7 +289,7 @@ class CCPBaseInputWidgetController extends HTMLElement {
<div name="content"> <div name="content">
</div> </div>
</label> </label>
</div> </div>
` `
this.renderPlusMinus() this.renderPlusMinus()
@ -594,9 +594,12 @@ class CCPRemoteFileInputWidgetController extends CCPBaseInputWidgetController {
<path d="M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h240l80 80h320q33 0 56.5 23.5T880-640H447l-80-80H160v480l96-320h684L837-217q-8 26-29.5 41.5T760-160H160Zm84-80h516l72-240H316l-72 240Zm0 0 72-240-72 240Zm-84-400v-80 80Z"/> <path d="M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h240l80 80h320q33 0 56.5 23.5T880-640H447l-80-80H160v480l96-320h684L837-217q-8 26-29.5 41.5T760-160H160Zm84-80h516l72-240H316l-72 240Zm0 0 72-240-72 240Zm-84-400v-80 80Z"/>
</svg> </svg>
<div name="ws" class="d-none position-absolute shadow border border-primary bg-light p-2" style="left: 100%;z-index:1000; line-height:1.5rem;overflow:hidden;padding:5px;"> <div name="ws" class="d-none position-absolute shadow border border-primary bg-light p-2" style="left: 100%;z-index:1000; line-height:1.5rem;overflow:hidden;padding:5px;">
<div class="d-flex justify-content-between" style="border-bottom: solid 1px gray;"> <div class="mb-1" style="border-bottom: solid 1px gray;">
<h5 class="text-secondary">Access your workspace</h5> <div class="d-flex justify-content-between m-0">
<span class="btn text-danger p-0" style="font-weight:bold" name="closebtn">x</span> <h5 class="text-secondary m-0">Access your workspace</h5>
<span class="btn text-danger p-0" style="font-weight:bold" name="closebtn">x</span>
</div>
<small class="text-muted m-0">Select an item or drag and drop it to a proper input</small>
</div> </div>
<div style="min-width:350px; max-width:500px;overflow-x:hidden;text-wrap:nowrap;text-overflow: ellipsis;min-height:5rem; max-height:10rem;"> <div style="min-width:350px; max-width:500px;overflow-x:hidden;text-wrap:nowrap;text-overflow: ellipsis;min-height:5rem; max-height:10rem;">
<d4s-storage-tree <d4s-storage-tree
@ -605,10 +608,12 @@ class CCPRemoteFileInputWidgetController extends CCPBaseInputWidgetController {
show-files="true" show-files="true"
allow-drag="true"/> allow-drag="true"/>
</div> </div>
<div class="d-flex justify-content-end mt-1 pt-1" style="border-top: solid 1px gray;">
<button class="btn btn-primary" name="selectbtn">SELECT</span>
</div>
</div> </div>
<div class="modal fade" style="background-color:rgba(0,0,0,0.3)" name="publicorprotected" tabindex="-1" role="dialog"> <div class="modal fade" style="background-color:rgba(0,0,0,0.3)" name="publicorprotected" tabindex="-1" role="dialog">
<div class="modal-dialog" role= this.#publicorprivate = <div class="modal-dialog" role="document">
"document">
<div class="modal-content shadow-lg border-primary"> <div class="modal-content shadow-lg border-primary">
<div class="modal-body"> <div class="modal-body">
Choose whether you want to use the public link or the protected link (requires authentication and authorization). Choose whether you want to use the public link or the protected link (requires authentication and authorization).
@ -616,6 +621,7 @@ class CCPRemoteFileInputWidgetController extends CCPBaseInputWidgetController {
<div class="modal-footer"> <div class="modal-footer">
<button name="public" type="button" class="btn btn-info">Public link</button> <button name="public" type="button" class="btn btn-info">Public link</button>
<button name="protected" type="button" class="btn btn-primary">Protected link</button> <button name="protected" type="button" class="btn btn-primary">Protected link</button>
<button name="cancel" type="button" class="btn btn-danger">Cancel</button>
</div> </div>
</div> </div>
</div> </div>
@ -637,12 +643,28 @@ class CCPRemoteFileInputWidgetController extends CCPBaseInputWidgetController {
this.#publiclink = this.#protectedlink = this.#target = this.#index = null this.#publiclink = this.#protectedlink = this.#target = this.#index = null
const newev = new Event("input", { bubbles : true}) const newev = new Event("input", { bubbles : true})
this.dispatchEvent(newev) this.dispatchEvent(newev)
} }else{
else return; this.#publicorprotected_dialog.style.display = "none"
this.#publicorprotected_dialog.classList.remove("show")
this.#publiclink = this.#protectedlink = this.#target = this.#index = null
}
} }
}) })
const ws = this.rootdoc.querySelector("div[name=ws]") const ws = this.rootdoc.querySelector("div[name=ws]")
const st = ws.querySelector("d4s-storage-tree")
this.addEventListener("click", ev=>{
ev.stopPropagation()
ev.preventDefault()
if (ev.target.getAttribute("name") == "selectbtn") {
this.#publicorprotected_dialog.style.display = "block"
this.#publicorprotected_dialog.classList.add("show")
this.#target = this.querySelector("input")
this.#index = 0
this.#publiclink = st.d4sWorkspace.getPublicLink(st.currentId)
this.#protectedlink = st.d4sWorkspace.getDownloadLink(st.currentId)
}
})
this.rootdoc.querySelector("svg[name=trigger]").addEventListener("click", ev => { this.rootdoc.querySelector("svg[name=trigger]").addEventListener("click", ev => {
ws.classList.toggle("d-none") ws.classList.toggle("d-none")
ev.preventDefault() ev.preventDefault()
@ -671,6 +693,13 @@ class CCPRemoteFileInputWidgetController extends CCPBaseInputWidgetController {
} }
}) })
this.addEventListener("input", ev => {
ev.stopPropagation()
if (ev.target.getAttribute("name") == this.name && ev.target.getAttribute("data-index") != null) {
this.value[Number(ev.target.getAttribute("data-index"))] = ev.target.value
}
})
document.addEventListener("keydown", ev => { document.addEventListener("keydown", ev => {
if (ev.code == 'Escape') ws.classList.add("d-none"); if (ev.code == 'Escape') ws.classList.add("d-none");
}) })

View File

@ -16,10 +16,7 @@ class D4SStorageHtmlElement extends HTMLElement {
} }
connectedCallback() { connectedCallback() {
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');
this.shadowRoot.appendChild(linkElem);
} }
get srcBaseURL() { get srcBaseURL() {
@ -98,7 +95,7 @@ class D4SStorageToolbar extends D4SStorageHtmlElement {
class D4SStorageTree extends D4SStorageHtmlElement { class D4SStorageTree extends D4SStorageHtmlElement {
static tree_event_name = "d4s-toolbar"; static tree_event_name = "d4s-tree";
static folder_data_event_name = "d4s-folder-data"; static folder_data_event_name = "d4s-folder-data";
static dataid_attr = 'data-id'; static dataid_attr = 'data-id';
@ -226,8 +223,10 @@ class D4SStorageTree extends D4SStorageHtmlElement {
const div = document.createElement('div') const div = document.createElement('div')
div.innerHTML = /*css*/` div.innerHTML = /*css*/`
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<style> <style>
.selected > span { .selected > .li-title {
background-color: ${this.#selectedbgcolor}; background-color: ${this.#selectedbgcolor};
} }
ul.root { ul.root {
@ -238,6 +237,12 @@ class D4SStorageTree extends D4SStorageHtmlElement {
margin-bottom: 0; margin-bottom: 0;
padding-left: 0.6em; padding-left: 0.6em;
} }
li{
color: #444444;
}
li:hover{
color: #555555;
}
li { li {
cursor: pointer; cursor: pointer;
} }
@ -378,7 +383,7 @@ class D4SStorageTree extends D4SStorageHtmlElement {
this.dispatchEvent( this.dispatchEvent(
new CustomEvent( new CustomEvent(
D4SStorageTree.tree_event_name, D4SStorageTree.tree_event_name,
{detail: {id: id}} {detail: {id: id, bubbles: true}}
) )
); );
} }
@ -417,15 +422,43 @@ class D4SStorageTree extends D4SStorageHtmlElement {
data data
.filter(item => this.showFiles || item['@class'].includes('FolderItem')) .filter(item => this.showFiles || item['@class'].includes('FolderItem'))
.forEach(item => { .forEach(item => {
ul.appendChild(this.createListItem(item.title, item.id, item['@class'], parentId)); ul.appendChild(this.createListItem(item, parentId));
}) })
} else { } else {
ul.appendChild(this.createListItem(data.displayName ? data.displayName : data.title, data.id, data['@class'], parentId)); ul.appendChild(this.createListItem(data, parentId));
} }
parentElement.appendChild(ul); parentElement.appendChild(ul);
} }
createListItem(label, id, type, parentId) { getIconByMIME(mime){
if(mime.startsWith("image")) return "image";
if(mime.startsWith("application/pdf")) return "picture_as_pdf";
if(mime.startsWith("application/zip")) return "archive";
if(mime.startsWith("application/xml")) return "code";
if(mime.match(/tar|compressed|gzip|gz|tgz/)) return 'archive';
return null;
}
getIconByExtension(name){
const tks = name.split(".")
if(tks.length === 0) return null;
const ext = tks[tks.length - 1]
if(ext.match(/java$|py$|^r$|^c$|ccp|lua|jl|^sh$|json|xml|xsl|xslt|md$|xq$|xqm$/i)) return "code";
if(ext.match(/js$/i)) return "javascript";
if(ext.match(/html$|css$|php$/i)) return ext;
if(ext.match(/kml$/i)) return "place";
if(ext.match(/ics$/i)) return "event";
if(ext.match(/csv$|xls$|ods$/i)) return "assessment";
if(ext.match(/txt$|odt$|rtf$|doc$|docx$/i)) return "description";
if(ext.match(/ppt$|odp$/i)) return "slideshow";
return null;
}
createListItem(item, parentId) {
const label = item.displayName ? item.displayName : item.title
const id = item.id
const type = item["@class"]
const mime = item.content && item.content.mimeType ? item.content.mimeType : null
const li = document.createElement('li'); const li = document.createElement('li');
li.setAttribute(D4SStorageTree.dataname_attr, label); li.setAttribute(D4SStorageTree.dataname_attr, label);
li.setAttribute(D4SStorageTree.dataid_attr, id); li.setAttribute(D4SStorageTree.dataid_attr, id);
@ -434,10 +467,25 @@ class D4SStorageTree extends D4SStorageHtmlElement {
if (parentId) { if (parentId) {
li.setAttribute(D4SStorageTree.parentid_attr, parentId); li.setAttribute(D4SStorageTree.parentid_attr, parentId);
} }
const icon = type.includes('FolderItem') || type.includes("SharedFolder")? "folder.svg" : "file-earmark.svg" //const icon = type.includes('FolderItem') || type.includes("SharedFolder")? "folder.svg" : "file-earmark.svg"
var icon = "insert_drive_file";
if(type.includes('FolderItem')){
icon = "folder"
}else if(type.includes("SharedFolder")){
icon = "folder_shared"
}else{
const im = mime ? this.getIconByMIME(mime) : null
if(im) icon = im;
else{
const ie = this.getIconByExtension(label)
if(ie) icon = ie;
}
}
li.innerHTML = ` li.innerHTML = `
<img class="px-1" src="${this.srcBaseURL}/img/${icon}"</img> <div class="li-title d-flex gap-1">
<span>${label}</span> <span class="material-icons">${icon}</span>
<span>${label}</span>
</div>
` `
li.addEventListener('click', (ev) => { li.addEventListener('click', (ev) => {