last demo import - cleaned

This commit is contained in:
ycc
2023-08-26 22:04:56 +02:00
parent 0ab5dd5e38
commit f3c3c67e2c
884 changed files with 301494 additions and 1 deletions

40
views/datacenter.tpl Normal file
View File

@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html>
<head>
<title>Machines list</title>
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicon-16x16.png">
<link rel="manifest" href="/static/site.webmanifest">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--Import Google Icon Font-->
<link type="text/css" rel="stylesheet" href="/static/css/material-icons.css">
<!--Import materialize.css-->
<link type="text/css" rel="stylesheet" href="/static/css/materialize.min.css" media="screen,projection" />
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
.small {
font-size: x-small;
}
</style>
</head>
<body>
<div class="row">
<a href="/"><img src="/static/img/O-cloud.svg" width="10%" height="auto"/></a>
<br/>
</div>
<script type="text/javascript" src="/static/js/materialize.min.js"></script>
</body>
</html>

139
views/details.tpl Normal file
View File

@@ -0,0 +1,139 @@
<!DOCTYPE html>
<html>
<head>
<title>o-search</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--Import Google Icon Font-->
<link type="text/css" rel="stylesheet" href="/static/css/material-icons.css">
<!--Import materialize.css-->
<link type="text/css" rel="stylesheet" href="/static/css/materialize.min.css" media="screen,projection" />
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
.small {
font-size: x-small;
}
</style>
<script type="text/javascript" src="/static/js/jquery-3.5.1.min.js"></script>
<link href='/static/fullcalendar/main.css' rel='stylesheet' />
<script src='/static/fullcalendar/main.js'></script>
<script type="text/javascript">
$( document ).ready(function() {
$('.tooltipped').tooltip();
$('.fixed-action-btn').floatingActionButton({direction: 'bottom'});
;(function() {
jQuery.expr[':'].containsNC = function(elem, index, match) {
return (elem.textContent || elem.innerText || jQuery(elem).text() || '').toLowerCase().indexOf((match[3] || '').toLowerCase()) >= 0;
}
}(jQuery));
$('#filter').on('input',function(e)
{
if ($('#filter').val())
{
$('a')
.find('span').not(':containsNC('+$('#filter').val()+')')
.parent()
//.css('outline', '3px solid red');
.hide();
$('a')
.find('span:containsNC('+$('#filter').val()+')')
.parent()
//.css('outline', '3px solid red');
.show();
}
});
});
</script>
</head>
<body>
{{ template "floating_menu.tpl" . }}
<div class="row">
<div class="col s4">
<a href="/"><img src="/static/img/O-cloud.svg" width="40%" height="auto"/></a>
</div>
</div>
<div class="collection">
<div class="row collection-item">
<div>
<img src="data:image/png;base64,{{.data.Logo}}"/>
</div>
<div id="resourceData">
<span rtype="{{.data | getRtype}}" rid="{{.data.ID}}" class="title">{{.data.Name}}</span><br>
<span class="small">{{.data.ID}} </span><br/>
<span class="small">{{.data.ShortDescription}} </span><br/>
<span class="small">[{{.data | getRtype}}]</span><br/>
</div>
<div class="col s1">
<a id="addButton" disabled="true" onclick="submitWorkspace()" class="btn tooltipped gray" data-position="bottom" data-tooltip="Add to Workspace" ><i class="material-icons">shopping_cart</i></a>
</div>
</div>
</div>
<script type="text/javascript" src="/static/js/materialize.min.js"></script>
</body>
{{ template "swagger.tpl" . }}
<script>
elem = document.getElementById("resourceData").querySelector("*[rid]");
var rid = elem.getAttribute("rid")
var rtype = elem.getAttribute("rtype")
window.onload = setInitialStatus;
function setInitialStatus() {
oc_catalog_api.then(client => {
client.apis
.workspace
.WorkspaceController_Get_workspace()
.then(response => {
//console.log(response);
if ( response.body[rtype].includes(rid)) {
document.getElementById("addButton").setAttribute("disabled", true);
} else {
document.getElementById("addButton").removeAttribute("disabled");
}
})
.catch((error) => {
console.log("ERROR: " + error)
});
});
}
//TODO: Make this function with callbacks in order to be used by any
function submitWorkspace() {
oc_catalog_api.then(client => {
client.apis
.workspace
.WorkspaceController_Add_model_to_workspace({id: rid, rtype: rtype})
.then(response => {
document.getElementById("addButton").setAttribute("disabled", true);
})
.catch((error) => {
console.log("ERROR: " + error)
});
});
}
</script>
</html>

13
views/floating_menu.tpl Normal file
View File

@@ -0,0 +1,13 @@
<div class="fixed-action-btn" style="position: absolute; top:20px; right: 24px;">
<a class="btn-floating btn-large">
<i class="large material-icons">menu</i>
</a>
<ul>
<li><a class="btn-floating tooltipped grey" data-position="left" data-tooltip="Map view" href="/map"><i class="material-icons">public</i></a></li>
<li><a class="btn-floating tooltipped red" data-position="left" data-tooltip="My datacenter" href="/datacenter"><i class="material-icons">dns</i></a></li>
<li><a class="btn-floating tooltipped orange" data-position="left" data-tooltip="Scheduled tasks" href="/schedule"><i class="material-icons">schedule</i></a></li>
<li><a class="btn-floating tooltipped yellow darken-1" data-position="left" data-tooltip="Task workflow editor" href="/workflow"><i class="material-icons">play_arrow</i></a></li>
<li><a class="btn-floating tooltipped green" data-position="left" data-tooltip="Workspace" href="/workspace"><i class="material-icons">shopping_cart</i></a></li>
<li><a class="btn-floating tooltipped blue" data-position="left" data-tooltip="User" href="/user"><i class="material-icons">person</i></a></li>
</ul>
</div>

85
views/identity.tpl Normal file
View File

@@ -0,0 +1,85 @@
<!DOCTYPE html>
<html>
<head>
<title>o-search</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--Import Google Icon Font-->
<link type="text/css" rel="stylesheet" href="/static/css/material-icons.css">
<!--Import materialize.css-->
<link type="text/css" rel="stylesheet" href="/static/css/materialize.min.css" media="screen,projection" />
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
.small {
font-size: x-small;
}
</style>
<script type="text/javascript" src="/static/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript">
$( document ).ready(function() {
$('.tooltipped').tooltip();
$('.fixed-action-btn').floatingActionButton({direction: 'bottom'});
;(function() {
jQuery.expr[':'].containsNC = function(elem, index, match) {
return (elem.textContent || elem.innerText || jQuery(elem).text() || '').toLowerCase().indexOf((match[3] || '').toLowerCase()) >= 0;
}
}(jQuery));
$('#filter').on('input',function(e)
{
if ($('#filter').val())
{
$('a')
.find('span').not(':containsNC('+$('#filter').val()+')')
.parent()
//.css('outline', '3px solid red');
.hide();
$('a')
.find('span:containsNC('+$('#filter').val()+')')
.parent()
//.css('outline', '3px solid red');
.show();
}
});
});
</script>
</head>
<body>
{{ template "floating_menu.tpl" . }}
<div class="row">
<div class="col s4">
<a href="/"><img src="/static/img/O-cloud.svg" width="40%" height="auto"/></a>
</div>
</div>
<div class="collection">
{{range $key, $value := .list}}
<div class="row collection-item">
<a href="/details/{{$value.Id}}">
<div class="col s1">
<img src="{{$value.Logo}}" style="width: 50%; height: 50%"/>
</div>
<div class="col s10">
<span class="title">{{$value.Name}}</span><br>
<span class="small">{{$value.ShortDescription}} </span>
<span class="small">[{{$value.Type}}]</span>
</div>
</a>
<div class="col s1">
<a class="btn tooltipped gray" data-position="bottom" data-tooltip="Remove from Workspace" ><i class="material-icons">delete</i></a>
</div>
</div>
{{end}}
</div>
<script type="text/javascript" src="/static/js/materialize.min.js"></script>
</body>
</html>

64
views/index.tpl Normal file
View File

@@ -0,0 +1,64 @@
<!DOCTYPE html>
<html>
<head>
<title>o-search</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--Import Google Icon Font-->
<link href="/static/css/material-icons.css" rel="stylesheet">
<!--Import materialize.css-->
<link type="text/css" rel="stylesheet" href="/static/css/materialize.min.css" media="screen,projection" />
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
.small {
font-size: x-small;
}
</style>
<script type="text/javascript" src="/static/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript">
$( document ).ready(function() {
$('.tooltipped').tooltip();
$('.fixed-action-btn').floatingActionButton({direction: 'bottom'});
$("#local").click( function()
{
query = $("#search").val()
if (query) {
window.location="/search?q="+encodeURIComponent($("#search").val());
}
}
);
});
</script>
</head>
<body>
{{ template "floating_menu.tpl" . }}
<div class="row">
<div class="center-align">
<img src="/static/img/O-cloud.svg" width="20%" height="auto"/>
</div>
<div class="input-field col s6 offset-s3">
<i class="material-icons prefix">search</i>
<input id="search" type="text" class="autocomplete">
</div>
</div>
<div class="row">
<div class="center-align">
<button class="btn waves-effect tooltipped waves-light btn-small" data-position="bottom" data-tooltip="Search in my local datacenter" id="local" name="local">Local Search<i class="material-icons left">home</i>
</button>
<button class="btn waves-effect tooltipped waves-light btn-small" data-position="bottom" data-tooltip="Distributed search in my partners network" id="network" name="network">Network Search<i class="material-icons left">public</i>
</button>
</div>
</div>
<script type="text/javascript" src="/static/js/materialize.min.js"></script>
</body>
</html>

63
views/item_add.tpl Normal file
View File

@@ -0,0 +1,63 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css"/>
</head>
<body>
<section class="section">
<!-- CSS Styles -->
<style>
.speech input {border: 0; width: 240px; display: inline-block; height: 30px; visibility:hidden;}
.speech img {float: right; width: 40px }
</style>
<!-- Search Form -->
<form id="speak" method="post" action="/item/add">
<div class="speech">
<input type="text" name="q" id="transcript" placeholder="Speak" />
<img onclick="startDictation()" src="/static/img/mic.png" />
</div>
<div id="history">
<table class="table is-striped is-fullwidth">
<!-- php
foreach (array_reverse($rqList) as $rq => $ts)
{
echo "<tr><td>".date("d/m/Y H:i:s", $ts)."</td><td>".$rq."</td></tr>";
}
-->
</table>
</div>
</form>
</section>
</body>
<!-- HTML5 Speech Recognition API -->
<script>
function startDictation() {
if (window.hasOwnProperty('webkitSpeechRecognition')) {
var recognition = new webkitSpeechRecognition();
recognition.continuous = false;
recognition.interimResults = false;
recognition.lang = "en-US";
recognition.start();
recognition.onresult = function(e) {
document.getElementById('transcript').value
= e.results[0][0].transcript;
recognition.stop();
document.getElementById('speak').submit();
};
recognition.onerror = function(e) {
recognition.stop();
}
}
}
</script>

69
views/login.tpl Normal file
View File

@@ -0,0 +1,69 @@
<!DOCTYPE html>
<html>
<head>
<title>o-cloud login</title>
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicon-16x16.png">
<link rel="manifest" href="/static/site.webmanifest">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--Import Google Icon Font-->
<link type="text/css" rel="stylesheet" href="/static/css/material-icons.css">
<!--Import materialize.css-->
<link type="text/css" rel="stylesheet" href="/static/css/materialize.min.css" media="screen,projection" />
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
.small {
font-size: x-small;
}
</style>
</head>
<body>
<div class="row">
<form action="/login" method="POST" class="col s12">
<div class="row">
<div class="input-field col s2 offset-s5">
<i class="material-icons prefix">account_circle</i>
<input name="login" id="login" type="text" class="validate">
<label for="login">Login</label>
</div>
</div>
<div class="row">
<div class="input-field col s2 offset-s5">
<i class="material-icons prefix">vpn_key</i>
<input name="password" id="password" type="password" class="validate">
<label for="password">Password</label>
</div>
</div>
<div class="row">
<div class="input-field col s2 offset-s6">
<button class="btn waves-effect waves-light" type="submit">Local login
<i class="material-icons right">send</i>
</button>
</div>
</div>
<div class="row">
<div class="input-field col s2 offset-s6">
<a class="waves-effect waves-light btn" href="/oidc"><i class="material-icons left">mail</i>O-Mail login</a>
</div> Ò
</div>
</form>
</div>
<script type="text/javascript" src="/static/js/materialize.min.js"></script>
</body>
</html>

77
views/map.tpl Normal file
View File

@@ -0,0 +1,77 @@
<!DOCTYPE html>
<html>
<head>
<title>o-search</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--Import Google Icon Font-->
<link type="text/css" rel="stylesheet" href="/static/css/material-icons.css">
<!--Import materialize.css-->
<link type="text/css" rel="stylesheet" href="/static/css/materialize.min.css" media="screen,projection" />
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
.map {
width: 100%;
height:800px;
}
</style>
<style>
.small {
font-size: x-small;
}
</style>
<!--Leaflet-->
<link rel="stylesheet" href="/static/css/leaflet.css" />
<script src="/static/js/leaflet.js"></script>
<script type="text/javascript" src="/static/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript">
$( document ).ready(function() {
$('.tooltipped').tooltip();
$('.fixed-action-btn').floatingActionButton({direction: 'bottom'});
var map = L.map('mapid').setView([43.55, 1.49], 11);
var osmLayer = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { // LIGNE 20
attribution: '© OpenStreetMap contributors',
maxZoom: 19
});
map.addLayer(osmLayer);
var partners = new L.geoJson();
partners.addTo(map);
$.ajax({
dataType: "json",
url: "/static/partners.json",
success: function(data) {
$(data.features).each(function(key, data) {
partners.addData(data);
});
}
}).fail(function() {console.log("Failed to load JSON")});
});
</script>
</head>
<body>
{{ template "floating_menu.tpl" . }}
<div class="row">
<div class="center-align">
<a href="/"><img src="/static/img/O-cloud.svg" width="10%" height="auto"/></a>
</div>
<div id="mapid" class="map">
</div>
</div>
<script type="text/javascript" src="/static/js/materialize.min.js"></script>
</body>
</html>

85
views/networks.tpl Normal file
View File

@@ -0,0 +1,85 @@
<!DOCTYPE html>
<html>
<head>
<title>o-search</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--Import Google Icon Font-->
<link type="text/css" rel="stylesheet" href="/static/css/material-icons.css">
<!--Import materialize.css-->
<link type="text/css" rel="stylesheet" href="/static/css/materialize.min.css" media="screen,projection" />
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
.small {
font-size: x-small;
}
</style>
<script type="text/javascript" src="/static/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript">
$( document ).ready(function() {
$('.tooltipped').tooltip();
$('.fixed-action-btn').floatingActionButton({direction: 'bottom'});
;(function() {
jQuery.expr[':'].containsNC = function(elem, index, match) {
return (elem.textContent || elem.innerText || jQuery(elem).text() || '').toLowerCase().indexOf((match[3] || '').toLowerCase()) >= 0;
}
}(jQuery));
$('#filter').on('input',function(e)
{
if ($('#filter').val())
{
$('a')
.find('span').not(':containsNC('+$('#filter').val()+')')
.parent()
//.css('outline', '3px solid red');
.hide();
$('a')
.find('span:containsNC('+$('#filter').val()+')')
.parent()
//.css('outline', '3px solid red');
.show();
}
});
});
</script>
</head>
<body>
{{ template "floating_menu.tpl" . }}
<div class="row">
<div class="col s4">
<a href="/"><img src="/static/img/O-cloud.svg" width="40%" height="auto"/></a>
</div>
</div>
<div class="collection">
{{range $key, $value := .list}}
<div class="row collection-item">
<a href="/details/{{$value.Id}}">
<div class="col s1">
<img src="{{$value.Logo}}" style="width: 50%; height: 50%"/>
</div>
<div class="col s10">
<span class="title">{{$value.Name}}</span><br>
<span class="small">{{$value.ShortDescription}} </span>
<span class="small">[{{$value.Type}}]</span>
</div>
</a>
<div class="col s1">
<a class="btn tooltipped gray" data-position="bottom" data-tooltip="Remove from Workspace" ><i class="material-icons">delete</i></a>
</div>
</div>
{{end}}
</div>
<script type="text/javascript" src="/static/js/materialize.min.js"></script>
</body>
</html>

315
views/schedule.tpl Normal file
View File

@@ -0,0 +1,315 @@
<!DOCTYPE html>
<html>
<head>
<title>o-search</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--Import Google Icon Font-->
<link type="text/css" rel="stylesheet" href="/static/css/material-icons.css">
<!--Import materialize.css-->
<link type="text/css" rel="stylesheet" href="/static/css/materialize.min.css" media="screen,projection" />
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
.small {
font-size: x-small;
}
#calendar {
position: fixed;
top: 15%;
left: 0;
right: 0;
bottom: 0;
}
.popper, .tooltip {
position: absolute;
z-index: 9999;
background: #FFC107;
color: black;
width: 250px;
border-radius: 3px;
box-shadow: 0 0 2px rgba(0,0,0,0.5);
padding: 10px;
text-align: center;
}
.style5 .tooltip {
background: #1E252B;
color: #FFFFFF;
max-width: 200px;
width: auto;
font-size: .8rem;
padding: .5em 1em;
}
.popper .popper__arrow,
.tooltip .tooltip-arrow {
width: 0;
height: 0;
border-style: solid;
position: absolute;
margin: 5px;
}
.tooltip .tooltip-arrow,
.popper .popper__arrow {
border-color: #FFC107;
}
.style5 .tooltip .tooltip-arrow {
border-color: #1E252B;
}
.popper[x-placement^="top"],
.tooltip[x-placement^="top"] {
margin-bottom: 5px;
}
.popper[x-placement^="top"] .popper__arrow,
.tooltip[x-placement^="top"] .tooltip-arrow {
border-width: 5px 5px 0 5px;
border-left-color: transparent;
border-right-color: transparent;
border-bottom-color: transparent;
bottom: -5px;
left: calc(50% - 5px);
margin-top: 0;
margin-bottom: 0;
}
.popper[x-placement^="bottom"],
.tooltip[x-placement^="bottom"] {
margin-top: 5px;
}
.tooltip[x-placement^="bottom"] .tooltip-arrow,
.popper[x-placement^="bottom"] .popper__arrow {
border-width: 0 5px 5px 5px;
border-left-color: transparent;
border-right-color: transparent;
border-top-color: transparent;
top: -5px;
left: calc(50% - 5px);
margin-top: 0;
margin-bottom: 0;
}
.tooltip[x-placement^="right"],
.popper[x-placement^="right"] {
margin-left: 5px;
}
.popper[x-placement^="right"] .popper__arrow,
.tooltip[x-placement^="right"] .tooltip-arrow {
border-width: 5px 5px 5px 0;
border-left-color: transparent;
border-top-color: transparent;
border-bottom-color: transparent;
left: -5px;
top: calc(50% - 5px);
margin-left: 0;
margin-right: 0;
}
.popper[x-placement^="left"],
.tooltip[x-placement^="left"] {
margin-right: 5px;
}
.popper[x-placement^="left"] .popper__arrow,
.tooltip[x-placement^="left"] .tooltip-arrow {
border-width: 5px 0 5px 5px;
border-top-color: transparent;
border-right-color: transparent;
border-bottom-color: transparent;
right: -5px;
top: calc(50% - 5px);
margin-left: 0;
margin-right: 0;
}
</style>
<script type="text/javascript" src="/static/js/jquery-3.5.1.min.js"></script>
<link href='/static/fullcalendar/main.css' rel='stylesheet' />
<script type="text/javascript" src="/static/js/popper.min.js"></script>
<script type="text/javascript" src="/static/js/tooltip.min.js"></script>
<script src='/static/fullcalendar/main.js'></script>
{{ template "swagger.tpl" . }}
<script type = "text/javascript">
window.onload = initCalendar
function initCalendar() {
var data = [];
var date = new Date().toISOString();
var d = new Date();
var dateMore = d.setDate(d.getDate() + 35);
dateMore = new Date(dateMore).toISOString()
oc_catalog_api.then(client => {
client.apis
.schedule
.ScheduleController_Get_schedules({
startDate: date,
stopDate: dateMore
})
.then(response => {
response.body
.forEach(elem => {
data.push(elem)
displayData = elem.Workflow.toString().split('.')
})
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
height: '85%',
selectable: true,
firstDay: 1,
eventDidMount: function(info) {
var tooltip = new Tooltip(info.el, {
title: info.event.extendedProps.description,
placement: 'top',
trigger: 'hover',
container: 'body'
});
},
views: {
dayGrid: {
titleFormat: {
month: 'long',
year: 'numeric'
}
},
timeGrid: {
titleFormat: {
day: '2-digit',
month: 'short',
year: 'numeric'
},
},
},
customButtons: {
nextEvent: {
text: 'Next Event',
click: function () {
oc_catalog_api.then(client => {
client.apis
.schedule
.ScheduleController_Get_next_schedule({
baseDate: date
})
.then(response => {
if (response.body == null) {
calendar.gotoDate(date)
alert("No next schedules")
} else {
calendar.gotoDate(response.body)
date = new Date(response.body)
date.setDate(date.getDate() + 1)
}
})
.catch((error) => {});
});
}
},
previousEvent: {
text: 'Previous Event',
click: function () {
oc_catalog_api.then(client => {
client.apis
.schedule
.ScheduleController_Get_previous_schedule({
baseDate: date
})
.then(response => {
if (response.body == null) {
calendar.gotoDate(date)
alert("No previous schedules")
} else {
calendar.gotoDate(response.body)
date = new Date(response.body)
date.setDate(date.getDate() - 1)
}
})
.catch((error) => {});
});
}
}
},
headerToolbar: {
left: ',previousEvent, ,prev, ,today, ,next, ,nextEvent,',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth'
},
initialView: 'dayGridMonth',
})
var eventTitle;
var eventStart;
var eventEnd;
data.forEach(elem => {
eventTitle = elem.Workflow.split(".")[2]
eventStart = elem.StartDate
eventEnd = elem.StopDate
var cpus = elem.ResourceQty.cpus;
var gpus = elem.ResourceQty.gpus;
var ram = elem.ResourceQty.ram;
calendar.addEvent({
title: eventTitle,
description:
'cpus: ' + cpus + ' | ' +
'gpus: ' + gpus + ' | ' +
'ram: ' + ram ,
start: eventStart,
end: eventEnd,
backgroundColor: stringToColour(eventTitle),
borderColor: stringToColour(eventTitle),
textColor: '',
});
});
calendar.render();
})
.catch((error) => {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth'
});
calendar.render();
});
})
}
// Determine color of eventTitle
var stringToColour = function (str) {
var hash = 0;
for (var i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}
var colour = '#';
for (var i = 0; i < 3; i++) {
var value = (hash >> (i * 8)) & 0xFF;
colour += ('00' + value.toString(16)).substr(-2);
}
return colour;
}
$(document).ready(function(){
$('.tooltipped').tooltip();
$('.fixed-action-btn').floatingActionButton({direction: 'bottom'});
})
</script>
</head>
<body>
{{ template "floating_menu.tpl" . }}
<div class="row">
<div class="col s4">
<a href="/"><img src="/static/img/O-cloud.svg" width="40%" height="auto"/></a>
</div>
</div>
<div>
<div id='calendar'></div>
</div>
<script type="text/javascript" src="/static/js/materialize.min.js"></script>
</body>
</html>

152
views/search.tpl Normal file
View File

@@ -0,0 +1,152 @@
<!DOCTYPE html>
<html>
<head>
<title>o-search</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--Import Google Icon Font-->
<link type="text/css" rel="stylesheet" href="/static/css/material-icons.css">
<!--Import materialize.css-->
<link type="text/css" rel="stylesheet" href="/static/css/materialize.min.css" media="screen,projection" />
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
.small {
font-size: x-small;
}
</style>
<script type="text/javascript" src="/static/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript">
$( document ).ready(function() {
$('.tooltipped').tooltip();
$('.fixed-action-btn').floatingActionButton({direction: 'bottom'});
;(function() {
jQuery.expr[':'].containsNC = function(elem, index, match) {
return (elem.textContent || elem.innerText || jQuery(elem).text() || '').toLowerCase().indexOf((match[3] || '').toLowerCase()) >= 0;
}
}(jQuery));
$('#filter').on('input',function(e)
{
if ($('#filter').val())
{
$('a')
.find('span').not(':containsNC('+$('#filter').val()+')')
.parent()
//.css('outline', '3px solid red');
.hide();
$('a')
.find('span:containsNC('+$('#filter').val()+')')
.parent()
//.css('outline', '3px solid red');
.show();
}
});
});
</script>
</head>
<body>
{{ template "floating_menu.tpl" . }}
<div class="row">
<div class="col s4">
<a href="/"><img src="/static/img/O-cloud.svg" width="40%" height="auto"/></a>
</div>
<div class="input-field col s8 offset-s0">
<i class="material-icons prefix">search</i>
<input id="search" type="text">
<label for="search">Search</label>
</div>
</div>
<div id="parentResults" class="collection">
{{range $key, $value := .list | searchResourceToList}}
<div class="row collection-item">
<a href="/details/{{$value | getRtype}}/{{$value | getID}}">
<div class="col s1">
<img src="data:image/png;base64,{{$value | getLogo}}" style="width: 50%; height: 50%"/>
</div>
<div class="col s10">
<span rtype="{{$value | getRtype}}" rid="{{$value | getID}}" class="title">{{$value | getName}}</span><br>
<span class="small">{{$value | getShortDescription}} </span>
<span class="small">[{{$value | getType}}]</span>
</div>
</a>
<div class="col s1">
<a id="addButton" onclick="submitWorkspace()" class="btn tooltipped gray waves-effect waves-light" data-position="bottom" data-tooltip="Add to Workspace" ><i class="material-icons">shopping_cart</i></a>
</div>
</div>
{{end}}
</div>
<script type="text/javascript" src="/static/js/materialize.min.js"></script>
</body>
{{ template "swagger.tpl" . }}
<script>
window.onload = setInitialStatus;
function setInitialStatus() {
oc_catalog_api.then(client => {
client.apis
.workspace
.WorkspaceController_Get_workspace()
.then(response => {
console.log(response);
Array.from(document.getElementById("parentResults").children).forEach((item) => {
elem = item.querySelector("*[rid]")
rid = elem.getAttribute("rid")
rtype = elem.getAttribute("rtype")
if ( response.body[rtype].includes(rid)) {
item.querySelector("*[id=addButton]").setAttribute("disabled", true);
} else {
item.querySelector("*[id=addButton]").removeAttribute("disabled");
}
});
})
.catch((error) => {
console.log("ERROR: " + error)
});
});
}
function submitWorkspace() {
var shopButton = event.target
var elem = shopButton.closest(".collection-item").querySelector("*[rid]")
var rid = elem.getAttribute("rid")
var rtype = elem.getAttribute("rtype")
//console.log(elem)
oc_catalog_api.then(client => {
client.apis
.workspace
.WorkspaceController_Add_model_to_workspace({id: rid, rtype: rtype})
.then(response => {
shopButton.parentNode.setAttribute("disabled", true);
shopButton.setAttribute("disabled", true);
})
.catch((error) => {
console.log("ERROR: " + error)
M.toast({html: 'already use!'});
});
});
}
</script>
</html>

46
views/swagger.tpl Normal file
View File

@@ -0,0 +1,46 @@
<script src="/static/js/swagger-client.browser.min.js"></script>
<script>
const swg_proto = "http://"
const swg_port = "49618"
const swg_suffix = "/swagger/swagger.json"
var specUrl = swg_proto + window.location.hostname + ":" + swg_port + swg_suffix
/**
switch (window.location.hostname) {
case 'localhost':
case '127.0.0.1':
var specUrl = 'http://localhost:49618/swagger/swagger.json';
break;
default:
var specUrl = 'https://' + window.location.hostname + ':8443/swagger.json';
break;
}
**/
var oc_catalog_api = new SwaggerClient(specUrl)
.then(client => {
return client;
})
.catch(err => {
alert("NO API AVAILABLE (" + specUrl + ") :" + err) // we will see what to do with it later
});
function WorkspaceAddElement(rid, rtype, callback) {
oc_catalog_api.then(client => {
client.apis
.workspace
.WorkspaceController_Add_model_to_workspace({id: rid, rtype: rtype})
.then(callback)
.catch((error) => {
console.log("ERROR: " + error)
});
});
}
</script>

154
views/templating.go Normal file
View File

@@ -0,0 +1,154 @@
package views
import (
OCCatalog_cli "oc-search/api-client/oc-catalog"
"github.com/beego/beego/v2/core/logs"
beego "github.com/beego/beego/v2/server/web"
)
func init() {
beego.AddFuncMap("getID", getID)
beego.AddFuncMap("getShortDescription", getShortDescription)
beego.AddFuncMap("getName", getName)
beego.AddFuncMap("getType", getType)
beego.AddFuncMap("getLogo", getLogo)
beego.AddFuncMap("getRtype", getRtype)
beego.AddFuncMap("searchResourceToList", searchResourceToList)
}
func getRtype(in interface{}) (out string) {
switch in.(type) {
case OCCatalog_cli.ModelsDataModel:
out = "data"
case OCCatalog_cli.ModelsComputingModel:
out = "computing"
case OCCatalog_cli.ModelsDatacenterModel:
out = "datacenter"
case OCCatalog_cli.ModelsStorageModel:
out = "storage"
}
return
}
func getID(in interface{}) (out string) {
switch in.(type) {
case OCCatalog_cli.ModelsDataModel:
out = in.(OCCatalog_cli.ModelsDataModel).ID
case OCCatalog_cli.ModelsComputingModel:
out = in.(OCCatalog_cli.ModelsComputingModel).ID
case OCCatalog_cli.ModelsDatacenterModel:
out = in.(OCCatalog_cli.ModelsDatacenterModel).ID
case OCCatalog_cli.ModelsStorageModel:
out = in.(OCCatalog_cli.ModelsStorageModel).ID
}
return
}
func getLogo(in interface{}) (out string) {
switch in.(type) {
case OCCatalog_cli.ModelsDataModel:
out = in.(OCCatalog_cli.ModelsDataModel).Logo
case OCCatalog_cli.ModelsComputingModel:
out = in.(OCCatalog_cli.ModelsComputingModel).Logo
case OCCatalog_cli.ModelsDatacenterModel:
out = in.(OCCatalog_cli.ModelsDatacenterModel).Logo
case OCCatalog_cli.ModelsStorageModel:
out = in.(OCCatalog_cli.ModelsStorageModel).Logo
default:
logs.Warn("Unable to parse Logo")
}
//TODO: Find a hybrid aproach for images as src and base64
return
}
func getName(in interface{}) (out string) {
switch in.(type) {
case OCCatalog_cli.ModelsDataModel:
out = in.(OCCatalog_cli.ModelsDataModel).Name
case OCCatalog_cli.ModelsComputingModel:
out = in.(OCCatalog_cli.ModelsComputingModel).Name
case OCCatalog_cli.ModelsDatacenterModel:
out = in.(OCCatalog_cli.ModelsDatacenterModel).Name
case OCCatalog_cli.ModelsStorageModel:
out = in.(OCCatalog_cli.ModelsStorageModel).Name
}
return
}
func getShortDescription(in interface{}) (out string) {
switch in.(type) {
case OCCatalog_cli.ModelsDataModel:
out = in.(OCCatalog_cli.ModelsDataModel).ShortDescription
case OCCatalog_cli.ModelsComputingModel:
out = in.(OCCatalog_cli.ModelsComputingModel).ShortDescription
case OCCatalog_cli.ModelsDatacenterModel:
out = in.(OCCatalog_cli.ModelsDatacenterModel).ShortDescription
case OCCatalog_cli.ModelsStorageModel:
out = in.(OCCatalog_cli.ModelsStorageModel).ShortDescription
}
return
}
func searchResourceToList(in interface{}) (out []interface{}) {
out = []interface{}{}
obj := in.(OCCatalog_cli.ModelsSearchResult)
// Data
if len(obj.Data) > 0 {
ArrInterface := make([]interface{}, len(obj.Data))
for i := range obj.Data {
ArrInterface[i] = obj.Data[i]
}
out = append(out, ArrInterface...)
}
// Computing
if len(obj.Computing) > 0 {
ArrInterface := make([]interface{}, len(obj.Computing))
for i := range obj.Computing {
ArrInterface[i] = obj.Computing[i]
}
out = append(out, ArrInterface...)
}
// Storage
if len(obj.Storage) > 0 {
ArrInterface := make([]interface{}, len(obj.Storage))
for i := range obj.Storage {
ArrInterface[i] = obj.Storage[i]
}
out = append(out, ArrInterface...)
}
// Datacenter
if len(obj.Datacenter) > 0 {
ArrInterface := make([]interface{}, len(obj.Datacenter))
for i := range obj.Datacenter {
ArrInterface[i] = obj.Datacenter[i]
}
out = append(out, ArrInterface...)
}
return
}
func getType(in interface{}) (out string) {
//FIXME: We should use types
switch in.(type) {
case OCCatalog_cli.ModelsDataModel:
out = "data"
case OCCatalog_cli.ModelsComputingModel:
out = "computing"
case OCCatalog_cli.ModelsDatacenterModel:
out = "datacenter"
case OCCatalog_cli.ModelsStorageModel:
out = "storage"
}
return
}

40
views/user.tpl Normal file
View File

@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html>
<head>
<title>Machines list</title>
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicon-16x16.png">
<link rel="manifest" href="/static/site.webmanifest">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--Import Google Icon Font-->
<link type="text/css" rel="stylesheet" href="/static/css/material-icons.css">
<!--Import materialize.css-->
<link type="text/css" rel="stylesheet" href="/static/css/materialize.min.css" media="screen,projection" />
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
.small {
font-size: x-small;
}
</style>
</head>
<body>
<div class="row">
<a href="/"><img src="/static/img/O-cloud.svg" width="10%" height="auto"/></a>
<br/>
{{.login}}
</div>
<script type="text/javascript" src="/static/js/materialize.min.js"></script>
</body>
</html>

290
views/workflow.tpl Normal file
View File

@@ -0,0 +1,290 @@
<!DOCTYPE html>
<html>
<head>
<title>workflow editor</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--Import Google Icon Font-->
<link type="text/css" rel="stylesheet" href="/static/css/material-icons.css">
<!--Import materialize.css-->
<link type="text/css" rel="stylesheet" href="/static/css/materialize.min.css" media="screen,projection" />
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="/static/mxgraph/examples/grapheditor/www/styles/grapheditor.css">
<script type="text/javascript" src="/static/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript">
// Parses URL parameters. Supported parameters are:
// - lang=xy: Specifies the language of the user interface.
// - touch=1: Enables a touch-style user interface.
// - storage=local: Enables HTML5 local storage.
// - chrome=0: Chromeless mode.
var urlParams = (function (url) {
var result = new Object();
var idx = url.lastIndexOf('?');
if (idx > 0) {
var params = url.substring(idx + 1).split('&');
for (var i = 0; i < params.length; i++) {
idx = params[i].indexOf('=');
if (idx > 0) {
result[params[i].substring(0, idx)] = params[i].substring(idx + 1);
}
}
}
return result;
})(window.location.href);
mxBasePath = '/static/mxgraph/src';
// Default resources are included in grapheditor resources
mxLoadResources = false;
</script>
<script type="text/javascript" src="/static/mxgraph/examples/grapheditor/www/js/Init.js"></script>
<script type="text/javascript" src="/static/mxgraph/examples/grapheditor/www/deflate/pako.min.js"></script>
<script type="text/javascript" src="/static/mxgraph/examples/grapheditor/www/deflate/base64.js"></script>
<script type="text/javascript" src="/static/mxgraph/examples/grapheditor/www/jscolor/jscolor.js"></script>
<script type="text/javascript" src="/static/mxgraph/examples/grapheditor/www/sanitizer/sanitizer.min.js"></script>
<script type="text/javascript" src="/static/mxgraph/src/js/mxClient.js"></script>
<script type="text/javascript" src="/static/mxgraph/examples/grapheditor/www/js/EditorUi.js"></script>
<script type="text/javascript" src="/static/mxgraph/examples/grapheditor/www/js/Editor.js"></script>
<script type="text/javascript" src="/static/mxgraph/examples/grapheditor/www/js/Sidebar.js"></script>
<script type="text/javascript" src="/static/mxgraph/examples/grapheditor/www/js/Graph.js"></script>
<script type="text/javascript" src="/static/mxgraph/examples/grapheditor/www/js/Format.js"></script>
<script type="text/javascript" src="/static/mxgraph/examples/grapheditor/www/js/Shapes.js"></script>
<script type="text/javascript" src="/static/mxgraph/examples/grapheditor/www/js/Actions.js"></script>
<script type="text/javascript" src="/static/mxgraph/examples/grapheditor/www/js/Menus.js"></script>
<script type="text/javascript" src="/static/mxgraph/examples/grapheditor/www/js/Toolbar.js"></script>
<script type="text/javascript" src="/static/mxgraph/examples/grapheditor/www/js/Dialogs.js"></script>
<script type="text/javascript" src="/static/mxgraph/examples/grapheditor/www/js/Swagger.js"></script>
{{ template "swagger.tpl" . }}
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
<script src="/static/js/bootstrap.bundle.min.js"></script>
<style>
.refresh {
margin-right: 10px;
margin-top: 10px;
}
.load {
margin-left: 10px;
margin-top: 10px;
}
</style>
</head>
<body class="geEditor">
{{ template "floating_menu.tpl" . }}
<div class="row">
<div class="center-align">
<a href="/"><img src="/static/img/O-cloud.svg" width="20%" height="auto" /></a>
</div>
<div class="geEditor">
<script type="text/javascript">
var MX_EDITORUI
var OC_WORKSPACE
var cursorX;
var cursorY;
document.onmousemove = function(e){
cursorX = e.pageX;
cursorY = e.pageY;
}
// Extends EditorUi to update I/O action states based on availability of backend
function LoadWorkloadWindow(ProjectName, XMLdata) {
OC_CATALOG_API = oc_catalog_api
OC_PROJECT_NAME = ProjectName
Editor.useLocalStorage = false;
var editorUiInit = EditorUi.prototype.init;
EditorUi.prototype.init = function () {
editorUiInit.apply(this, arguments);
this.actions.get('export').setEnabled(false);
// Updates action states which require a backend
if (!Editor.useLocalStorage) {
mxUtils.post(OPEN_URL, '', mxUtils.bind(this, function (req) {
var enabled = req.getStatus() != 404;
this.actions.get('open').setEnabled(enabled || Graph.fileSupport);
this.actions.get('import').setEnabled(enabled || Graph.fileSupport);
this.actions.get('save').setEnabled(enabled);
this.actions.get('saveAs').setEnabled(enabled);
this.actions.get('export').setEnabled(enabled);
}));
}
};
// Adds required resources (disables loading of fallback properties, this can only
// be used if we know that all keys are defined in the language specific file)
mxResources.loadDefaultBundle = false;
var bundle = mxResources.getDefaultBundle(RESOURCE_BASE, mxLanguage) ||
mxResources.getSpecialBundle(RESOURCE_BASE, mxLanguage);
// Fixes possible asynchronous requests
mxUtils.getAll([bundle, STYLE_PATH + '/default.xml'], function (xhr) {
// Adds bundle text to resources
mxResources.parse(xhr[0].getText());
// Configures the default graph theme
var themes = new Object();
themes[Graph.prototype.defaultThemeName] = xhr[1].getDocumentElement();
// Main
MX_EDITORUI = new EditorUi(new Editor(urlParams['chrome'] == '0', themes));
if (XMLdata != null) {
MX_EDITORUI.editor.setGraphXml(mxUtils.parseXml(XMLdata).documentElement);
}
}, function () {
document.body.innerHTML = '<center style="margin-top:10%;">Error loading resource files. Please check browser console.</center>';
});
};
$(document).ready(function () {
refreshProjects()
// LoadSavedData('test_project')
$('.tooltipped').tooltip();
$('.fixed-action-btn').floatingActionButton({ direction: 'bottom' });
});
</script>
</div>
<script type="text/javascript" src="/static/js/materialize.min.js"></script>
</div>
<div class="row">
<div>
<select class="form-select col m4 offset-m4" id="inlineFormSelectPref">
<!-- <option selected>Choose...</option> -->
</select>
</div>
<div class="btns center-align">
<span type="button" onclick="refreshProjects()" class="refresh btn btn-secondary">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-arrow-clockwise" viewBox="0 0 16 16">
<path fill-rule="evenodd"
d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z" />
<path
d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z" />
</svg>
</span>
<span id="loadButton" type="submit" onclick="LoadSelectedProject()" class="load btn btn-primary disabled">Load</span>
</div>
</div>
<div class="row">
<div>
<input class="col m4 offset-m4" id="new_workflow_name" type="text" placeholder="New Workflow Name">
</div>
<div class="center-align">
<button type="button" class="btn btn-success" onclick="CreateNewWorkflow()">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-plus" viewBox="0 0 16 16">
<path
d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z" />
</svg>
</button>
</div>
</div>
<script>
function LoadSavedData(PrjName) {
oc_catalog_api.then(client => {
client.apis
.workflow
.WorkflowController_Get_mxGraph_last_status({
workflowName: PrjName
})
.then(response => {
console.log(response)
LoadWorkloadWindow(PrjName, response.body)
})
.catch((error) => {
console.log("Workflow get XML error: " + error)
});
});
}
function CreateNewWorkflow() {
//debugger
var select = document.getElementById("new_workflow_name");
var NewProjectName = select.value;
if (!!NewProjectName) {
oc_catalog_api.then(client => {
client.apis
.workflow
.WorkflowController_Create_a_new_workflow({
workflowName: NewProjectName
})
.then(response => {
// console.log(response)
refreshProjects(NewProjectName)
select.value = "";
})
.catch((error) => {
console.log("Workflow create projects error: " + error)
});
});
}
}
function LoadSelectedProject() {
var select = document.getElementById("inlineFormSelectPref");
var projectName = select.value;
if (!!projectName) {
LoadSavedData(projectName)
}
}
function populateProjectOptions(arrayProjectNames, focusValue) {
var select = document.getElementById("inlineFormSelectPref");
select.innerHTML = '' // clear previous options
arrayProjectNames.forEach(elem => {
var option = document.createElement("option");
if (elem == focusValue) {
option.selected="selected"
}
option.value = elem
option.text = elem
select.appendChild(option)
})
if (arrayProjectNames !== null && arrayProjectNames.length > 0) {
document.getElementById("loadButton").classList.remove("disabled");
}
}
function refreshProjects(focusValue) {
oc_catalog_api.then(client => {
client.apis
.workflow
.WorkflowController_List_workflows()
.then(response => {
// console.log(response)
populateProjectOptions(response.body, focusValue)
})
.catch((error) => {
console.log("Workflow list projects error: " + error)
});
});
}
</script>
</body>
</html>

114
views/workspace.tpl Normal file
View File

@@ -0,0 +1,114 @@
<!DOCTYPE html>
<html>
<head>
<title>o-search</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--Import Google Icon Font-->
<link type="text/css" rel="stylesheet" href="/static/css/material-icons.css">
<!--Import materialize.css-->
<link type="text/css" rel="stylesheet" href="/static/css/materialize.min.css" media="screen,projection" />
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
.small {
font-size: x-small;
}
</style>
<script type="text/javascript" src="/static/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript">
$( document ).ready(function() {
$('.tooltipped').tooltip();
$('.fixed-action-btn').floatingActionButton({direction: 'bottom'});
;(function() {
jQuery.expr[':'].containsNC = function(elem, index, match) {
return (elem.textContent || elem.innerText || jQuery(elem).text() || '').toLowerCase().indexOf((match[3] || '').toLowerCase()) >= 0;
}
}(jQuery));
$('#filter').on('input',function(e)
{
if ($('#filter').val())
{
$('a')
.find('span').not(':containsNC('+$('#filter').val()+')')
.parent()
//.css('outline', '3px solid red');
.hide();
$('a')
.find('span:containsNC('+$('#filter').val()+')')
.parent()
//.css('outline', '3px solid red');
.show();
}
});
});
</script>
</head>
<body>
{{ template "floating_menu.tpl" . }}
<div class="row">
<div class="col s4">
<a href="/"><img src="/static/img/O-cloud.svg" width="40%" height="auto"/></a>
</div>
</div>
<div class="col s12">
<h4>Workspace</h4>
</div>
<div class="collection">
{{range $key, $value := .list}}
<div class="row collection-item">
<a href="/details/{{$value | getRtype}}/{{$value | getID}}">
<div class="col s1">
<img src="data:image/png;base64,{{$value | getLogo}}" style="width: 50%; height: 50%"/>
</div>
<div class="col s10">
<span rtype="{{$value | getRtype}}" rid="{{$value | getID}}" class="title">{{$value | getName}}</span><br>
<span class="small">{{$value | getShortDescription}} </span>
<span class="small">[{{$value | getType}}]</span>
</div>
</a>
<div class="col s1">
<a id="removeButton" onclick="removeWorkspace()" class="btn tooltipped red" data-position="bottom" data-tooltip="Remove from Workspace" ><i class="material-icons">delete</i></a>
</div>
</div>
{{end}}
</div>
<script type="text/javascript" src="/static/js/materialize.min.js"></script>
</body>
{{ template "swagger.tpl" . }}
<script>
function removeWorkspace() {
var item = event.srcElement.closest(".collection-item")
var elem = item.querySelector("*[rid]")
var rid = elem.getAttribute("rid")
var rtype = elem.getAttribute("rtype")
//console.log(elem)
oc_catalog_api.then(client => {
client.apis
.workspace
.WorkspaceController_Delete_element_from_user_workspace({id: rid, rtype: rtype})
.then(response => {
item.remove()
})
.catch((error) => {
console.log("ERROR: " + error)
});
});
}
</script>
</html>