lxconsole/lxconsole/templates/images.html

395 lines
15 KiB
HTML

{% extends "main.html" %}
{% block header %}
<div class="row mb-2">
<div class="col-sm-6">
<h1>{{ page_title | safe }}</h1>
</div>
<div class="col-sm-6">
<button class="btn btn-outline-primary float-sm-right mr-4" data-bs-toggle="modal" data-bs-target="#addModal" title="Add Image" aria-hidden="true">
<i class="fas fa-plus fa-sm fa-fw"></i> Image
</button>
</div>
</div>
{% endblock header %}
{% block content %}
<div class="col-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">Images</h3>
<div class="card-tools">
<button type="button" class="btn btn-tool" onclick="reloadPageContent()" title="Refresh">
<i class="fas fa-sync"></i>
</button>
</div>
</div>
<div class="card-body">
<table class="table table-hover" id="myDataTable" width="100%" cellspacing="0">
</table>
</div>
</div>
</div>
{% endblock content %}
{% block modal %}
{% include 'modals/images.html' %}
{% endblock modal %}
{% block script %}
<script>
var reloadTime = 10000;
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const serverId = urlParams.get('id');
const project = urlParams.get('project');
var editedImage = ''
applySidebarStyles();
applySidebarLinks();
populateSidebarLinks();
populateNavbarLinks();
function reloadPageContent() {
//Clear the automatic page reload
clearTimeout(pageReloadTimeout);
//Reload the datatables content
$('#myDataTable').DataTable().ajax.reload(null, false);
//Set the automatic page reload
pageReloadTimeout = setTimeout(() => { reloadPageContent(); }, reloadTime);
}
function loadPageContent(){
//Display the current project
$("#selectedProject").text(project);
//Populate the Server dropdown
$.getJSON("../api/servers/list_servers?id="+serverId, function (data) {
data = data.data
for (var index = 0; index < data.length; index++) {
if (data[index].name == '')
optionText = data[index].addr
else
optionText = data[index].name
if (data[index].id == serverId)
$('#serverListNav').append('<option value="' + data[index].id + '" selected="selected">' + optionText + '</option>');
else
$('#serverListNav').append('<option value="' + data[index].id + '">' + optionText + '</option>');
}
})
//Populate the Project dropdown
$.getJSON("../api/projects/list_projects?id="+serverId+"&project="+project, function (data) {
data = data.metadata
for (var index = 0; index < data.length; index++) {
optionText = data[index].replace('/1.0/projects/','');
if (optionText == project)
$('#projectListNav').append('<option value="' + optionText + '" selected="selected">' + optionText + '</option>');
else
$('#projectListNav').append('<option value="' + optionText + '">' + optionText + '</option>');
}
})
// Configure Datatable
$('#myDataTable').DataTable({
ajax: {
url: "../api/images/list_images?id="+serverId + "&project=" + project + "&recursion=1",
dataType: "json",
dataSrc: "metadata",
contentType: "application/json",
error: function (xhr, error, code) {
console.log(xhr, code);
}
},
columns: [
{ title: "Alias", data: function (row, type, set) {
if (row.hasOwnProperty('update_source')) {
if (row.update_source.hasOwnProperty('alias')) {
return row.update_source['alias']
}
}
return '-'
},
},
{ title: "Description", data: function (row, type, set) {
if (row.hasOwnProperty('properties')) {
if (row.properties.hasOwnProperty('description')) {
return row.properties['description']
}
}
return '-'
},
},
{ title: "Update Server", data: function (row, type, set) {
if (row.hasOwnProperty('update_source')) {
if (row.update_source.hasOwnProperty('server')) {
return row.update_source['server']
}
}
return '-'
},
},
{ title: "Fingerprint", data: function (row, type, set) {
if (row.hasOwnProperty('fingerprint')) {
if (row.fingerprint)
return row.fingerprint.substring(0,11) + "...";
}
return '-'
},
},
{ title: "Type", data: function (row, type, set) {
if (row.hasOwnProperty('type')) {
if (row.type)
return row.type
}
return '-'
},
},
{ title: "Size", data: function (row, type, set) {
if (row.hasOwnProperty('size')) {
if (row.size) {
if (type === 'display'){
size = row.size / 1024 / 1024
return size.toFixed(2) + ' MiB'
}
return row.size
}
}
return '-'
},
},
{ title: "Actions", data: function (row, type, set) {
links = ''
if (row.hasOwnProperty('fingerprint')) {
links = '<a href="#" onclick=editImage(\''+row.fingerprint+'\')><i class="fas fa-edit fa-lg" style="color:#ddd" title="Edit" aria-hidden="true"></i></a>' +
'&nbsp' + '&nbsp' +
'<a href="#" onclick=refreshImage(\''+row.fingerprint+'\')><i class="fas fa-sync-alt fa-lg" style="color:#ddd" title="Refresh" aria-hidden="true"></i></a>' +
'&nbsp' + '&nbsp' +
'<a href="#" onclick=deleteImage(\''+row.fingerprint+'\')><i class="fas fa-trash-alt fa-lg" style="color:#ddd" title="Delete" aria-hidden="true"></i></a>'
}
return links
},
},
],
order: [],
});
//Populate the Simplestreams dropdown in addModal
$.getJSON("../api/simplestreams/list_simplestreams?id="+serverId, function (data) {
data = data.data
for (var index = 0; index < data.length; index++) {
if (data[index].alias == '')
optionText = data[index].addr
else
optionText = data[index].alias
$('#selectRepoInput').append('<option value="' + data[index].id + '">' + optionText + '</option>');
}
})
//Populate the image catalog choices
updateCatalog()
//Set reload page content
pageReloadTimeout = setTimeout(() => { reloadPageContent(); }, reloadTime);
}
function deleteImage(fingerprint){
console.log("Info: confirming deletion of image " + fingerprint);
if (confirm("Are you sure you want to delete image " + fingerprint.substring(0,11) + "...?") == true) {
console.log("Info: deleting image " + fingerprint);
$.post("../api/images/delete_image?id=" + serverId + "&project=" + project, { fingerprint: fingerprint }, function (data) {
console.log(data);
if (data.error_code >= 400){
alert(data.error);
}
//Sync type
setTimeout(() => { reloadPageContent(); }, 1000);
operationStatusCheck()
});
}
}
function refreshImage(fingerprint){
console.log("Info: refreshing image " + fingerprint);
$.post("../api/images/refresh_image?id="+serverId+"&project="+project, { fingerprint: fingerprint }, function (data) {
console.log(data);
if (data.error_code >= 400){
alert(data.error);
}
//Async type
setTimeout(() => { reloadPageContent(); }, 2000);
operationStatusCheck()
});
}
function editImage(fingerprint){
editedImage = fingerprint
console.log("Info: loading image " + fingerprint);
$.post("../api/images/load_image?id=" + serverId + "&project=" + project, { fingerprint: fingerprint }, function (data) {
console.log(data);
if (data.error_code >= 400){
alert(data.error);
}
$("#imageNameEditInput").text("Fingerprint: " + fingerprint);
$("#jsonInput").val(JSON.stringify(data.metadata, null, 2));
$("#editModal").modal('show');
});
}
function updateImage(){
fingerprint = editedImage
var updatedJSON = $("#jsonInput").val();
console.log("Info: updating image");
$.post("../api/images/update_image?id=" + serverId + "&project=" + project + "&fingerprint=" + encodeURI(fingerprint), { json: updatedJSON }, function (data) {
console.log(data);
if (data.error_code >= 400){
alert(data.error);
}
//Sync type
setTimeout(() => { reloadPageContent(); }, 1000);
operationStatusCheck()
});
}
function addItem(){
console.log("Info: downloading image");
data = $('#addForm').serialize();
$.post("../api/images/add_image?id="+serverId+"&project="+project, data, function (data) {
console.log(data);
if (data.error_code >= 400){
alert(data.error);
}
//Async type
setTimeout(() => { reloadPageContent(); }, 2000);
operationStatusCheck()
});
}
function addCatalogImage(){
image = $("#operatingSystem").val();
repo = 'https://images.linuxcontainers.org'
imageVersion = $("#operatingSystemVersion").val();
imageVariant = $("#operatingSystemVariant").val();
imageType = $("#operatingSystemType").val();
console.log("Info: downloading image " + image + " from " + repo);
$.post("../api/images/add_image?id="+serverId+"&project="+project, { image: image, repo: repo, image_version: imageVersion, image_variant: imageVariant, image_type: imageType }, function (data) {
console.log(data);
if (data.error_code >= 400){
alert(data.error);
}
//Async type
setTimeout(() => { reloadPageContent(); }, 2000);
operationStatusCheck()
});
}
function updateCatalog(){
catalog_images = {}
// Check if session variable catalog_images is not yet set
if (sessionStorage.getItem("catalog_images") === null) {
console.log("Info: updating catalog images");
$.get("../api/images/list_simplestream_images", function (data) {
//Clear operating system select options in modal
$("#operatingSystem").empty();
//Loop through each operating system item
for (i = 0; i < data.length; i++) {
// Split the string by semicolon. Ex: "almalinux:8:amd64:cloud"
image = data[i].split(':')
//Check that operating system is not already in catalog_images object
if (!(image[0] in catalog_images)){
catalog_images[image[0]] = { "versions": [ image[1] ], "variants": [image[3]] }
$('#operatingSystem').append('<option value="' + image[0] + '">' + image[0] + '</option>');
}
//Populate OS versions
if (!(catalog_images[image[0]]['versions'].includes(image[1]))){
catalog_images[image[0]]['versions'].push(image[1])
}
//Populate OS variants
if (!(catalog_images[image[0]]['variants'].includes(image[3]))){
catalog_images[image[0]]['variants'].push(image[3])
}
}
//Check if we populated any operating systems and store them in session storage
if (Object.keys(catalog_images).length > 0) {
sessionStorage.setItem('catalog_images', JSON.stringify(catalog_images))
}
//Update the OS version options based on selected OS
updateOSVersion()
});
}
else {
//Set catalog_images from session storage
catalog_images = JSON.parse(sessionStorage.getItem('catalog_images'))
//Double check to make sure there are actually operating systems as keys
if (Object.keys(catalog_images).length > 0) {
//Clear operating system select options in modal
$("#operatingSystem").empty();
//Loop through each operating system to populate operating system select options
for (var catalog_image in catalog_images){
$('#operatingSystem').append('<option value="' + catalog_image + '">' + catalog_image + '</option>');
}
//Update the OS version options based on selected OS
updateOSVersion()
}
}
}
function updateOSVersion(){
catalog_images = {}
if (sessionStorage.getItem("catalog_images") != null) {
catalog_images = JSON.parse(sessionStorage.getItem('catalog_images'))
if (Object.keys(catalog_images).length > 0) {
$("#operatingSystemVersion").empty();
os = $("#operatingSystem option:selected").text();
for (let i = 0; i < catalog_images[os]['versions'].length; i++) {
$('#operatingSystemVersion').append('<option value="' + catalog_images[os]['versions'][i] + '">' + catalog_images[os]['versions'][i] + '</option>');
}
}
}
//Update the OS Variant
updateOSVariant()
}
function updateOSVariant(){
catalog_images = {}
if (sessionStorage.getItem("catalog_images") != null) {
catalog_images = JSON.parse(sessionStorage.getItem('catalog_images'))
if (Object.keys(catalog_images).length > 0) {
$("#operatingSystemVariant").empty();
os = $("#operatingSystem option:selected").text();
for (let i = 0; i < catalog_images[os]['variants'].length; i++) {
if (catalog_images[os]['variants'][i] == 'default') {
$('#operatingSystemVariant').append('<option value="' + catalog_images[os]['variants'][i] + '" selected>' + catalog_images[os]['variants'][i] + '</option>');
}
else {
$('#operatingSystemVariant').append('<option value="' + catalog_images[os]['variants'][i] + '">' + catalog_images[os]['variants'][i] + '</option>');
}
}
}
}
}
$(document).ready(function(){
//If id or project variables are missing redirect to servers page
if (!serverId || !project) {
window.location.href = 'servers';
}
else {
loadPageContent()
operationStatusCheck()
}
});
</script>
{% endblock script %}