Merge pull request 'master' (#14) from master into prod
Reviewed-on: #14
This commit is contained in:
commit
5f9aeff8b2
|
@ -13,6 +13,7 @@
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" 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="../storage/d4s-storage.js"></script>
|
<script src="../storage/d4s-storage.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/ol@v9.2.4/dist/ol.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="m-4">
|
<body class="m-4">
|
||||||
|
|
|
@ -58,6 +58,7 @@ class CCPExecutionForm extends HTMLElement{
|
||||||
<link rel="canonical" href="https://getbootstrap.com/docs/5.0/components/modal/">
|
<link rel="canonical" href="https://getbootstrap.com/docs/5.0/components/modal/">
|
||||||
<link rel="stylesheet" href="https://cdn.dev.d4science.org/ccp/css/common.css"></link>
|
<link rel="stylesheet" href="https://cdn.dev.d4science.org/ccp/css/common.css"></link>
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" crossorigin="anonymous">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" crossorigin="anonymous">
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"/>
|
||||||
<style>
|
<style>
|
||||||
.ccp-execution-form{
|
.ccp-execution-form{
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -85,7 +86,11 @@ class CCPExecutionForm extends HTMLElement{
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="col form-check">
|
<div class="col form-check">
|
||||||
<input class="form-check-input" type="checkbox" name="auto-archive-outputs" alt="Automatically archive outputs to workspace" title="Automatically archive outputs to workspace" checked="checked">
|
<input class="form-check-input" type="checkbox" name="auto-archive" alt="Automatically archive the whole execution with metadata to workspace folder" title="Automatically archive the whole execution with metadata to workspace folder">
|
||||||
|
<label class="form-check-label">Automatically archive whole execution to workspace</label>
|
||||||
|
</div>
|
||||||
|
<div class="col form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" name="auto-archive-outputs" alt="Automatically archive only the outputs to workspace" title="Automatically archive only the outputs to workspace" checked="checked">
|
||||||
<label class="form-check-label">Automatically archive outputs to workspace</label>
|
<label class="form-check-label">Automatically archive outputs to workspace</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -115,6 +120,8 @@ class CCPExecutionForm extends HTMLElement{
|
||||||
<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>
|
<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>
|
||||||
<option value="application/x-sh+curl" data-ext="sh" title="Generate Bash script (curl)">Bash (curl)</option>
|
<option value="application/x-sh+curl" data-ext="sh" title="Generate Bash script (curl)">Bash (curl)</option>
|
||||||
<option value="application/x-sh+wget" data-ext="sh" title="Generate Bash script (wget)">Bash (wget)</option>
|
<option value="application/x-sh+wget" data-ext="sh" title="Generate Bash script (wget)">Bash (wget)</option>
|
||||||
|
<option value="application/json+galaxy" data-ext="json" title="Generate JSON request for Galaxy">Galaxy CCP request (preview)</option>
|
||||||
|
<option value="application/xml+galaxy" data-ext="xml" title="Generate installable Galaxy tool">Galaxy tool (preview)</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">
|
||||||
|
@ -251,11 +258,12 @@ class CCPExecutionForm extends HTMLElement{
|
||||||
if(o.enabled) request.outputs[o.name] = { transmissionMode : "value" };
|
if(o.enabled) request.outputs[o.name] = { transmissionMode : "value" };
|
||||||
})
|
})
|
||||||
|
|
||||||
const autoarchiveoption = this.#rootdoc.querySelector("input[name='auto-archive-outputs']")
|
const autoarchiveoption = this.#rootdoc.querySelector("input[name='auto-archive']")
|
||||||
if (autoarchiveoption.checked){
|
const autoarchiveoutputsoption = this.#rootdoc.querySelector("input[name='auto-archive-outputs']")
|
||||||
request.subscribers = [
|
if (autoarchiveoption.checked || autoarchiveoutputoption.checked){
|
||||||
{ successUri : "http://registry:8080/executions/archive-to-folder" }
|
request.subscribers = []
|
||||||
]
|
if(autoarchiveoption.checked) request.subscribers.push({ successUri : "http://registry:8080/executions/archive-to-folder" })
|
||||||
|
if(autoarchiveoutputsoption.checked) request.subscribers.push({ successUri : "http://registry:8080/executions/outputs/archive-to-folder" })
|
||||||
}
|
}
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
|
@ -78,18 +78,18 @@ class CCPExecutionHistory extends HTMLElement {
|
||||||
<span name="status" class="ml-1 badge"></span>
|
<span name="status" class="ml-1 badge"></span>
|
||||||
<div class="d-flex float-right" style="gap: 3px 5px; max-width: 40%; min-width:60px; flex-wrap:wrap;">
|
<div class="d-flex float-right" style="gap: 3px 5px; max-width: 40%; min-width:60px; flex-wrap:wrap;">
|
||||||
${ this.#archive ? `
|
${ this.#archive ? `
|
||||||
<button data-index="0" name="archive" title="Archive to workspace" class="btn btn-primary ccp-toolbar-button ccp-toolbar-button-small">
|
<button data-index="0" name="archive" title="Archive whole execution to workspace folder" class="btn btn-primary ccp-toolbar-button ccp-toolbar-button-small">
|
||||||
<svg viewBox="0 96 960 960"><path d="M140 796h680V516H140v280Zm540.118-90Q701 706 715.5 691.382q14.5-14.617 14.5-35.5Q730 635 715.382 620.5q-14.617-14.5-35.5-14.5Q659 606 644.5 620.618q-14.5 14.617-14.5 35.5Q630 677 644.618 691.5q14.617 14.5 35.5 14.5ZM880 456h-85L695 356H265L165 456H80l142-142q8-8 19.278-13 11.278-5 23.722-5h430q12.444 0 23.722 5T738 314l142 142ZM140 856q-24.75 0-42.375-17.625T80 796V456h800v340q0 24.75-17.625 42.375T820 856H140Z"/></svg>
|
<svg viewBox="0 96 960 960"><path d="M140 796h680V516H140v280Zm540.118-90Q701 706 715.5 691.382q14.5-14.617 14.5-35.5Q730 635 715.382 620.5q-14.617-14.5-35.5-14.5Q659 606 644.5 620.618q-14.5 14.617-14.5 35.5Q630 677 644.618 691.5q14.617 14.5 35.5 14.5ZM880 456h-85L695 356H265L165 456H80l142-142q8-8 19.278-13 11.278-5 23.722-5h430q12.444 0 23.722 5T738 314l142 142ZM140 856q-24.75 0-42.375-17.625T80 796V456h800v340q0 24.75-17.625 42.375T820 856H140Z"/></svg>
|
||||||
</button>`
|
</button>`
|
||||||
: ``
|
: ``
|
||||||
}
|
}
|
||||||
<button data-index="0" name="provo" title="Export to Prov-o document" class="btn btn-primary ccp-toolbar-button ccp-toolbar-button-small">
|
<!--button data-index="0" name="provo" title="Export to Prov-o document" class="btn btn-primary ccp-toolbar-button ccp-toolbar-button-small">
|
||||||
<svg viewBox="0 0 24 24"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M13 3H6v18h4v-6h3c3.31 0 6-2.69 6-6s-2.69-6-6-6zm.2 8H10V7h3.2c1.1 0 2 .9 2 2s-.9 2-2 2z"/></svg>
|
<svg viewBox="0 0 24 24"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M13 3H6v18h4v-6h3c3.31 0 6-2.69 6-6s-2.69-6-6-6zm.2 8H10V7h3.2c1.1 0 2 .9 2 2s-.9 2-2 2z"/></svg>
|
||||||
</button>
|
</button-->
|
||||||
<!-- button data-index="0" name="zip" title="Download as zip archive" class="btn btn-primary ccp-toolbar-button ccp-toolbar-button-small">
|
<!-- button data-index="0" name="zip" title="Download as zip archive" class="btn btn-primary ccp-toolbar-button ccp-toolbar-button-small">
|
||||||
<svg viewBox="0 0 48 48"><path d="M7 40q-1.15 0-2.075-.925Q4 38.15 4 37V11q0-1.15.925-2.075Q5.85 8 7 8h14l3 3h17q1.15 0 2.075.925Q44 12.85 44 14v23q0 1.15-.925 2.075Q42.15 40 41 40Zm25-3h9V14h-9v4.6h4.6v4.6H32v4.6h4.6v4.6H32ZM7 37h20.4v-4.6H32v-4.6h-4.6v-4.6H32v-4.6h-4.6V14h-4.65l-3-3H7v26Zm0-23v-3 26-23Z"/></svg>
|
<svg viewBox="0 0 48 48"><path d="M7 40q-1.15 0-2.075-.925Q4 38.15 4 37V11q0-1.15.925-2.075Q5.85 8 7 8h14l3 3h17q1.15 0 2.075.925Q44 12.85 44 14v23q0 1.15-.925 2.075Q42.15 40 41 40Zm25-3h9V14h-9v4.6h4.6v4.6H32v4.6h4.6v4.6H32ZM7 37h20.4v-4.6H32v-4.6h-4.6v-4.6H32v-4.6h-4.6V14h-4.65l-3-3H7v26Zm0-23v-3 26-23Z"/></svg>
|
||||||
</button-->
|
</button-->
|
||||||
<button data-index="0" name="archivefolder" title="Archive outputs to workspace" class="btn btn-primary ccp-toolbar-button ccp-toolbar-button-small">
|
<button data-index="0" name="archiveoutputs" title="Archive only outputs to workspace folder" class="btn btn-primary ccp-toolbar-button ccp-toolbar-button-small">
|
||||||
<svg viewBox="0 0 48 48"><path d="M7 40q-1.15 0-2.075-.925Q4 38.15 4 37V11q0-1.15.925-2.075Q5.85 8 7 8h14l3 3h17q1.15 0 2.075.925Q44 12.85 44 14v23q0 1.15-.925 2.075Q42.15 40 41 40Zm25-3h9V14h-9v4.6h4.6v4.6H32v4.6h4.6v4.6H32ZM7 37h20.4v-4.6H32v-4.6h-4.6v-4.6H32v-4.6h-4.6V14h-4.65l-3-3H7v26Zm0-23v-3 26-23Z"/></svg>
|
<svg viewBox="0 0 48 48"><path d="M7 40q-1.15 0-2.075-.925Q4 38.15 4 37V11q0-1.15.925-2.075Q5.85 8 7 8h14l3 3h17q1.15 0 2.075.925Q44 12.85 44 14v23q0 1.15-.925 2.075Q42.15 40 41 40Zm25-3h9V14h-9v4.6h4.6v4.6H32v4.6h4.6v4.6H32ZM7 37h20.4v-4.6H32v-4.6h-4.6v-4.6H32v-4.6h-4.6V14h-4.65l-3-3H7v26Zm0-23v-3 26-23Z"/></svg>
|
||||||
</button>
|
</button>
|
||||||
<button data-index="0" name="reexecute1" title="Re-submit this execution" class="btn btn-info ccp-toolbar-button ccp-toolbar-button-small">
|
<button data-index="0" name="reexecute1" title="Re-submit this execution" class="btn btn-info ccp-toolbar-button ccp-toolbar-button-small">
|
||||||
|
@ -208,7 +208,7 @@ class CCPExecutionHistory extends HTMLElement {
|
||||||
const link = ev.target.parentElement.querySelector("input").value
|
const link = ev.target.parentElement.querySelector("input").value
|
||||||
if(link){
|
if(link){
|
||||||
if(confirm("Please confirm importing of execution from link?")){
|
if(confirm("Please confirm importing of execution from link?")){
|
||||||
this.fromArchive(link)
|
this.fromArchiveFolder(link)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -425,30 +425,30 @@ class CCPExecutionHistory extends HTMLElement {
|
||||||
}).catch(err=>{ alert(err)})
|
}).catch(err=>{ alert(err)})
|
||||||
}
|
}
|
||||||
|
|
||||||
toArchive(id){
|
|
||||||
this.#boot.secureFetch(`${this.#serviceurl}/executions/${id}/archive`, { method: "POST" })
|
|
||||||
.then(reply =>{
|
|
||||||
if (!reply.ok) {
|
|
||||||
throw "Unable to archive"
|
|
||||||
}
|
|
||||||
}).catch(err=>{ alert(err)})
|
|
||||||
}
|
|
||||||
|
|
||||||
toArchiveFolder(id){
|
toArchiveFolder(id){
|
||||||
this.#boot.secureFetch(`${this.#serviceurl}/executions/${id}/archive-to-folder`, { method: "POST" })
|
this.#boot.secureFetch(`${this.#serviceurl}/executions/${id}/archive-to-folder`, { method: "POST" })
|
||||||
.then(reply =>{
|
.then(reply =>{
|
||||||
if (!reply.ok) {
|
if (!reply.ok) {
|
||||||
throw "Unable to archive"
|
throw "Unable to archive execution to folder"
|
||||||
}
|
}
|
||||||
}).catch(err=>{ alert(err)})
|
}).catch(err=>{ alert(err)})
|
||||||
}
|
}
|
||||||
|
|
||||||
fromArchive(url){
|
toOutputsArchiveFolder(id){
|
||||||
|
this.#boot.secureFetch(`${this.#serviceurl}/executions/${id}/outputs/archive-to-folder`, { method: "POST" })
|
||||||
|
.then(reply =>{
|
||||||
|
if (!reply.ok) {
|
||||||
|
throw "Unable to archive outputs to folder"
|
||||||
|
}
|
||||||
|
}).catch(err=>{ alert(err)})
|
||||||
|
}
|
||||||
|
|
||||||
|
fromArchiveFolder(url){
|
||||||
if(url){
|
if(url){
|
||||||
this.#boot.secureFetch(`${this.#serviceurl}/executions/archive?url=${url}`)
|
this.#boot.secureFetch(`${this.#serviceurl}/executions/archive?url=${url}`)
|
||||||
.then(reply =>{
|
.then(reply =>{
|
||||||
if (!reply.ok) {
|
if (!reply.ok) {
|
||||||
throw "Unable to fetch from archive"
|
throw "Unable to fetch from archive folder"
|
||||||
}
|
}
|
||||||
return reply.text()
|
return reply.text()
|
||||||
}).then(data=>{
|
}).then(data=>{
|
||||||
|
@ -555,17 +555,17 @@ class CCPExecutionHistory extends HTMLElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(ev.target.getAttribute("name") === "archive"){
|
if(ev.target.getAttribute("name") === "archive"){
|
||||||
if(confirm(" Please confirm archiving of execution to workspace?")){
|
if(confirm(" Please confirm archiving of execution to workspace folder?")){
|
||||||
const id = ev.currentTarget.getAttribute("data-index")
|
|
||||||
this.toArchive(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(ev.target.getAttribute("name") === "archivefolder"){
|
|
||||||
if(confirm(" Please confirm archiving of execution outputs to workspace?")){
|
|
||||||
const id = ev.currentTarget.getAttribute("data-index")
|
const id = ev.currentTarget.getAttribute("data-index")
|
||||||
this.toArchiveFolder(id)
|
this.toArchiveFolder(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(ev.target.getAttribute("name") === "archiveoutputs"){
|
||||||
|
if(confirm(" Please confirm archiving of execution outputs to workspace folder?")){
|
||||||
|
const id = ev.currentTarget.getAttribute("data-index")
|
||||||
|
this.toOutputsArchiveFolder(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
recurse : [
|
recurse : [
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,6 +43,11 @@ class CCPInputWidgetController extends HTMLElement {
|
||||||
this.innerHTML += `<d4s-ccp-input-remotefile readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-remotefile>`
|
this.innerHTML += `<d4s-ccp-input-remotefile readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-remotefile>`
|
||||||
this.querySelector("d4s-ccp-input-remotefile").default = this.#data.schema.default
|
this.querySelector("d4s-ccp-input-remotefile").default = this.#data.schema.default
|
||||||
|
|
||||||
|
} else if (this.isGeo()) {
|
||||||
|
|
||||||
|
this.innerHTML += `<d4s-ccp-input-geo readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-remotefile>`
|
||||||
|
this.querySelector("d4s-ccp-input-geo").default = this.#data.schema.default
|
||||||
|
|
||||||
} else if (this.isSecret()) {
|
} else if (this.isSecret()) {
|
||||||
|
|
||||||
this.innerHTML += `<d4s-ccp-input-secret readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs }" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-secret>`
|
this.innerHTML += `<d4s-ccp-input-secret readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs }" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-secret>`
|
||||||
|
@ -130,6 +135,13 @@ class CCPInputWidgetController extends HTMLElement {
|
||||||
(this.#data.schema.format.toLowerCase() === "remotefile")
|
(this.#data.schema.format.toLowerCase() === "remotefile")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isGeo() {
|
||||||
|
return (this.#data.schema.type === "string") &&
|
||||||
|
("format" in this.#data.schema) &&
|
||||||
|
(this.#data.schema.format != null) &&
|
||||||
|
(this.#data.schema.format.toLowerCase() === "geo")
|
||||||
|
}
|
||||||
|
|
||||||
isDateTime() {
|
isDateTime() {
|
||||||
return (this.#data.schema.type === "string") &&
|
return (this.#data.schema.type === "string") &&
|
||||||
("format" in this.#data.schema) &&
|
("format" in this.#data.schema) &&
|
||||||
|
@ -600,11 +612,11 @@ class CCPRemoteFileInputWidgetController extends CCPBaseInputWidgetController {
|
||||||
<div class="mb-1" style="border-bottom: solid 1px gray;">
|
<div class="mb-1" style="border-bottom: solid 1px gray;">
|
||||||
<div class="d-flex justify-content-between m-0">
|
<div class="d-flex justify-content-between m-0">
|
||||||
<h5 class="text-secondary m-0">Access your workspace</h5>
|
<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>
|
<span class="material-icons btn text-danger p-0" style="font-weight:bold" name="closebtn">close</span>
|
||||||
</div>
|
</div>
|
||||||
<small class="text-muted m-0">Select an item or drag and drop it to a proper input</small>
|
<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:auto;etxt-wrap:nowrap;text-overflow: ellipsis;min-height:5rem; max-height:10rem;">
|
<div style="min-width:500px; max-width:640px;overflow:auto;etxt-wrap:nowrap;text-overflow: ellipsis;min-height:5rem; max-height:10rem;">
|
||||||
<d4s-storage-tree
|
<d4s-storage-tree
|
||||||
base-url="${addresses[iss]}"
|
base-url="${addresses[iss]}"
|
||||||
file-download-enabled="true"
|
file-download-enabled="true"
|
||||||
|
@ -771,3 +783,220 @@ class CCPSecretInputWidgetController extends CCPBaseInputWidgetController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window.customElements.define('d4s-ccp-input-secret', CCPSecretInputWidgetController);
|
window.customElements.define('d4s-ccp-input-secret', CCPSecretInputWidgetController);
|
||||||
|
|
||||||
|
class CCPGeoInputWidgetController extends CCPBaseInputWidgetController {
|
||||||
|
|
||||||
|
#format_dialog = null;
|
||||||
|
#target = null
|
||||||
|
#draw = null;
|
||||||
|
#raster = null
|
||||||
|
#source = null
|
||||||
|
#map = null;
|
||||||
|
#vector = null
|
||||||
|
#index = null;
|
||||||
|
#widget = null
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addToolContent() {
|
||||||
|
|
||||||
|
this.rootdoc.querySelector("div[name=tools]").innerHTML += `
|
||||||
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||||
|
<svg name="trigger" style="width:24;height:24;fill:#007bff; cursor:pointer" viewBox="0 -960 960 960">
|
||||||
|
<path d="M480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm-40-82v-78q-33 0-56.5-23.5T360-320v-40L168-552q-3 18-5.5 36t-2.5 36q0 121 79.5 212T440-162Zm276-102q20-22 36-47.5t26.5-53q10.5-27.5 16-56.5t5.5-59q0-98-54.5-179T600-776v16q0 33-23.5 56.5T520-680h-80v80q0 17-11.5 28.5T400-560h-80v80h240q17 0 28.5 11.5T600-440v120h40q26 0 47 15.5t29 40.5Z"/>
|
||||||
|
</svg>
|
||||||
|
<div name="map" class="d-none position-absolute shadow border border-primary bg-light p-2" style="right:0;z-index:1000; line-height:1.5rem;overflow:hidden;padding:5px;">
|
||||||
|
<div name="maptoolbar" class="mb-1" style="border-bottom: solid 1px gray;">
|
||||||
|
<div class="d-flex justify-content-between m-0">
|
||||||
|
<div>
|
||||||
|
<span title="Draw a rectangular box" name="Box" class="btn text-primary p-0 material-icons">crop_16_9</span>
|
||||||
|
<span title="Draw a circle" name="Circle" class="btn text-primary p-0 material-icons">radio_button_unchecked</span>
|
||||||
|
<span title="Select a Point" name="Point" class="btn text-primary p-0 material-icons">my_location</span>
|
||||||
|
<span title="Draw a Polygon" name="Polygon" class="btn text-primary p-0 material-icons" style="color:transparent">pentagon</span>
|
||||||
|
<span title="Delete all" name="deletebtn" class="btn text-danger p-0 material-icons">delete</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span title="Set geometry" class="btn btn-primary" style="font-weight:bold" name="selectbtn">Export</span>
|
||||||
|
<span title="Close" class="material-icons btn text-danger p-0" style="font-weight:bold" name="closebtn">close</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<small class="text-muted m-0">Draw and export geometry</small>
|
||||||
|
</div>
|
||||||
|
<div style="width:500px;height:500px;position:relative;">
|
||||||
|
<style>
|
||||||
|
div[name=internalmap]{
|
||||||
|
width: 100%;
|
||||||
|
height:100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div name="internalmap"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal fade" style="background-color:rgba(0,0,0,0.3)" name="format" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content shadow-lg border-primary">
|
||||||
|
<div class="modal-body">
|
||||||
|
Choose export format.
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<span title="Export WKT" name="wkt" class="btn btn-info">WKT</span>
|
||||||
|
<span title="Export to GML" name="gml" class="btn btn-primary">GML</span>
|
||||||
|
<span title="Export to GeoJSON" name="geojson" class="btn btn-secondary">GeoJSON</span>
|
||||||
|
<span title="Cancel" name="cancel" class="btn btn-danger">Cancel</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
|
||||||
|
// Init map
|
||||||
|
this.init()
|
||||||
|
|
||||||
|
this.rootdoc.querySelector("div[name=maptoolbar]").addEventListener("click", ev=>{
|
||||||
|
const type = ev.target.getAttribute("name")
|
||||||
|
if(type === "closebtn"){
|
||||||
|
this.#widget.classList.add("d-none")
|
||||||
|
ev.preventDefault()
|
||||||
|
ev.stopPropagation()
|
||||||
|
}if(type === "selectbtn"){
|
||||||
|
this.#widget.classList.add("d-none")
|
||||||
|
this.#format_dialog.style.display = "block"
|
||||||
|
this.#format_dialog.classList.add("show")
|
||||||
|
this.#index = this.value.length - 1
|
||||||
|
const alltargets = this.#target = this.rootdoc.querySelectorAll("textarea")
|
||||||
|
for(let i=0; i < alltargets.length;i++){
|
||||||
|
if(!alltargets.item(i).value[i]){
|
||||||
|
this.#index = i
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.#target = this.rootdoc.querySelectorAll("textarea").item(this.#index)
|
||||||
|
ev.preventDefault()
|
||||||
|
ev.stopPropagation()
|
||||||
|
}else if(["Circle", "Point", "Polygon", "Box"].indexOf(type) !== -1){
|
||||||
|
ev.stopPropagation();
|
||||||
|
ev.preventDefault();
|
||||||
|
this.undoAllDrawings()
|
||||||
|
if(this.#draw != null && this.#draw.type === type) return;
|
||||||
|
if(this.#draw != null) this.#map.removeInteraction(this.#draw);
|
||||||
|
this.#draw = new ol.interaction.Draw({
|
||||||
|
source: this.#source,
|
||||||
|
type : type === "Box" ? "Circle" : type,
|
||||||
|
geometryFunction : type === "Box" ? ol.interaction.Draw.createBox() : null
|
||||||
|
})
|
||||||
|
this.#map.addInteraction(this.#draw)
|
||||||
|
}else if(type === "deletebtn"){
|
||||||
|
this.undoAllDrawings()
|
||||||
|
ev.preventDefault()
|
||||||
|
ev.stopPropagation()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
document.addEventListener("keydown", ev=>{
|
||||||
|
if (ev.ctrlKey && ev.key === 'z') {
|
||||||
|
this.undoDrawing()
|
||||||
|
}else if(ev.key === "Escape"){
|
||||||
|
this.stopDrawing()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.#format_dialog = this.rootdoc.querySelector("div.modal[name=format]")
|
||||||
|
this.#format_dialog.addEventListener("click", ev => {
|
||||||
|
ev.stopPropagation()
|
||||||
|
ev.preventDefault()
|
||||||
|
const features = this.#source.getFeatures()
|
||||||
|
if( features.length && this.#index != null && this.#target != null){
|
||||||
|
const name = ev.target.getAttribute("name")
|
||||||
|
var format
|
||||||
|
if(name === "wkt") {
|
||||||
|
format = new ol.format.WKT()
|
||||||
|
}else if(name === "geojson"){
|
||||||
|
format = new ol.format.GeoJSON()
|
||||||
|
}else if(name === "gml"){
|
||||||
|
format = new ol.format.GML()
|
||||||
|
}
|
||||||
|
const result = features.map(f=>{
|
||||||
|
const geom = f.getGeometry().getType() === "Circle" ? ol.geom.Polygon.fromCircle(f.getGeometry(), 50) : f.getGeometry()
|
||||||
|
const tgeom = geom.transform(this.#map.getView().getProjection(), new ol.proj.Projection({code: "EPSG:4326"}))
|
||||||
|
return format.writeGeometry(tgeom)
|
||||||
|
}).join("\n")
|
||||||
|
|
||||||
|
this.#target.value = this.value[this.#index] = result
|
||||||
|
const newev = new Event("input", { bubbles : true})
|
||||||
|
this.dispatchEvent(newev)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#format_dialog.style.display = "none"
|
||||||
|
this.#format_dialog.classList.remove("show")
|
||||||
|
})
|
||||||
|
|
||||||
|
this.rootdoc.querySelector("svg[name=trigger]").addEventListener("click", ev => {
|
||||||
|
this.#widget.classList.toggle("d-none")
|
||||||
|
ev.preventDefault()
|
||||||
|
ev.stopPropagation()
|
||||||
|
})
|
||||||
|
|
||||||
|
this.rootdoc.addEventListener("input", ev=>{
|
||||||
|
if(ev.target.getAttribute("name") === this.name && ev.target.getAttribute("data-index")){
|
||||||
|
const index = Number(ev.target.getAttribute("data-index"))
|
||||||
|
this.value[index] = ev.target.value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
init(){
|
||||||
|
this.#widget = this.rootdoc.querySelector("div[name=map]")
|
||||||
|
this.#draw = null
|
||||||
|
this.#raster = new ol.layer.Tile({source: new ol.source.OSM()});
|
||||||
|
this.#source = new ol.source.Vector({wrapX: false});
|
||||||
|
this.#vector = new ol.layer.Vector({source: this.#source});
|
||||||
|
|
||||||
|
this.#map = new ol.Map({
|
||||||
|
layers: [this.#raster, this.#vector],
|
||||||
|
target: this.rootdoc.querySelector("div[name=internalmap]"),
|
||||||
|
view: new ol.View({center: [0, 0], zoom: 4 }),
|
||||||
|
controls :[]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
undoAllDrawings(){
|
||||||
|
this.#source.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
undoDrawing(){
|
||||||
|
const features = this.#source.getFeatures()
|
||||||
|
if(features.length){
|
||||||
|
this.#source.removeFeature(features[features.length-1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stopDrawing(){
|
||||||
|
if(this.#draw){
|
||||||
|
this.#draw.abortDrawing()
|
||||||
|
this.#map.removeInteraction(this.#draw);
|
||||||
|
this.#draw = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
content() {
|
||||||
|
if(!this.readonly && !this.querySelector("div[name=map]")) this.addToolContent();
|
||||||
|
if (this.value.length <= 1) {
|
||||||
|
return `
|
||||||
|
<textarea name="${this.name}" data-index="0" class="ccp-input my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" rows="5" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}>${this.value.length ? this.value[0] : ''}</textarea>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
var out =
|
||||||
|
this.value.map((c, i) => {
|
||||||
|
return `
|
||||||
|
<textarea name="${this.name}" data-index="${i}" class="ccp-input my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" rows="5" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}>${c}</textarea>
|
||||||
|
`
|
||||||
|
}).join("\n")
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.customElements.define('d4s-ccp-input-geo', CCPGeoInputWidgetController);
|
||||||
|
|
|
@ -127,6 +127,7 @@ class CCPInputWidgetEditorController extends HTMLElement{
|
||||||
<option value="code" ${this.isSelectedFormat('code') ? "selected" : ""}>Code</option>
|
<option value="code" ${this.isSelectedFormat('code') ? "selected" : ""}>Code</option>
|
||||||
<option value="file" ${this.isSelectedFormat('file') ? "selected" : ""}>File</option>
|
<option value="file" ${this.isSelectedFormat('file') ? "selected" : ""}>File</option>
|
||||||
<option value="remotefile" ${this.isSelectedFormat('remotefile') ? "selected" : ""}>Workspace file</option>
|
<option value="remotefile" ${this.isSelectedFormat('remotefile') ? "selected" : ""}>Workspace file</option>
|
||||||
|
<option value="geo" ${this.isSelectedFormat('geo') ? "selected" : ""}>Geography</option>
|
||||||
<option value="secret" ${this.isSelectedFormat('secret') ? "selected" : ""}>Secret</option>
|
<option value="secret" ${this.isSelectedFormat('secret') ? "selected" : ""}>Secret</option>
|
||||||
<option value="url" ${this.isSelectedFormat('url') ? "selected" : ""}>Url</option>
|
<option value="url" ${this.isSelectedFormat('url') ? "selected" : ""}>Url</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
|
@ -890,7 +890,7 @@ class D4SWorkspace {
|
||||||
* @throws the error as string, if occurred
|
* @throws the error as string, if occurred
|
||||||
*/
|
*/
|
||||||
listFolder(folderId, extraHeaders) {
|
listFolder(folderId, extraHeaders) {
|
||||||
const uri = "/items/" + folderId + "/children";
|
const uri = "/items/" + folderId + "/children?exclude=hl:accounting";
|
||||||
return this.#callWorkspace("GET", uri, null, null, extraHeaders)
|
return this.#callWorkspace("GET", uri, null, null, extraHeaders)
|
||||||
.then(blob => {
|
.then(blob => {
|
||||||
return blob.text().then(text => {
|
return blob.text().then(text => {
|
||||||
|
|
Loading…
Reference in New Issue