lxd-dashboard/admin/images.html
matthewalanpenning d477f951ba v1.1.1
2020-10-19 12:31:17 -04:00

481 lines
No EOL
18 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" type="image/png" href="theme/images/logo_dark.png">
<title>lxdware - dashboard</title>
<!-- Custom fonts for this template-->
<link href="theme/vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
<!-- Custom styles for this template-->
<link href="theme/css/sb-admin-2.css" rel="stylesheet">
<!-- Custom styles for this page -->
<link href="theme/vendor/datatables/dataTables.bootstrap4.min.css" rel="stylesheet">
</head>
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
<ul class="navbar-nav bg-gradient-dark sidebar sidebar-dark accordion" id="accordionSidebar">
<div id="sidebarLinks"></div>
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
<!-- Sidebar Toggler (Sidebar) -->
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
</ul>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Topbar -->
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
<!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars"></i>
</button>
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<li class="nav-item dropdown no-arrow" id="remoteListNav">
</li>
<li class="nav-item dropdown no-arrow" id="projectListNav">
</li>
<li>
<div class="nav-item spinner-grow text-primary m-3" role="status" style="display:none;" id="spinner">
<span class="nav-item sr-only">Loading...</span>
</div>
</li>
<li class="nav-item dropdown no-arrow" id="notificationArea" style="display: none;">
<div class="nav-link dropdown-toggle">
<span id="notification" class="mr-2 d-none d-lg-inline text-gray-600 small">Notification</span>
</div>
</li>
<div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User Information -->
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Admin</span>
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="userDropdown">
<a class="dropdown-item" href="index.html">
<i class="fas fa-server fa-sm fa-fw mr-2 text-gray-400"></i>
Hosts
</a>
<a class="dropdown-item" href="#" onclick="logout()">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Logout
</a>
</div>
</li>
</ul>
</nav>
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div class="container-fluid">
<!-- BreadCrumb -->
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="#" id="remoteBreadCrumb"></a></li>
<li class="breadcrumb-item active" aria-current="page" id="imagesBreadCrumb"></li>
</ol>
</nav>
<div class="row">
<div class="col-12">
<!-- Image List -->
<div class="card shadow mb-4">
<!-- Card Header - Dropdown -->
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">Images</h6>
<div class="dropdown no-arrow">
<a class="dropdown-toggle" href="#" data-toggle="modal" data-target="#downloadImageModal">
<i class="fas fa-plus fa-sm fa-fw"></i>
Download Image
</a>
</div>
</div>
<!-- Card Body -->
<div class="card-body">
<div class="table-responsive">
<table class="table" id="imageListTable" width="100%" cellspacing="0">
</table>
</div>
</div>
</div>
<!-- End Image List -->
</div>
</div>
</div>
<!-- /.container-fluid -->
</div>
<!-- End of Main Content -->
<!-- Footer -->
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright &copy; lxdware.com 2020</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Download Image Modal-->
<div class="modal fade" id="downloadImageModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Download Image</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<label class="col-3 col-form-label text-right">Image/Alias: </label>
<div class="col-8">
<div class="form-group">
<input type="text" class="form-control" id="imageNameInput" required="required" placeholder="" name="image">
</div>
</div>
<label class="col-3 col-form-label text-right">Repository:</label>
<div class="col-8 text-right">
<div class="form-group">
<select id="selectRepoInput" class="form-control" name="repo">
</select>
</div>
</div>
<label class="col-3 col-form-label text-right">Image Type:</label>
<div class="col-8 text-right">
<div class="form-group">
<select id="selectTypeInput" class="form-control" name="image_type">
<option value="container" selected>container</option>
<option value="virtual-machine">virtual-machine</option>
</select>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="#" onclick="downloadImage()" data-dismiss="modal">Ok</a>
</div>
</div>
</div>
</div>
<!-- Edit Image Modal-->
<div class="modal fade" id="editImageModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Edit Image</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<label class="col-4 col-form-label" id="imageNameEditInput"></label>
<div class="col-12">
<div class="form-group text-right">
<pre>
<textarea name="json" class="form-control" id="jsonEditInput" rows="16" ></textarea>
</pre>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="#" onclick="updateImage()" data-dismiss="modal">Submit</a>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="theme/vendor/jquery/jquery.min.js"></script>
<script src="theme/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="theme/vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="theme/js/sb-admin-2.min.js"></script>
<!-- Page level plugins -->
<script src="theme/vendor/datatables/jquery.dataTables.min.js"></script>
<script src="theme/vendor/datatables/dataTables.bootstrap4.min.js"></script>
</body>
<script>
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const remoteName = urlParams.get('remote');
const projectName = urlParams.get('project');
var selectList = "";
var operationNumbers = [];
var imageToUpdate = "";
function logout(){
var http = new XMLHttpRequest();
http.open("get", "../admin", false, "null", "null");
http.send("");
window.location.replace("../index.html");
}
function operationStatusCheck(){
operationNumbers = operationNumbers.filter(function(e){return e});
var numberOfOperations = operationNumbers.length;
if (numberOfOperations > 0){
$('#spinner').show();
for (i = 0; i < numberOfOperations; i++){
var elementNumber = i;
$.get("./php/lxd/operation-status.php?remote=" + encodeURI(remoteName) + "&id=" + encodeURI(operationNumbers[elementNumber]) , function (data) {
var operationData = JSON.parse(data);
console.log(operationData);
if (operationData.error_code == 404) {
operationNumbers[elementNumber] = undefined;
reloadPageContent();
}
if (operationData.status_code == 200) {
if (operationData.metadata.status_code == 103){
$('#notificationArea').show();
$('#notification').text(operationData.metadata.description);
}
if (operationData.metadata.status_code == 200){
operationNumbers[elementNumber] = undefined;
reloadPageContent();
}
if (operationData.metadata.status_code >= 400){
operationNumbers[elementNumber] = undefined;
alert(operationData.metadata.err);
reloadPageContent();
}
}
});
}
setTimeout(() => { operationStatusCheck(); }, 4000);
}
else {
$('#spinner').hide();
$('#notificationArea').hide();
$('#notification').text("");
}
}
function loadPageContent(){
//Check Authorization
$.get("./php/auth/auth-check.php", function (data) {
if(data != "true"){
window.location.replace("../index.html");
}
});
$('#imageListTable').DataTable( {
ajax: "./php/lxd/image-list.php?remote=" + encodeURI(remoteName) + "&project=" + encodeURI(projectName),
columns: [
{},
{ title: "Description" },
{ title: "Fingerprint" },
{ title: "Type" },
{ title: "Size" },
{ title: "Action" }
],
order: [],
columnDefs: [
{ targets: 0, orderable: false, width: "25px" }
]
});
//Load the select List for Download Image Modal
$.get("./php/lxd/simplestreams-list-select.php?remote=" + encodeURI(remoteName) + "&project=" + encodeURI(projectName), function (data) {
if (selectList != data){
$("#selectRepoInput").html(data);
selectList = data;
}
});
}
function reloadPageContent() {
$('#imageListTable').DataTable().ajax.reload();
//Load the select List for Download Image Modal
$.get("./php/lxd/simplestreams-list-select.php?remote=" + encodeURI(remoteName) + "&project=" + encodeURI(projectName), function (data) {
if (selectList != data){
$("#selectRepoInput").html(data);
selectList = data;
}
});
}
//API uses async
function refreshImage(imageFingerprint){
console.log("Info: refreshing image " + imageFingerprint);
$.get("./php/lxd/images.php?remote=" + encodeURI(remoteName) + "&project=" + encodeURI(projectName) + "&fingerprint=" + encodeURI(imageFingerprint) + "&action=refreshImage", function (data) {
var operationData = JSON.parse(data);
console.log(operationData);
if (operationData.status_code == 100 && operationData.metadata.status_code < 400){
operationNumbers.push(operationData.metadata.id);
operationStatusCheck();
}
if (operationData.metadata.status_code >= 400){
alert(operationData.metadata.err);
}
setTimeout(() => { operationStatusCheck(); }, 4000);
});
}
//API uses async
function deleteImage(imageFingerprint){
console.log("Info: deleting image " + imageFingerprint);
$.get("./php/lxd/images.php?remote=" + encodeURI(remoteName) + "&project=" + encodeURI(projectName) + "&fingerprint=" + encodeURI(imageFingerprint) + "&action=deleteImage", function (data) {
var operationData = JSON.parse(data);
console.log(operationData);
if (operationData.status_code == 100 && operationData.metadata.status_code < 400){
operationNumbers.push(operationData.metadata.id);
operationStatusCheck();
}
if (operationData.metadata.status_code >= 400){
alert(operationData.metadata.err);
}
setTimeout(() => { operationStatusCheck(); }, 4000);
});
}
//API uses async
function downloadImage(){
var imageName = $("#imageNameInput").val();
var repoName = $("#selectRepoInput").val();
var imageType = $("#selectTypeInput").val();
console.log("Info: downloading image " + imageName + " from " + repoName);
$.get("./php/lxd/images.php?remote=" + encodeURI(remoteName) + "&project=" + encodeURI(projectName) + "&image=" + encodeURI(imageName) + "&repo=" + encodeURI(repoName) + "&image_type=" + encodeURI(imageType) + "&action=downloadImage", function (data) {
var operationData = JSON.parse(data);
console.log(operationData);
if (operationData.status_code == 100 && operationData.metadata.status_code < 400){
operationNumbers.push(operationData.metadata.id);
operationStatusCheck();
}
if (operationData.metadata.status_code >= 400){
alert(operationData.metadata.err);
}
setTimeout(() => { operationStatusCheck(); }, 4000);
});
}
//Called by Edit action, loads JSON data of project
function loadImageJson(imageToLoad){
console.log("Info: loading iname " + imageToLoad);
imageToUpdate = imageToLoad;
$.get("./php/lxd/images.php?remote=" + encodeURI(remoteName) + "&project=" + encodeURI(projectName) + "&fingerprint=" + encodeURI(imageToLoad) + "&action=loadImage", function (data) {
var operationData = JSON.parse(data);
console.log(operationData);
if (operationData.error_code >= 400){
alert(operationData.error);
}
$("#imageNameEditInput").text("Name: " + imageToLoad);
$("#jsonEditInput").val(JSON.stringify(operationData.metadata, null, 2));
$("#editImageModal").modal('show');
});
}
function updateImage(){
var imageUpdateJSON = $("#jsonEditInput").val();
console.log("Info: updating image " + imageToUpdate);
$.post("./php/lxd/images.php?remote=" + encodeURI(remoteName) + "&project=" + encodeURI(projectName) + "&fingerprint=" + encodeURI(imageToUpdate) + "&action=updateImage", {json: imageUpdateJSON}, function (data) {
var operationData = JSON.parse(data);
console.log(operationData);
if (operationData.error_code >= 400){
alert(operationData.error);
}
setTimeout(() => { operationStatusCheck(); }, 4000);
});
}
$(document).ready(function(){
//Load in the sidebar
$("#sidebarLinks").load("./sidebar.html");
//Setup Page Breadcrumb Links/Information
$('#remoteBreadCrumb').load("./php/lxd/remote-breadcrumb.php?remote=" + encodeURI(remoteName));
$('#remoteBreadCrumb').attr("href", "host.html?remote=" + encodeURI(remoteName) + "&project=" + encodeURI(projectName));
$('#imagesBreadCrumb').text("images");
//Load the card contents
loadPageContent();
//Set page reload every 15 seconds
setInterval(function(){reloadPageContent()}, 15000);
$("#remoteListNav").load("./php/lxd/remote-list-nav.php?remote=" + encodeURI(remoteName) + "&project=" + encodeURI(projectName));
$("#projectListNav").load("./php/lxd/project-list-nav.php?remote=" + encodeURI(remoteName) + "&project=" + encodeURI(projectName));
});
</script>
</html>