master #6
|
@ -88,6 +88,7 @@ class CCPExecutionForm extends HTMLElement{
|
||||||
<option value="text/python" data-ext="py" title="Generate plain Python3">Python 3</option>
|
<option value="text/python" data-ext="py" title="Generate plain Python3">Python 3</option>
|
||||||
<option value="text/plain+r" data-ext="r" title="Generate plain R">R</option>
|
<option value="text/plain+r" data-ext="r" title="Generate plain R">R</option>
|
||||||
<option value="application/vnd.jupyter+python" data-ext="ipynb" title="Generate Jupyter notebook with Python 3 cells">Jupyter Python3</option>
|
<option value="application/vnd.jupyter+python" data-ext="ipynb" title="Generate Jupyter notebook with Python 3 cells">Jupyter Python3</option>
|
||||||
|
<option value="text/julia" data-ext="jl" title="Generate Julia 1.9.0 code (HTTP 1.10.0, JSON3 1.13.2)">Julia 1.9.0</option>
|
||||||
</select>
|
</select>
|
||||||
<button name="codegen" title="Generate code" class="btn btn-primary ccp-toolbar-button ccp-toolbar-button-small">
|
<button name="codegen" title="Generate code" class="btn btn-primary ccp-toolbar-button ccp-toolbar-button-small">
|
||||||
<svg viewBox="0 96 960 960">
|
<svg viewBox="0 96 960 960">
|
||||||
|
|
|
@ -125,6 +125,7 @@ class CCPExecutionHistory extends HTMLElement {
|
||||||
<option value="text/python" data-ext="py" title="Generate plain Python3">Python 3</option>
|
<option value="text/python" data-ext="py" title="Generate plain Python3">Python 3</option>
|
||||||
<option value="text/plain+r" data-ext="r" title="Generate plain R">R</option>
|
<option value="text/plain+r" data-ext="r" title="Generate plain R">R</option>
|
||||||
<option value="application/vnd.jupyter+python" data-ext="ipynb" title="Generate Jupyter notebook with Python 3 cells">Jupyter Python3</option>
|
<option value="application/vnd.jupyter+python" data-ext="ipynb" title="Generate Jupyter notebook with Python 3 cells">Jupyter Python3</option>
|
||||||
|
<option value="text/julia" data-ext="jl" title="Generate Julia 1.9.0 code (HTTP 1.10.0, JSON3 1.13.2)">Julia 1.9.0</option>
|
||||||
</select>
|
</select>
|
||||||
<button data-index="0" name="codegen" title="Generate code" class="btn btn-primary ccp-toolbar-button ccp-toolbar-button-small">
|
<button data-index="0" name="codegen" title="Generate code" class="btn btn-primary ccp-toolbar-button ccp-toolbar-button-small">
|
||||||
<svg viewBox="0 96 960 960">
|
<svg viewBox="0 96 960 960">
|
||||||
|
|
|
@ -509,20 +509,8 @@ window.customElements.define('d4s-ccp-input-file', CCPFileInputWidgetController)
|
||||||
|
|
||||||
class CCPRemoteFileInputWidgetController extends CCPBaseInputWidgetController{
|
class CCPRemoteFileInputWidgetController extends CCPBaseInputWidgetController{
|
||||||
|
|
||||||
#iss = null;
|
|
||||||
#addresses = {
|
|
||||||
"https://accounts.dev.d4science.org/auth/realms/d4science" : "https://workspace-repository.dev.d4science.org/storagehub/workspace",
|
|
||||||
"https://accounts.pre.d4science.org/auth/realms/d4science" : "https://pre.d4science.org/workspace",
|
|
||||||
"https://accounts.d4science.org/auth/realms/d4science" : "https://api.d4science.org/workspace"
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(){
|
constructor(){
|
||||||
super()
|
super()
|
||||||
this.#iss = document.querySelector("d4s-boot-2").loginToken.iss
|
|
||||||
}
|
|
||||||
|
|
||||||
get baseurl(){
|
|
||||||
return this.#addresses[this.#iss]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback(){
|
connectedCallback(){
|
||||||
|
@ -532,23 +520,42 @@ class CCPRemoteFileInputWidgetController extends CCPBaseInputWidgetController{
|
||||||
this.value[index] = ev.target.value
|
this.value[index] = ev.target.value
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
addToolContent(){
|
||||||
|
const iss = document.querySelector("d4s-boot-2").loginToken.iss;
|
||||||
|
const addresses = {
|
||||||
|
"https://accounts.dev.d4science.org/auth/realms/d4science" : "https://workspace-repository.dev.d4science.org/storagehub/workspace",
|
||||||
|
"https://accounts.pre.d4science.org/auth/realms/d4science" : "https://pre.d4science.org/workspace",
|
||||||
|
"https://accounts.d4science.org/auth/realms/d4science" : "https://api.d4science.org/workspace"
|
||||||
|
};
|
||||||
this.rootdoc.querySelector("div[name=tools]").innerHTML += `
|
this.rootdoc.querySelector("div[name=tools]").innerHTML += `
|
||||||
<svg name="trigger" style="width:24;height:24;fill:#007bff; cursor:pointer" viewBox="0 -960 960 960">
|
<svg name="trigger" style="width:24;height:24;fill:#007bff; cursor:pointer" viewBox="0 -960 960 960">
|
||||||
<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 class="d-flex justify-content-between" style="border-bottom: solid 1px gray;">
|
||||||
|
<h5 class="text-secondary">Access your workspace</h5>
|
||||||
|
<span class="btn text-danger p-0" style="font-weight:bold" name="closebtn">x</span>
|
||||||
|
</div>
|
||||||
|
<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
|
||||||
class="d-none position-absolute shadow border border-primary bg-light"
|
base-url="${addresses[iss]}"
|
||||||
style="left: 100%; margin: 0 0 0 -.5rem;min-width:350px; max-width:500px;z-index:1000; line-height:1.5rem;overflow-x:hidden;text-wrap:nowrap;text-overflow: ellipsis;min-height:5rem; max-height:10rem; padding:5px;"
|
|
||||||
base-url="${this.baseurl}"
|
|
||||||
file-download-enabled="true"
|
file-download-enabled="true"
|
||||||
show-files="true"
|
show-files="true"
|
||||||
allow-drag="true"/>
|
allow-drag="true"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
`
|
`
|
||||||
const ws = this.rootdoc.querySelector("d4s-storage-tree")
|
const ws = this.rootdoc.querySelector("div[name=ws]")
|
||||||
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")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.rootdoc.querySelector("span[name=closebtn]").addEventListener("click", ev=>{
|
||||||
|
ws.classList.add("d-none")
|
||||||
|
})
|
||||||
|
|
||||||
this.addEventListener("dragover", ev=>{
|
this.addEventListener("dragover", ev=>{
|
||||||
ev.preventDefault()
|
ev.preventDefault()
|
||||||
})
|
})
|
||||||
|
@ -568,6 +575,7 @@ class CCPRemoteFileInputWidgetController extends CCPBaseInputWidgetController{
|
||||||
}
|
}
|
||||||
|
|
||||||
content(){
|
content(){
|
||||||
|
this.addToolContent()
|
||||||
if(this.value.length <= 1){
|
if(this.value.length <= 1){
|
||||||
return `
|
return `
|
||||||
<input data-index="0" value="${this.value.length ? this.value[0] : ''}" class="my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/>`
|
<input data-index="0" value="${this.value.length ? this.value[0] : ''}" class="my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/>`
|
||||||
|
|
|
@ -286,10 +286,11 @@ class CCPMethodEditorController extends HTMLElement{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cloneMethod(method){
|
cloneMethod(method, derivation){
|
||||||
if(this.#locked) return;
|
if(this.#locked) return;
|
||||||
this.lockRender()
|
this.lockRender()
|
||||||
this.#boot.secureFetch(this.#serviceurl + "/methods/" + method + "/clone").then(
|
const derive = derivation ? "?derive=true" : ""
|
||||||
|
this.#boot.secureFetch(this.#serviceurl + "/methods/" + method + "/clone" + derive).then(
|
||||||
(resp)=>{
|
(resp)=>{
|
||||||
if(resp.status === 200){
|
if(resp.status === 200){
|
||||||
return resp.json()
|
return resp.json()
|
||||||
|
@ -373,6 +374,7 @@ class CCPMethodEditorController extends HTMLElement{
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button name="clone" type="button" class="btn btn-info">Clone</button>
|
<button name="clone" type="button" class="btn btn-info">Clone</button>
|
||||||
<button name="edit" type="button" class="btn btn-primary">Edit</button>
|
<button name="edit" type="button" class="btn btn-primary">Edit</button>
|
||||||
|
<button name="derive" type="button" class="btn btn-secondary">Derive</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -510,6 +512,13 @@ class CCPMethodEditorController extends HTMLElement{
|
||||||
this.#dragging_method = null
|
this.#dragging_method = null
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.#rootdoc.querySelector("#cloneornew button[name=derive]").addEventListener("click", ev=>{
|
||||||
|
this.#cloneornew_dialog.classList.remove("show")
|
||||||
|
this.#cloneornew_dialog.style.display = "none"
|
||||||
|
this.cloneMethod(this.#dragging_method, true)
|
||||||
|
this.#dragging_method = null
|
||||||
|
})
|
||||||
|
|
||||||
this.#rootdoc.querySelector("#cloneornew button[name=edit]").addEventListener("click", ev=>{
|
this.#rootdoc.querySelector("#cloneornew button[name=edit]").addEventListener("click", ev=>{
|
||||||
this.#cloneornew_dialog.classList.remove("show")
|
this.#cloneornew_dialog.classList.remove("show")
|
||||||
this.#cloneornew_dialog.style.display = "none"
|
this.#cloneornew_dialog.style.display = "none"
|
||||||
|
@ -985,7 +994,7 @@ class CCPMethodEditorController extends HTMLElement{
|
||||||
const val = 'deploy-script'
|
const val = 'deploy-script'
|
||||||
return this.#current.additionalParameters.parameters.map(
|
return this.#current.additionalParameters.parameters.map(
|
||||||
(script, i) => {
|
(script, i) => {
|
||||||
let code = script.value.length ? script.value.join("\r\n") : ""
|
let code = script.value && script.value.length ? script.value.join("\r\n") : ""
|
||||||
return `
|
return `
|
||||||
<textarea rows="5" class="script-area form-control ${script.name === val ? '' : 'd-none'}" name="${script.name}">${code}</textarea>
|
<textarea rows="5" class="script-area form-control ${script.name === val ? '' : 'd-none'}" name="${script.name}">${code}</textarea>
|
||||||
`
|
`
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<script src="js/rolescontroller.js"></script>
|
||||||
|
<script src="../common/js/keycloak.js" type="text/javascript"></script>
|
||||||
|
<script src="../boot/d4s-boot.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<d4s-boot-2 context="_myextapp"
|
||||||
|
gateway="next.d4science.org"
|
||||||
|
redirect-url="http://localhost:8080"
|
||||||
|
url="https://accounts.dev.d4science.org/auth">
|
||||||
|
</d4s-boot-2>
|
||||||
|
<d4s-extapp-role-manager appid="076bfe7d-12a2-41d1-a720-05911f0ae527"></d4s-extapp-role-manager>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,90 @@
|
||||||
|
class ExtAppRoleController extends HTMLElement{
|
||||||
|
|
||||||
|
#boot;
|
||||||
|
#roles;
|
||||||
|
#users;
|
||||||
|
#mappings;
|
||||||
|
#serviceurl;
|
||||||
|
#appid;
|
||||||
|
#loading = false;
|
||||||
|
|
||||||
|
constructor(){
|
||||||
|
super()
|
||||||
|
this.#boot = document.querySelector("d4s-boot-2")
|
||||||
|
this.#serviceurl = this.#boot.url
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback(){
|
||||||
|
this.#appid = this.getAttribute("appid")
|
||||||
|
if(!this.#loading){
|
||||||
|
this.#loading = true
|
||||||
|
this.loadData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadData(){
|
||||||
|
Promise.all([
|
||||||
|
this.loadEligibleUsers(), this.loadRoles()
|
||||||
|
]).then(()=>{
|
||||||
|
console.log("Done. Ui should be complete now")
|
||||||
|
}).catch(err=>alert(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
loadEligibleUsers(){
|
||||||
|
const url = this.#serviceurl + `/admin/realms/d4science/clients/${this.#appid}/roles/eligible/users?briefRepresentation=true&max=-1&first=0`
|
||||||
|
return this.#boot.secureFetch(url).then(resp=>{
|
||||||
|
if(resp.ok){
|
||||||
|
return resp.json()
|
||||||
|
}else if(resp.status === 403){
|
||||||
|
throw "Fetching users: You are not allowed to manage roles for this application."
|
||||||
|
}else{
|
||||||
|
throw "Fetching users: Unspecified error"
|
||||||
|
}
|
||||||
|
}).then(json=>{
|
||||||
|
console.log("Fetched eligible users can show table")
|
||||||
|
this.#users = json
|
||||||
|
return loadMappings()
|
||||||
|
}).then(()=>{
|
||||||
|
console.log(this.#mappings)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
loadRoles(){
|
||||||
|
const url = this.#serviceurl + `/admin/realms/d4science/clients/${this.#appid}/roles`
|
||||||
|
return this.#boot.secureFetch(url).then(resp=>{
|
||||||
|
if(resp.ok){
|
||||||
|
return resp.json()
|
||||||
|
}else if(resp.status === 403){
|
||||||
|
throw "Fetching roles: You are not allowed to manage roles for this application."
|
||||||
|
}else{
|
||||||
|
throw "Fetching roles: Unspecified error"
|
||||||
|
}
|
||||||
|
}).then(json=>{
|
||||||
|
this.#roles = json
|
||||||
|
console.log("Roles loaded, could draw header")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
loadMappings(){
|
||||||
|
return Promise.all(
|
||||||
|
this.#users.forEach(u => {
|
||||||
|
const url = this.#serviceurl + `/admin/realms/d4science/users/${u.id}/clients/${this.#appid}/roles`
|
||||||
|
this.#boot.secureFetch(url).then(resp=>{
|
||||||
|
if(resp.ok){
|
||||||
|
return resp.json()
|
||||||
|
}else if(resp.status === 403){
|
||||||
|
throw "Fetching role mappings: You are not allowed to manage roles for this application."
|
||||||
|
}else{
|
||||||
|
throw "Fetching role mappings: Unspecified error"
|
||||||
|
}
|
||||||
|
}).then(json=>{
|
||||||
|
u.mappings = json
|
||||||
|
console.log(`Fetched mappings for user ${u.id} can update the proper table`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
window.customElements.define('d4s-extapp-role-manager', ExtAppRoleController);
|
|
@ -417,10 +417,10 @@ 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.name, item.id, item['@class'], parentId));
|
ul.appendChild(this.createListItem(item.title, item.id, item['@class'], parentId));
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
ul.appendChild(this.createListItem(data.displayName ? data.displayName : data.name, data.id, data['@class'], parentId));
|
ul.appendChild(this.createListItem(data.displayName ? data.displayName : data.title, data.id, data['@class'], parentId));
|
||||||
}
|
}
|
||||||
parentElement.appendChild(ul);
|
parentElement.appendChild(ul);
|
||||||
}
|
}
|
||||||
|
@ -434,7 +434,7 @@ 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') ? "folder.svg" : "file-earmark.svg"
|
const icon = type.includes('FolderItem') || type.includes("SharedFolder")? "folder.svg" : "file-earmark.svg"
|
||||||
li.innerHTML = `
|
li.innerHTML = `
|
||||||
<img class="px-1" src="${this.srcBaseURL}/img/${icon}"</img>
|
<img class="px-1" src="${this.srcBaseURL}/img/${icon}"</img>
|
||||||
<span>${label}</span>
|
<span>${label}</span>
|
||||||
|
|
Loading…
Reference in New Issue