mirror of
https://github.com/komodorio/helm-dashboard.git
synced 2026-03-24 11:48:04 +00:00
Chart details draft (#4)
* Add logo * Refactor out structs * Data layer context-awareness * Mod * Data layer improvements * Progress * Progress * Progress * Figured the time format shorter * Statuses colors * Sticky URL * Calculate some diffs inside * Separate checks * Scrap gofmt * Skip custom test in GH * Shows some colorful diff
This commit is contained in:
@@ -1,58 +1,125 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<link rel="icon" href="https://komodor.com/wp-content/uploads/2021/05/favicon-50x50.png"/>
|
||||
<link rel="icon" href="static/logo.png"/>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Helm Dashboard</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"/>
|
||||
<!-- CSS -->
|
||||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css" />
|
||||
<link href="static/styles.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
<nav class="navbar navbar-expand-lg bg-light rounded" aria-label="Eleventh navbar example">
|
||||
<i class="fa-solid fa-arrow-trend-down"></i>
|
||||
<nav class="navbar navbar-expand-lg bg-light rounded" style="margin-bottom: 0.75rem">
|
||||
<div class="container-fluid">
|
||||
<div style="line-height: 90%">
|
||||
<div style="line-height: 90%; font-size: 1.5rem" class="navbar-brand">
|
||||
<img src="static/logo.png" style="height: 3rem; float: left" alt="Logo">
|
||||
<a class="navbar-brand" href="#"><b>Helm Dashboard</b></a><br/>
|
||||
<span style="font-size: smaller">by <a href="https://komodor.io">komodor.io</a></span>
|
||||
<span style="font-size: 0.8rem;">by <a href="https://komodor.io">komodor.io</a></span>
|
||||
</div>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample09"
|
||||
aria-controls="navbarsExample09" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mainNav"
|
||||
aria-controls="mainNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarsExample09">
|
||||
<div class="collapse navbar-collapse" id="mainNav">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" aria-current="page" href="/">Charts List</a>
|
||||
<a class="nav-link active" aria-current="page" href="/">Installed Charts</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link disabled">Provisional Charts</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link disabled">Repositories</a>
|
||||
</li>
|
||||
</ul>
|
||||
<form class="d-flex flex-nowrap text-nowrap">
|
||||
<label for="cluster" class="">K8s Context:</label>
|
||||
<label for="cluster" style="margin-top: 0.5rem">K8s Context:</label>
|
||||
<select id="cluster" class="form-control"></select>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="bg-light p-5 pt-0 rounded" id="sectionDetails" style="display: none">
|
||||
<span class="text-muted" style="transform: rotate(270deg); z-index: 100; display: inline-block; position: relative; left:-4rem; top: 4rem; color: #BBB!important; text-transform: uppercase">Revisions</span>
|
||||
<div class="row mb-3">
|
||||
|
||||
<div class="bg-light p-5 rounded">
|
||||
</div>
|
||||
<h1><a href="/" class="text-reset" style="text-decoration: none">⇐</a> Chart Details: <span class="name">chosen-one</span>,
|
||||
revision <span class="rev"></span></h1>
|
||||
|
||||
<nav>
|
||||
<div class="nav nav-tabs" id="nav-tab" role="tablist">
|
||||
<button class="nav-link active" id="nav-manifest-diff-tab" data-bs-toggle="tab" data-bs-target="#nav-manifest-diff"
|
||||
type="button" role="tab" aria-controls="nav-manifest-diff" aria-selected="true">Manifests
|
||||
</button>
|
||||
<button class="nav-link" id="nav-disabled-tab" data-bs-toggle="tab" data-bs-target="#nav-disabled"
|
||||
type="button" role="tab" aria-controls="nav-disabled" aria-selected="false" disabled>Resources
|
||||
</button>
|
||||
<button class="nav-link" id="nav-disabled-tab" data-bs-toggle="tab" data-bs-target="#nav-disabled"
|
||||
type="button" role="tab" aria-controls="nav-disabled" aria-selected="false" disabled>Parameterized Values
|
||||
</button>
|
||||
<button class="nav-link" id="nav-disabled-tab" data-bs-toggle="tab" data-bs-target="#nav-disabled"
|
||||
type="button" role="tab" aria-controls="nav-disabled" aria-selected="false" disabled>Notes
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="tab-content" id="nav-tabContent">
|
||||
<div class="tab-pane fade show active" id="nav-manifest-diff" role="tabpanel" aria-labelledby="nav-manifest-diff-tab"
|
||||
tabindex="0">
|
||||
<nav class="navbar bg-light">
|
||||
<form class="container-fluid">
|
||||
<label class="form-check-label" for="diffModeNone">
|
||||
<input class="form-check-input" type="radio" name="diffMode" id="diffModeNone" disabled>
|
||||
View Manifests
|
||||
</label>
|
||||
<label class="form-check-label" for="diffModePrev">
|
||||
<input class="form-check-input" type="radio" name="diffMode" id="diffModePrev">
|
||||
Diff with previous
|
||||
</label>
|
||||
<label class="form-check-label" for="diffModeLatest">
|
||||
<input class="form-check-input" type="radio" name="diffMode" id="diffModeLatest" disabled>
|
||||
Diff with latest <span class="text-muted">(#5)</span>
|
||||
</label>
|
||||
<label class="form-check-label" for="diffModeRev">
|
||||
<input class="form-check-input" type="radio" name="diffMode" id="diffModeRev" disabled>
|
||||
Diff with specific revision: <input class="form-input" size="3" disabled>
|
||||
</label>
|
||||
</form>
|
||||
</nav>
|
||||
|
||||
<div id="manifestText" class="mt-2"></div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="nav-disabled" role="tabpanel" aria-labelledby="nav-disabled-tab"
|
||||
tabindex="0">...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-light p-5 rounded" id="sectionList" style="display: none">
|
||||
<h1>Charts List</h1>
|
||||
<div id="charts" class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/diff2html/bundles/js/diff2html-ui.min.js"></script>
|
||||
<script src="static/scripts.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
BIN
pkg/dashboard/static/logo.png
Normal file
BIN
pkg/dashboard/static/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
@@ -5,6 +5,126 @@ function reportError(err) {
|
||||
alert(err) // TODO: nice modal/baloon/etc
|
||||
}
|
||||
|
||||
function revisionClicked(namespace, name, self) {
|
||||
const elm = self.data("elm")
|
||||
const parts = window.location.hash.split("&")
|
||||
parts[2] = elm.revision
|
||||
window.location.hash = parts.join("&")
|
||||
$("#sectionDetails h1 span.rev").text(elm.revision)
|
||||
let qstr = "chart=" + name + "&namespace=" + namespace + "&revision1=" + (elm.revision - 1) + "&revision2=" + elm.revision
|
||||
let url = "/api/helm/charts/manifest/diff?" + qstr;
|
||||
$.getJSON(url).fail(function () {
|
||||
reportError("Failed to get diff of manifests")
|
||||
}).done(function (data) {
|
||||
if (data === "") {
|
||||
$("#manifestText").text("No differences to display")
|
||||
} else {
|
||||
const targetElement = document.getElementById('manifestText');
|
||||
const configuration = {
|
||||
inputFormat: 'diff',
|
||||
outputFormat: 'side-by-side',
|
||||
|
||||
drawFileList: false,
|
||||
showFiles: false,
|
||||
//matching: 'lines',
|
||||
};
|
||||
const diff2htmlUi = new Diff2HtmlUI(targetElement, data, configuration);
|
||||
diff2htmlUi.draw()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function fillChartDetails(namespace, name) {
|
||||
$("#sectionDetails").show()
|
||||
$("#sectionDetails h1 span.name").text(name)
|
||||
$.getJSON("/api/helm/charts/history?chart=" + name + "&namespace=" + namespace).fail(function () {
|
||||
reportError("Failed to get list of clusters")
|
||||
}).done(function (data) {
|
||||
let revRow = $("#sectionDetails .row");
|
||||
for (let x = 0; x < data.length; x++) {
|
||||
const elm = data[x]
|
||||
const rev = $(`<div class="col-md-2 rounded border border-secondary bg-gradient bg-white">
|
||||
<span><b class="rev-number"></b> - <span class="rev-status"></span></span><br/>
|
||||
<span class="text-muted">Chart:</span> <span class="chart-ver"></span><br/>
|
||||
<span class="text-muted">App:</span> <span class="app-ver"></span><br/>
|
||||
<span class="text-muted small rev-date"></span><br/>
|
||||
</div>`)
|
||||
rev.find(".rev-number").text("#" + elm.revision)
|
||||
rev.find(".app-ver").text(elm.app_version)
|
||||
rev.find(".chart-ver").text(elm.chart_ver)
|
||||
rev.find(".rev-date").text(elm.updated.replace("T", " "))
|
||||
rev.find(".rev-status").text(elm.status).attr("title", elm.action)
|
||||
|
||||
if (elm.status === "failed") {
|
||||
rev.find(".rev-status").parent().addClass("text-danger")
|
||||
}
|
||||
|
||||
if (elm.status === "deployed") {
|
||||
//rev.removeClass("bg-white").addClass("text-light bg-primary")
|
||||
}
|
||||
|
||||
rev.data("elm", elm)
|
||||
rev.addClass("rev-" + elm.revision)
|
||||
rev.click(function () {
|
||||
revisionClicked(namespace, name, $(this))
|
||||
})
|
||||
|
||||
revRow.append(rev)
|
||||
}
|
||||
|
||||
const parts = window.location.hash.substring(1).split("&")
|
||||
if (parts.length >= 3) {
|
||||
revRow.find(".rev-" + parts[2]).click()
|
||||
} else {
|
||||
revRow.find("div.col-md-2:last-child").click()
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
function loadChartsList() {
|
||||
$("#sectionList").show()
|
||||
$.getJSON("/api/helm/charts").fail(function () {
|
||||
reportError("Failed to get list of clusters")
|
||||
}).done(function (data) {
|
||||
chartsCards.empty()
|
||||
data.forEach(function (elm) {
|
||||
const header = $("<div class='card-header'></div>")
|
||||
header.append($('<div class="float-end"><h5 class="float-end text-muted text-end">#' + elm.revision + '</h5><br/><div class="badge">' + elm.status + "</div>"))
|
||||
// TODO: for pending- and uninstalling, add the spinner
|
||||
if (elm.status === "failed") {
|
||||
header.find(".badge").addClass("bg-danger text-light")
|
||||
} else if (elm.status === "deployed" || elm.status === "superseded") {
|
||||
header.find(".badge").addClass("bg-info")
|
||||
} else {
|
||||
header.find(".badge").addClass("bg-light text-dark")
|
||||
}
|
||||
|
||||
header.append($('<h5 class="card-title"></h5>').text(elm.name))
|
||||
header.append($('<p class="card-text small text-muted"></p>').append("Chart: " + elm.chart))
|
||||
|
||||
const body = $("<div class='card-body'></div>")
|
||||
body.append($('<p class="card-text"></p>').append("Namespace: " + elm.namespace))
|
||||
body.append($('<p class="card-text"></p>').append("Version: " + elm.app_version))
|
||||
body.append($('<p class="card-text"></p>').append("Updated: " + elm.updated))
|
||||
|
||||
let card = $("<div class='card'></div>").append(header).append(body);
|
||||
|
||||
card.data("chart", elm)
|
||||
card.click(function () {
|
||||
const self = $(this)
|
||||
$("#sectionList").hide()
|
||||
|
||||
let chart = self.data("chart");
|
||||
window.location.hash = chart.namespace + "&" + chart.name
|
||||
fillChartDetails(chart.namespace, chart.name)
|
||||
})
|
||||
|
||||
chartsCards.append($("<div class='col'></div>").append(card))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
$(function () {
|
||||
// cluster list
|
||||
$.getJSON("/api/kube/contexts").fail(function () {
|
||||
@@ -25,34 +145,10 @@ $(function () {
|
||||
// TODO: remember it, respect it in the function above and in all other places
|
||||
})
|
||||
|
||||
// charts list
|
||||
$.getJSON("/api/helm/charts").fail(function () {
|
||||
reportError("Failed to get list of clusters")
|
||||
}).done(function (data) {
|
||||
chartsCards.empty()
|
||||
data.forEach(function (elm) {
|
||||
const header = $("<div class='card-header'></div>")
|
||||
header.append($('<div class="float-end"><h5 class="float-end text-muted text-end">#' + elm.revision + '</h5><br/><div class="badge bg-info">' + elm.status + "</div>"))
|
||||
header.append($('<h5 class="card-title"></h5>').text(elm.name))
|
||||
header.append($('<p class="card-text small text-muted"></p>').append("Version: " + elm.app_version))
|
||||
|
||||
const body = $("<div class='card-body'></div>")
|
||||
body.append($('<p class="card-text"></p>').append("Namespace: " + elm.namespace))
|
||||
body.append($('<p class="card-text"></p>').append("Chart: " + elm.chart))
|
||||
body.append($('<p class="card-text"></p>').append("Updated: " + elm.updated))
|
||||
|
||||
/*
|
||||
"namespace": "default",
|
||||
"revision": "4",
|
||||
"updated": "2022-08-16 17:11:26.73393511 +0300 IDT",
|
||||
"status": "deployed",
|
||||
"chart": "k8s-watcher-0.17.1",
|
||||
"app_version": "0.1.108"
|
||||
|
||||
*/
|
||||
|
||||
let card = $("<div class='card'></div>").append(header).append(body);
|
||||
chartsCards.append($("<div class='col'></div>").append(card))
|
||||
})
|
||||
})
|
||||
const parts = window.location.hash.substring(1).split("&")
|
||||
if (parts[0] === "") {
|
||||
loadChartsList()
|
||||
} else {
|
||||
fillChartDetails(parts[0], parts[1])
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
#charts .card {
|
||||
#charts .card, #sectionDetails .row > div {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bg-primary .text-muted {
|
||||
color: white!important;
|
||||
}
|
||||
|
||||
.d2h-file-header {
|
||||
display: none;
|
||||
}
|
||||
Reference in New Issue
Block a user