Restyle LAF (#12)
* Logos change * Coding HTML * Top bar * Top bar is fine * Restyling it * progressing * age line * cosmetics * Installed list is fine * Save * revision list display * Split up files * Rev list works * Details * Working on details * Action buttons * cosmetics * Describe flyout * Uninstall confirm flyout * Working on flyouts * Fixed the actions working * Polishing it * Cosmetics
@@ -43,14 +43,13 @@ helm plugin uninstall dashboard
|
||||
|
||||
## Support Channels
|
||||
|
||||
We have two main channels for supporting the Helm Dashboard users: [Slack community](#TODO) for general conversations
|
||||
We have two main channels for supporting the Helm Dashboard users: [Slack community](https://komodorkommunity.slack.com/x-p3820586794880-3937175868755-4092688791734/archives/C042U85BD45/p1663573506220839) for general conversations
|
||||
and [GitHub issues](https://github.com/komodorio/helm-dashboard/issues) for real bugs.
|
||||
|
||||
## Roadmap
|
||||
|
||||
### First Public Version
|
||||
|
||||
- Helm Plugin Packaging
|
||||
- CLI launcher
|
||||
- Web Server with REST API
|
||||
- Listing the installed applications
|
||||
@@ -64,7 +63,12 @@ and [GitHub issues](https://github.com/komodorio/helm-dashboard/issues) for real
|
||||
- Switch clusters
|
||||
- Show manifest/describe upon clicking on resource
|
||||
|
||||
- Helm Plugin Packaging
|
||||
- Styled properly
|
||||
|
||||
### Further Ideas
|
||||
- solve umbrella-chart case
|
||||
- use `--dry-run` instead of `template`
|
||||
- Have cleaner idea on the web API structure
|
||||
- Recognise & show ArgoCD-originating charts/objects, those `helm ls` does not show
|
||||
- Recognise the revisions that are rollbacks by their description and mark in timeline
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/hexops/gotextdiff"
|
||||
"github.com/hexops/gotextdiff/myers"
|
||||
"github.com/hexops/gotextdiff/span"
|
||||
@@ -174,8 +173,6 @@ func (d *DataLayer) ChartHistory(namespace string, chartName string) (res []*his
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var aprev *semver.Version
|
||||
var cprev *semver.Version
|
||||
for _, elm := range res {
|
||||
chartRepoName, curVer, err := chartAndVersion(elm.Chart)
|
||||
if err != nil {
|
||||
@@ -183,32 +180,7 @@ func (d *DataLayer) ChartHistory(namespace string, chartName string) (res []*his
|
||||
}
|
||||
elm.ChartName = chartRepoName
|
||||
elm.ChartVer = curVer
|
||||
elm.Action = ""
|
||||
elm.Updated.Time = elm.Updated.Time.Round(time.Second)
|
||||
|
||||
cver, err1 := semver.NewVersion(elm.ChartVer)
|
||||
aver, err2 := semver.NewVersion(elm.AppVersion)
|
||||
if err1 == nil && err2 == nil {
|
||||
if aprev != nil && cprev != nil {
|
||||
switch {
|
||||
case aprev.LessThan(aver):
|
||||
elm.Action = "app_upgrade"
|
||||
case aprev.GreaterThan(aver):
|
||||
elm.Action = "app_downgrade"
|
||||
case cprev.LessThan(cver):
|
||||
elm.Action = "chart_upgrade"
|
||||
case cprev.GreaterThan(cver):
|
||||
elm.Action = "chart_downgrade"
|
||||
default:
|
||||
elm.Action = "reconfigure"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Debugf("Semver parsing errors: %s=%s, %s=%s", elm.ChartVer, err1, elm.AppVersion, err2)
|
||||
}
|
||||
|
||||
aprev = aver
|
||||
cprev = cver
|
||||
}
|
||||
|
||||
return res, nil
|
||||
|
||||
@@ -22,6 +22,8 @@ func (h *HelmHandler) GetCharts(c *gin.Context) {
|
||||
c.IndentedJSON(http.StatusOK, res)
|
||||
}
|
||||
|
||||
// TODO: helm show chart komodorio/k8s-watcher to get the icon URL
|
||||
|
||||
func (h *HelmHandler) Uninstall(c *gin.Context) {
|
||||
qp, err := getQueryProps(c, false)
|
||||
if err != nil {
|
||||
|
||||
@@ -25,7 +25,6 @@ type historyElement struct {
|
||||
Description string `json:"description"`
|
||||
ChartName string `json:"chart_name"`
|
||||
ChartVer string `json:"chart_ver"`
|
||||
Action string `json:"action"`
|
||||
}
|
||||
|
||||
type repoChartElement struct {
|
||||
|
||||
4
pkg/dashboard/static/action.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11 20.5C16.2467 20.5 20.5 16.2467 20.5 11C20.5 5.75329 16.2467 1.5 11 1.5C5.75329 1.5 1.5 5.75329 1.5 11C1.5 16.2467 5.75329 20.5 11 20.5ZM11 22C17.0751 22 22 17.0751 22 11C22 4.92487 17.0751 0 11 0C4.92487 0 0 4.92487 0 11C0 17.0751 4.92487 22 11 22Z" fill="#3B3D45"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.4718 16.3004C10.6247 16.8115 8.56283 16.3411 7.11084 14.8891C5.65885 13.4371 5.18842 11.3753 5.69955 9.52809L4.51969 8.34823C3.48499 10.8798 3.99515 13.8947 6.05018 15.9498C8.10522 18.0048 11.1201 18.515 13.6517 17.4803L12.4718 16.3004ZM10.213 5.55627C11.8698 5.31807 13.6144 5.83629 14.889 7.11092C16.1636 8.38555 16.6819 10.1302 16.4437 11.7869L17.6973 13.0406C18.4242 10.6477 17.8416 7.94219 15.9497 6.05026C14.0577 4.15833 11.3523 3.57578 8.95934 4.3026L10.213 5.55627Z" fill="#3B3D45"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 968 B |
189
pkg/dashboard/static/actions.js
Normal file
@@ -0,0 +1,189 @@
|
||||
$("#btnUpgradeCheck").click(function () {
|
||||
const self = $(this)
|
||||
self.find(".bi-repeat").hide()
|
||||
self.find(".spinner-border").show()
|
||||
const repoName = self.data("repo")
|
||||
$("#btnUpgrade span").text("Checking...")
|
||||
$.post("/api/helm/repo/update?name=" + repoName).fail(function (xhr) {
|
||||
reportError("Failed to update chart repo", xhr)
|
||||
}).done(function () {
|
||||
self.find(".spinner-border").hide()
|
||||
self.find(".bi-repeat").show()
|
||||
|
||||
checkUpgradeable(self.data("chart"))
|
||||
$("#btnUpgradeCheck").prop("disabled", true)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
function checkUpgradeable(name) {
|
||||
$.getJSON("/api/helm/repo/search?name=" + name).fail(function (xhr) {
|
||||
reportError("Failed to find chart in repo", xhr)
|
||||
}).done(function (data) {
|
||||
if (!data) {
|
||||
return
|
||||
}
|
||||
|
||||
$('#upgradeModalLabel select').empty()
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
$('#upgradeModalLabel select').append("<option value='" + data[i].version + "'>" + data[i].version + "</option>")
|
||||
}
|
||||
|
||||
const elm = data[0]
|
||||
$("#btnUpgradeCheck").data("repo", elm.name.split('/').shift())
|
||||
$("#btnUpgradeCheck").data("chart", elm.name.split('/').pop())
|
||||
|
||||
const verCur = $("#specRev").data("last-chart-ver");
|
||||
const canUpgrade = isNewerVersion(verCur, elm.version);
|
||||
$("#btnUpgradeCheck").prop("disabled", false)
|
||||
if (canUpgrade) {
|
||||
$("#btnUpgrade span").text("Upgrade to " + elm.version)
|
||||
} else {
|
||||
$("#btnUpgrade span").text("No upgrades")
|
||||
}
|
||||
|
||||
$("#btnUpgrade").off("click").click(function () {
|
||||
popUpUpgrade($(this), verCur, elm)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function popUpUpgrade(self, verCur, elm) {
|
||||
const name = getHashParam("chart");
|
||||
let url = "/api/helm/charts/install?namespace=" + getHashParam("namespace") + "&name=" + name + "&chart=" + elm.name;
|
||||
$('#upgradeModalLabel select').data("url", url)
|
||||
|
||||
$("#upgradeModalLabel .name").text(name)
|
||||
$("#upgradeModalLabel .ver-old").text(verCur)
|
||||
|
||||
$('#upgradeModalLabel select').val(elm.version).trigger("change")
|
||||
|
||||
const myModal = new bootstrap.Offcanvas(document.getElementById('upgradeModal'), {});
|
||||
myModal.show()
|
||||
|
||||
const btnConfirm = $("#upgradeModal .btn-confirm");
|
||||
btnConfirm.prop("disabled", true).off('click').click(function () {
|
||||
console.log("working")
|
||||
btnConfirm.prop("disabled", true).prepend('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>')
|
||||
$.ajax({
|
||||
url: url + "&version=" + $('#upgradeModalLabel select').val(),
|
||||
type: 'POST',
|
||||
}).fail(function (xhr) {
|
||||
reportError("Failed to upgrade the chart", xhr)
|
||||
}).done(function (data) {
|
||||
setHashParam("revision", data.version)
|
||||
window.location.reload()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
$('#upgradeModalLabel select').change(function () {
|
||||
const self = $(this)
|
||||
|
||||
$("#upgradeModalBody").empty().append('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>')
|
||||
$("#upgradeModal .btn-confirm").prop("disabled", true)
|
||||
$.get(self.data("url") + "&version=" + self.val()).fail(function (xhr) {
|
||||
reportError("Failed to get upgrade info", xhr)
|
||||
}).done(function (data) {
|
||||
$("#upgradeModalBody").empty();
|
||||
$("#upgradeModal .btn-confirm").prop("disabled", false)
|
||||
|
||||
const targetElement = document.getElementById('upgradeModalBody');
|
||||
const configuration = {
|
||||
inputFormat: 'diff', outputFormat: 'side-by-side',
|
||||
drawFileList: false, showFiles: false, highlight: true,
|
||||
};
|
||||
const diff2htmlUi = new Diff2HtmlUI(targetElement, data, configuration);
|
||||
diff2htmlUi.draw()
|
||||
$("#upgradeModalBody").prepend("<p>Following changes will happen to cluster:</p>")
|
||||
if (!data) {
|
||||
$("#upgradeModalBody").html("No changes will happen to cluster")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const btnConfirm = $("#confirmModal .btn-confirm");
|
||||
$("#btnUninstall").click(function () {
|
||||
const chart = getHashParam('chart');
|
||||
const namespace = getHashParam('namespace');
|
||||
const revision = $("#specRev").data("last-rev")
|
||||
$("#confirmModalLabel").html("Uninstall <b class='text-danger'>" + chart + "</b> from namespace <b class='text-danger'>" + namespace + "</b>")
|
||||
$("#confirmModalBody").empty().append('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>')
|
||||
btnConfirm.prop("disabled", true).off('click').click(function () {
|
||||
btnConfirm.prop("disabled", true).append('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>')
|
||||
const url = "/api/helm/charts?namespace=" + namespace + "&name=" + chart;
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: 'DELETE',
|
||||
}).fail(function (xhr) {
|
||||
reportError("Failed to delete the chart", xhr)
|
||||
}).done(function () {
|
||||
window.location.href = "/"
|
||||
})
|
||||
})
|
||||
|
||||
const myModal = new bootstrap.Offcanvas(document.getElementById('confirmModal'));
|
||||
myModal.show()
|
||||
|
||||
let qstr = "name=" + chart + "&namespace=" + namespace + "&revision=" + revision
|
||||
let url = "/api/helm/charts/resources"
|
||||
url += "?" + qstr
|
||||
$.getJSON(url).fail(function (xhr) {
|
||||
reportError("Failed to get list of resources", xhr)
|
||||
}).done(function (data) {
|
||||
$("#confirmModalBody").empty().append("<p>Following resources will be deleted from the cluster:</p>");
|
||||
btnConfirm.prop("disabled", false)
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const res = data[i]
|
||||
$("#confirmModalBody").append("<p class='row'><i class='col-sm-3 text-end'>" + res.kind + "</i><b class='col-sm-9'>" + res.metadata.name + "</b></p>")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
$("#btnRollback").click(function () {
|
||||
const chart = getHashParam('chart');
|
||||
const namespace = getHashParam('namespace');
|
||||
const revisionNew = $("#btnRollback").data("rev")
|
||||
const revisionCur = $("#specRev").data("last-rev")
|
||||
$("#confirmModalLabel").html("Rollback <b class='text-danger'>" + chart + "</b> from revision " + revisionCur + " to " + revisionNew)
|
||||
$("#confirmModalBody").empty().append('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>')
|
||||
btnConfirm.prop("disabled", true).off('click').click(function () {
|
||||
btnConfirm.prop("disabled", true).append('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>')
|
||||
const url = "/api/helm/charts/rollback?namespace=" + namespace + "&name=" + chart + "&revision=" + revisionNew;
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: 'POST',
|
||||
}).fail(function (xhr) {
|
||||
reportError("Failed to rollback the chart", xhr)
|
||||
}).done(function () {
|
||||
window.location.reload()
|
||||
})
|
||||
})
|
||||
|
||||
const myModal = new bootstrap.Offcanvas(document.getElementById('confirmModal'), {});
|
||||
myModal.show()
|
||||
|
||||
let qstr = "name=" + chart + "&namespace=" + namespace + "&revision=" + revisionNew + "&revisionDiff=" + revisionCur
|
||||
let url = "/api/helm/charts/manifests"
|
||||
url += "?" + qstr
|
||||
$.get(url).fail(function (xhr) {
|
||||
reportError("Failed to get list of resources", xhr)
|
||||
}).done(function (data) {
|
||||
$("#confirmModalBody").empty();
|
||||
$("#confirmModal .btn-confirm").prop("disabled", false)
|
||||
|
||||
const targetElement = document.getElementById('confirmModalBody');
|
||||
const configuration = {
|
||||
inputFormat: 'diff', outputFormat: 'side-by-side',
|
||||
drawFileList: false, showFiles: false, highlight: true,
|
||||
};
|
||||
const diff2htmlUi = new Diff2HtmlUI(targetElement, data, configuration);
|
||||
diff2htmlUi.draw()
|
||||
if (data) {
|
||||
$("#confirmModalBody").prepend("<p>Following changes will happen to cluster:</p>")
|
||||
} else {
|
||||
$("#confirmModalBody").html("<p>No changes will happen to cluster</p>")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
207
pkg/dashboard/static/details-view.js
Normal file
@@ -0,0 +1,207 @@
|
||||
function revisionClicked(namespace, name, self) {
|
||||
let active = "active border-primary border-1 bg-white";
|
||||
let inactive = "border-secondary bg-secondary";
|
||||
revRow.find(".active").removeClass(active).addClass(inactive)
|
||||
self.removeClass(inactive).addClass(active)
|
||||
const elm = self.data("elm")
|
||||
console.log(elm)
|
||||
setHashParam("revision", elm.revision)
|
||||
$("#sectionDetails span.rev").text("#"+elm.revision)
|
||||
statusStyle(elm.status, $("#none"), $("#sectionDetails .rev-details .rev-status"))
|
||||
|
||||
$("#sectionDetails .rev-date").text(elm.updated.replace("T", " ").replace("+", " +"))
|
||||
$("#sectionDetails .rev-tags .rev-chart").text(elm.chart)
|
||||
$("#sectionDetails .rev-tags .rev-app").text(elm.app_version)
|
||||
$("#sectionDetails .rev-tags .rev-ns").text(getHashParam("namespace"))
|
||||
|
||||
$("#revDescr").text(elm.description).removeClass("text-danger")
|
||||
if (elm.status === "failed") {
|
||||
$("#revDescr").addClass("text-danger")
|
||||
}
|
||||
|
||||
const rev = $("#specRev").data("last-rev") == elm.revision ? elm.revision - 1 : elm.revision
|
||||
if (!rev || getHashParam("revision") === $("#specRev").data("first-rev")) {
|
||||
$("#btnRollback").hide()
|
||||
} else {
|
||||
$("#btnRollback").show().data("rev", rev).find("span").text("Rollback to #" + rev)
|
||||
}
|
||||
|
||||
const tab = getHashParam("tab")
|
||||
if (!tab) {
|
||||
$("#nav-tab [data-tab=resources]").click()
|
||||
} else {
|
||||
$("#nav-tab [data-tab=" + tab + "]").click()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function loadContentWrapper() {
|
||||
let revDiff = 0
|
||||
const revision = parseInt(getHashParam("revision"));
|
||||
if (revision === $("#specRev").data("first-rev")) {
|
||||
revDiff = 0
|
||||
} else if (getHashParam("mode") === "diff-prev") {
|
||||
revDiff = revision - 1
|
||||
} else if (getHashParam("mode") === "diff-rev") {
|
||||
revDiff = $("#specRev").val()
|
||||
}
|
||||
|
||||
const flag = $("#userDefinedVals").prop("checked");
|
||||
loadContent(getHashParam("tab"), getHashParam("namespace"), getHashParam("chart"), revision, revDiff, flag)
|
||||
}
|
||||
|
||||
function loadContent(mode, namespace, name, revision, revDiff, flag) {
|
||||
let qstr = "name=" + name + "&namespace=" + namespace + "&revision=" + revision
|
||||
if (revDiff) {
|
||||
qstr += "&revisionDiff=" + revDiff
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
qstr += "&flag=" + flag
|
||||
}
|
||||
|
||||
let url = "/api/helm/charts/" + mode
|
||||
url += "?" + qstr
|
||||
const diffDisplay = $("#manifestText");
|
||||
diffDisplay.empty().append('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>')
|
||||
$.get(url).fail(function (xhr) {
|
||||
reportError("Failed to get diff of " + mode, xhr)
|
||||
}).done(function (data) {
|
||||
diffDisplay.empty();
|
||||
if (data === "") {
|
||||
diffDisplay.text("No differences to display")
|
||||
} else {
|
||||
if (revDiff) {
|
||||
const targetElement = document.getElementById('manifestText');
|
||||
const configuration = {
|
||||
inputFormat: 'diff', outputFormat: 'side-by-side',
|
||||
|
||||
drawFileList: false, showFiles: false, highlight: true, //matching: 'lines',
|
||||
};
|
||||
const diff2htmlUi = new Diff2HtmlUI(targetElement, data, configuration);
|
||||
diff2htmlUi.draw()
|
||||
} else {
|
||||
data = hljs.highlight(data, {language: 'yaml'}).value
|
||||
const code = $("#manifestText").empty().append("<pre class='bg-white rounded p-3'></pre>").find("pre");
|
||||
code.html(data)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
$('#specRev').keyup(function (event) {
|
||||
let keycode = (event.keyCode ? event.keyCode : event.which);
|
||||
if (keycode == '13') {
|
||||
$("#diffModeRev").click()
|
||||
}
|
||||
event.preventDefault()
|
||||
});
|
||||
|
||||
|
||||
$("#userDefinedVals").change(function () {
|
||||
const self = $(this)
|
||||
const flag = $("#userDefinedVals").prop("checked");
|
||||
setHashParam("udv", flag)
|
||||
loadContentWrapper()
|
||||
})
|
||||
|
||||
$("#modePanel [data-mode]").click(function () {
|
||||
const self = $(this)
|
||||
const mode = self.data("mode")
|
||||
setHashParam("mode", mode)
|
||||
loadContentWrapper()
|
||||
})
|
||||
|
||||
$("#nav-tab [data-tab]").click(function () {
|
||||
const self = $(this)
|
||||
setHashParam("tab", self.data("tab"))
|
||||
|
||||
if (self.data("tab") === "values") {
|
||||
$("#userDefinedVals").parent().show()
|
||||
} else {
|
||||
$("#userDefinedVals").parent().hide()
|
||||
}
|
||||
|
||||
const flag = getHashParam("udv") === "true";
|
||||
$("#userDefinedVals").prop("checked", flag)
|
||||
|
||||
if (self.data("tab") === "resources") {
|
||||
showResources(getHashParam("namespace"), getHashParam("chart"), getHashParam("revision"))
|
||||
} else {
|
||||
const mode = getHashParam("mode")
|
||||
if (!mode) {
|
||||
$("#modePanel [data-mode=view]").trigger('click')
|
||||
} else {
|
||||
$("#modePanel [data-mode=" + mode + "]").trigger('click')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function showResources(namespace, chart, revision) {
|
||||
const resBody = $("#nav-resources .body");
|
||||
resBody.empty().append('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>');
|
||||
let qstr = "name=" + chart + "&namespace=" + namespace + "&revision=" + revision
|
||||
let url = "/api/helm/charts/resources"
|
||||
url += "?" + qstr
|
||||
$.getJSON(url).fail(function (xhr) {
|
||||
reportError("Failed to get list of resources", xhr)
|
||||
}).done(function (data) {
|
||||
resBody.empty();
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const res = data[i]
|
||||
const resBlock = $(`
|
||||
<div class="row px-3 py-2 mb-2">
|
||||
<div class="col-2 res-kind"></div>
|
||||
<div class="col-4 res-name"></div>
|
||||
<div class="col-5 res-status"><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> <span class="text-muted small">Getting status...</span></div>
|
||||
<div class="col-1 res-actions"></div>
|
||||
</div>
|
||||
`)
|
||||
|
||||
resBlock.find(".res-kind").text(res.kind)
|
||||
resBlock.find(".res-name").text(res.metadata.name)
|
||||
|
||||
resBody.append(resBlock)
|
||||
let ns = res.metadata.namespace ? res.metadata.namespace : namespace
|
||||
$.getJSON("/api/kube/resources/" + res.kind.toLowerCase() + "?name=" + res.metadata.name + "&namespace=" + ns).fail(function () {
|
||||
//reportError("Failed to get list of resources")
|
||||
}).done(function (data) {
|
||||
const badge = $("<span class='badge me-2'></span>").text(data.status.phase);
|
||||
if (["Available", "Active", "Established"].includes(data.status.phase)) {
|
||||
badge.addClass("bg-success")
|
||||
} else if (["Exists"].includes(data.status.phase)) {
|
||||
badge.addClass("bg-success bg-opacity-50")
|
||||
} else if (["Progressing"].includes(data.status.phase)) {
|
||||
badge.addClass("bg-warning")
|
||||
} else {
|
||||
badge.addClass("bg-danger")
|
||||
}
|
||||
|
||||
const statusBlock = resBlock.find(".res-status");
|
||||
statusBlock.empty().append(badge).append("<span class='text-muted small'>" + (data.status.message ? data.status.message : '') + "</span>")
|
||||
|
||||
if (badge.text() !== "NotFound") {
|
||||
resBlock.find(".res-actions")
|
||||
resBlock.find(".res-actions").append("<i class=\"btn bi-zoom-in float-end text-muted\"></i>")
|
||||
statusBlock.find(".bi-zoom-in").click(function () {
|
||||
showDescribe(ns, res.kind, res.metadata.name)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function showDescribe(ns, kind, name) {
|
||||
$("#describeModalLabel").text("Describe " + kind + ": " + ns + " / " + name)
|
||||
$("#describeModalBody").empty().append('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>')
|
||||
|
||||
const myModal = new bootstrap.Offcanvas(document.getElementById('describeModal'));
|
||||
myModal.show()
|
||||
$.get("/api/kube/describe/" + kind.toLowerCase() + "?name=" + name + "&namespace=" + ns).fail(function (xhr) {
|
||||
reportError("Failed to describe resource", xhr)
|
||||
}).done(function (data) {
|
||||
data = hljs.highlight(data, {language: 'yaml'}).value
|
||||
$("#describeModalBody").empty().append("<pre class='bg-white rounded p-3'></pre>").find("pre").html(data)
|
||||
})
|
||||
}
|
||||
65
pkg/dashboard/static/helm-gray-50.svg
Normal file
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="28"
|
||||
height="28"
|
||||
viewBox="0 0 28 28"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg886"
|
||||
sodipodi:docname="helm-gray-50.svg"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs890" />
|
||||
<sodipodi:namedview
|
||||
id="namedview888"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="64.928571"
|
||||
inkscape:cx="13.992299"
|
||||
inkscape:cy="14"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2059"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg886" />
|
||||
<path
|
||||
d="M7.64558 6.78334C7.61355 6.75296 7.57868 6.72027 7.54422 6.68716C6.83768 6.00837 6.29089 5.22352 5.9606 4.29585C5.86816 4.03621 5.79837 3.7714 5.81075 3.49176C5.81193 3.46522 5.81185 3.4386 5.81368 3.41212C5.8386 3.05114 6.08019 2.86874 6.43295 2.95422C6.54422 2.98304 6.65188 3.0243 6.75391 3.07723C7.13976 3.27073 7.45426 3.55679 7.74346 3.87051C8.25713 4.41715 8.66907 5.05112 8.95989 5.74257C8.96624 5.75904 8.97352 5.77514 8.9817 5.79078C8.98569 5.79798 8.99415 5.8027 9.01302 5.81984C10.3898 4.99388 11.9471 4.51602 13.5501 4.42764C13.5403 4.37858 13.5344 4.34108 13.5251 4.30444C13.3615 3.62754 13.3113 2.9282 13.3765 2.23488C13.4052 1.81941 13.4889 1.40957 13.6254 1.01611C13.6914 0.808874 13.7954 0.615724 13.9321 0.446513C13.9837 0.386073 14.0433 0.33292 14.1092 0.288509C14.1749 0.242074 14.2532 0.216879 14.3337 0.216318C14.4141 0.215757 14.4927 0.239858 14.5591 0.285373C14.6992 0.380274 14.8119 0.510259 14.8861 0.662357C15.0243 0.920312 15.1236 1.19726 15.1808 1.48424C15.3112 2.09109 15.3513 2.71388 15.2997 3.33244C15.2741 3.70997 15.2086 4.08373 15.1042 4.44745C15.503 4.52092 15.8999 4.57785 16.2884 4.67017C16.6761 4.76031 17.0583 4.87256 17.4331 5.00635C17.811 5.14505 18.1807 5.30527 18.5402 5.48623C18.8956 5.66344 19.2338 5.87491 19.5884 6.07638C19.5999 6.05213 19.6167 6.02319 19.628 5.99226C19.9973 4.97054 20.6335 4.06633 21.4704 3.37357C21.6658 3.20585 21.8901 3.07522 22.1324 2.98812C22.1992 2.96486 22.2682 2.94899 22.3384 2.9408C22.6892 2.90063 22.8365 3.12136 22.8624 3.38498C22.8818 3.57931 22.8672 3.77555 22.8191 3.96484C22.6909 4.45379 22.4883 4.92009 22.2182 5.34735C21.8379 5.96177 21.3866 6.51522 20.813 6.96185C20.796 6.97503 20.7812 6.99087 20.7525 7.01731C21.3135 7.53479 21.8132 8.11507 22.2417 8.74672C22.2106 8.75474 22.179 8.76031 22.1471 8.76339C21.5538 8.76423 20.9604 8.76237 20.3671 8.76597C20.3321 8.76513 20.2979 8.75614 20.267 8.73971C20.2362 8.72327 20.2096 8.69986 20.1894 8.67133C18.8949 7.25696 17.1496 6.33565 15.2515 6.06462C14.6902 5.98295 14.1218 5.961 13.5558 5.99914C11.8683 6.10218 10.2539 6.72438 8.93373 7.78053C8.59283 8.04942 8.27485 8.34616 7.98306 8.66767C7.95717 8.6998 7.92412 8.72543 7.88656 8.74252C7.84899 8.75961 7.80796 8.76768 7.76672 8.76609C7.19997 8.76215 6.63318 8.76413 6.0664 8.76413H5.94588C5.98049 8.62928 6.32893 8.15161 6.72336 7.72518C7.01749 7.40716 7.32909 7.10529 7.64558 6.78334Z"
|
||||
fill="#3B3D45"
|
||||
id="path874"
|
||||
style="opacity:1;fill:#3b3d45;fill-opacity:0.5" />
|
||||
<path
|
||||
d="M22.0936 19.4833C21.6995 20.035 21.2496 20.5447 20.7511 21.0044C20.7909 21.0375 20.8231 21.0644 20.8554 21.0913C21.7206 21.799 22.3734 22.7321 22.7417 23.7874C22.8397 24.0448 22.8817 24.3201 22.865 24.595C22.8598 24.6654 22.8458 24.7348 22.8231 24.8017C22.7946 24.8964 22.7324 24.9774 22.6482 25.0292C22.564 25.0811 22.4636 25.1002 22.3663 25.083C22.2348 25.0659 22.107 25.028 21.9875 24.9706C21.8051 24.8806 21.6327 24.7715 21.4734 24.645C20.634 23.9554 19.9967 23.0516 19.629 22.0294C19.6185 22.0007 19.607 21.9723 19.5885 21.9243C19.1415 22.2198 18.6734 22.482 18.1878 22.7087C17.7046 22.929 17.205 23.1111 16.6934 23.2533C16.1735 23.3944 15.6436 23.4952 15.1083 23.555C15.1177 23.6021 15.1231 23.6396 15.1328 23.6759C15.3026 24.342 15.3588 25.032 15.2992 25.7167C15.2768 26.146 15.1934 26.5698 15.0515 26.9755C14.9839 27.1434 14.906 27.3069 14.8183 27.4652C14.7827 27.5266 14.7386 27.5826 14.6873 27.6315C14.4644 27.8617 14.1983 27.8636 13.9811 27.6274C13.8952 27.5322 13.8217 27.4265 13.7623 27.3128C13.59 26.9894 13.5013 26.6377 13.438 26.2791C13.3565 25.7895 13.331 25.2923 13.3619 24.797C13.3787 24.4343 13.4328 24.0743 13.5234 23.7226C13.5312 23.6928 13.5384 23.6627 13.5442 23.6325C13.5457 23.6248 13.5406 23.6158 13.5346 23.5911C11.9318 23.5005 10.3754 23.0201 9.0004 22.1915C8.97745 22.2424 8.95773 22.2853 8.93871 22.3284C8.55337 23.2275 7.96033 24.0225 7.20825 24.648C7.00915 24.8181 6.78047 24.9502 6.53361 25.0377C6.41792 25.0841 6.29167 25.0977 6.16876 25.0769C6.10089 25.0647 6.03733 25.0352 5.9843 24.9911C5.93126 24.9471 5.89056 24.89 5.86618 24.8255C5.78687 24.6338 5.80092 24.4343 5.82785 24.2366C5.87203 23.9609 5.95317 23.6925 6.06908 23.4385C6.41254 22.6386 6.91804 21.9186 7.55371 21.3238C7.57941 21.2995 7.60578 21.2758 7.63103 21.251C7.63906 21.2395 7.64591 21.2272 7.65149 21.2143C7.05256 20.6949 6.51739 20.1062 6.05723 19.4606C6.11237 19.4561 6.14925 19.4505 6.18615 19.4505C6.77495 19.4499 7.36377 19.452 7.95254 19.448C7.99171 19.4469 8.03065 19.4544 8.06652 19.4702C8.1024 19.4859 8.13431 19.5095 8.15994 19.5391C8.80004 20.1976 9.54586 20.7444 10.3665 21.1567C11.2347 21.6034 12.1787 21.884 13.1499 21.984C15.7886 22.2405 18.0585 21.4405 19.9595 19.5841C20.002 19.5382 20.0541 19.5021 20.1121 19.4785C20.1701 19.4548 20.2325 19.4442 20.2951 19.4473C20.844 19.4541 21.393 19.4501 21.9419 19.4501H22.0838L22.0936 19.4833Z"
|
||||
fill="#3B3D45"
|
||||
id="path876"
|
||||
style="opacity:1;fill:#3b3d45;fill-opacity:0.5" />
|
||||
<path
|
||||
d="M19.6412 11.0745C19.7972 11.0745 19.9475 11.0851 20.0956 11.0717C20.2633 11.0565 20.3834 11.1165 20.5057 11.2292C21.212 11.88 21.9257 12.5229 22.637 13.1683C22.6728 13.2008 22.7093 13.2324 22.7552 13.273C22.798 13.2362 22.8381 13.2034 22.8764 13.1686C23.6096 12.5012 24.3422 11.8331 25.0743 11.1645C25.1047 11.1332 25.1414 11.1088 25.182 11.0929C25.2226 11.077 25.2662 11.07 25.3097 11.0724C25.49 11.0797 25.6707 11.0745 25.8608 11.0745V16.9751C25.7643 17.0033 24.4678 17.0089 24.313 16.9785V13.9903L24.283 13.976C23.7784 14.4362 23.2738 14.8964 22.7577 15.3671C22.241 14.9017 21.7305 14.4418 21.22 13.9819L21.1906 13.9927C21.1893 14.2421 21.1902 14.4915 21.19 14.7409C21.1899 14.9888 21.1899 15.2367 21.19 15.4846V16.9894H19.654C19.6253 16.8901 19.6119 11.4083 19.6412 11.0745Z"
|
||||
fill="#3B3D45"
|
||||
id="path878"
|
||||
style="opacity:1;fill:#3b3d45;fill-opacity:0.5" />
|
||||
<path
|
||||
d="M5.46747 11.0815H6.99421C7.02504 11.1797 7.03107 16.8479 6.99951 16.9909H5.47141C5.46299 16.6155 5.46875 16.2414 5.4677 15.8675C5.46665 15.4966 5.46747 15.1258 5.46747 14.7453H3.57536V16.9708C3.46003 17.0052 2.15667 17.0085 2.0271 16.9777V11.0822H3.56924V13.1648C3.67944 13.1966 5.30094 13.2025 5.46607 13.172C5.46653 13.0053 5.46719 12.8346 5.46742 12.6638C5.46765 12.4867 5.46767 12.3096 5.46747 12.1325C5.46747 11.9599 5.46747 11.7872 5.46747 11.6145C5.46747 11.4422 5.46747 11.2698 5.46747 11.0815Z"
|
||||
fill="#3B3D45"
|
||||
id="path880"
|
||||
style="opacity:1;fill:#3b3d45;fill-opacity:0.5" />
|
||||
<path
|
||||
d="M8.82422 16.9889V11.0991C8.91477 11.0695 12.2707 11.0579 12.4901 11.0877V12.3429C12.4409 12.3464 12.3901 12.3531 12.3393 12.3532C11.7417 12.354 11.144 12.3541 10.5463 12.3537H10.3801V13.33H12.2476V14.6287H10.3968C10.3659 14.7399 10.3574 15.5145 10.3825 15.7289C10.4298 15.7321 10.4805 15.7384 10.5312 15.7384C11.1289 15.7391 11.7265 15.7393 12.3242 15.7389H12.4905V16.9889H8.82422Z"
|
||||
fill="#3B3D45"
|
||||
id="path882"
|
||||
style="opacity:1;fill:#3b3d45;fill-opacity:0.5" />
|
||||
<path
|
||||
d="M14.2399 16.991C14.2118 16.833 14.2175 11.1893 14.2453 11.082H15.7664V15.4368C15.832 15.4403 15.8835 15.4452 15.935 15.4452C16.5371 15.4458 17.1392 15.4459 17.7413 15.4456C17.7932 15.4456 17.845 15.4456 17.9042 15.4456V16.991L14.2399 16.991Z"
|
||||
fill="#3B3D45"
|
||||
id="path884"
|
||||
style="opacity:1;fill:#3b3d45;fill-opacity:0.5" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.1 KiB |
8
pkg/dashboard/static/helm-gray.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.64558 6.78334C7.61355 6.75296 7.57868 6.72027 7.54422 6.68716C6.83768 6.00837 6.29089 5.22352 5.9606 4.29585C5.86816 4.03621 5.79837 3.7714 5.81075 3.49176C5.81193 3.46522 5.81185 3.4386 5.81368 3.41212C5.8386 3.05114 6.08019 2.86874 6.43295 2.95422C6.54422 2.98304 6.65188 3.0243 6.75391 3.07723C7.13976 3.27073 7.45426 3.55679 7.74346 3.87051C8.25713 4.41715 8.66907 5.05112 8.95989 5.74257C8.96624 5.75904 8.97352 5.77514 8.9817 5.79078C8.98569 5.79798 8.99415 5.8027 9.01302 5.81984C10.3898 4.99388 11.9471 4.51602 13.5501 4.42764C13.5403 4.37858 13.5344 4.34108 13.5251 4.30444C13.3615 3.62754 13.3113 2.9282 13.3765 2.23488C13.4052 1.81941 13.4889 1.40957 13.6254 1.01611C13.6914 0.808874 13.7954 0.615724 13.9321 0.446513C13.9837 0.386073 14.0433 0.33292 14.1092 0.288509C14.1749 0.242074 14.2532 0.216879 14.3337 0.216318C14.4141 0.215757 14.4927 0.239858 14.5591 0.285373C14.6992 0.380274 14.8119 0.510259 14.8861 0.662357C15.0243 0.920312 15.1236 1.19726 15.1808 1.48424C15.3112 2.09109 15.3513 2.71388 15.2997 3.33244C15.2741 3.70997 15.2086 4.08373 15.1042 4.44745C15.503 4.52092 15.8999 4.57785 16.2884 4.67017C16.6761 4.76031 17.0583 4.87256 17.4331 5.00635C17.811 5.14505 18.1807 5.30527 18.5402 5.48623C18.8956 5.66344 19.2338 5.87491 19.5884 6.07638C19.5999 6.05213 19.6167 6.02319 19.628 5.99226C19.9973 4.97054 20.6335 4.06633 21.4704 3.37357C21.6658 3.20585 21.8901 3.07522 22.1324 2.98812C22.1992 2.96486 22.2682 2.94899 22.3384 2.9408C22.6892 2.90063 22.8365 3.12136 22.8624 3.38498C22.8818 3.57931 22.8672 3.77555 22.8191 3.96484C22.6909 4.45379 22.4883 4.92009 22.2182 5.34735C21.8379 5.96177 21.3866 6.51522 20.813 6.96185C20.796 6.97503 20.7812 6.99087 20.7525 7.01731C21.3135 7.53479 21.8132 8.11507 22.2417 8.74672C22.2106 8.75474 22.179 8.76031 22.1471 8.76339C21.5538 8.76423 20.9604 8.76237 20.3671 8.76597C20.3321 8.76513 20.2979 8.75614 20.267 8.73971C20.2362 8.72327 20.2096 8.69986 20.1894 8.67133C18.8949 7.25696 17.1496 6.33565 15.2515 6.06462C14.6902 5.98295 14.1218 5.961 13.5558 5.99914C11.8683 6.10218 10.2539 6.72438 8.93373 7.78053C8.59283 8.04942 8.27485 8.34616 7.98306 8.66767C7.95717 8.6998 7.92412 8.72543 7.88656 8.74252C7.84899 8.75961 7.80796 8.76768 7.76672 8.76609C7.19997 8.76215 6.63318 8.76413 6.0664 8.76413H5.94588C5.98049 8.62928 6.32893 8.15161 6.72336 7.72518C7.01749 7.40716 7.32909 7.10529 7.64558 6.78334Z" fill="#3B3D45"/>
|
||||
<path d="M22.0936 19.4833C21.6995 20.035 21.2496 20.5447 20.7511 21.0044C20.7909 21.0375 20.8231 21.0644 20.8554 21.0913C21.7206 21.799 22.3734 22.7321 22.7417 23.7874C22.8397 24.0448 22.8817 24.3201 22.865 24.595C22.8598 24.6654 22.8458 24.7348 22.8231 24.8017C22.7946 24.8964 22.7324 24.9774 22.6482 25.0292C22.564 25.0811 22.4636 25.1002 22.3663 25.083C22.2348 25.0659 22.107 25.028 21.9875 24.9706C21.8051 24.8806 21.6327 24.7715 21.4734 24.645C20.634 23.9554 19.9967 23.0516 19.629 22.0294C19.6185 22.0007 19.607 21.9723 19.5885 21.9243C19.1415 22.2198 18.6734 22.482 18.1878 22.7087C17.7046 22.929 17.205 23.1111 16.6934 23.2533C16.1735 23.3944 15.6436 23.4952 15.1083 23.555C15.1177 23.6021 15.1231 23.6396 15.1328 23.6759C15.3026 24.342 15.3588 25.032 15.2992 25.7167C15.2768 26.146 15.1934 26.5698 15.0515 26.9755C14.9839 27.1434 14.906 27.3069 14.8183 27.4652C14.7827 27.5266 14.7386 27.5826 14.6873 27.6315C14.4644 27.8617 14.1983 27.8636 13.9811 27.6274C13.8952 27.5322 13.8217 27.4265 13.7623 27.3128C13.59 26.9894 13.5013 26.6377 13.438 26.2791C13.3565 25.7895 13.331 25.2923 13.3619 24.797C13.3787 24.4343 13.4328 24.0743 13.5234 23.7226C13.5312 23.6928 13.5384 23.6627 13.5442 23.6325C13.5457 23.6248 13.5406 23.6158 13.5346 23.5911C11.9318 23.5005 10.3754 23.0201 9.0004 22.1915C8.97745 22.2424 8.95773 22.2853 8.93871 22.3284C8.55337 23.2275 7.96033 24.0225 7.20825 24.648C7.00915 24.8181 6.78047 24.9502 6.53361 25.0377C6.41792 25.0841 6.29167 25.0977 6.16876 25.0769C6.10089 25.0647 6.03733 25.0352 5.9843 24.9911C5.93126 24.9471 5.89056 24.89 5.86618 24.8255C5.78687 24.6338 5.80092 24.4343 5.82785 24.2366C5.87203 23.9609 5.95317 23.6925 6.06908 23.4385C6.41254 22.6386 6.91804 21.9186 7.55371 21.3238C7.57941 21.2995 7.60578 21.2758 7.63103 21.251C7.63906 21.2395 7.64591 21.2272 7.65149 21.2143C7.05256 20.6949 6.51739 20.1062 6.05723 19.4606C6.11237 19.4561 6.14925 19.4505 6.18615 19.4505C6.77495 19.4499 7.36377 19.452 7.95254 19.448C7.99171 19.4469 8.03065 19.4544 8.06652 19.4702C8.1024 19.4859 8.13431 19.5095 8.15994 19.5391C8.80004 20.1976 9.54586 20.7444 10.3665 21.1567C11.2347 21.6034 12.1787 21.884 13.1499 21.984C15.7886 22.2405 18.0585 21.4405 19.9595 19.5841C20.002 19.5382 20.0541 19.5021 20.1121 19.4785C20.1701 19.4548 20.2325 19.4442 20.2951 19.4473C20.844 19.4541 21.393 19.4501 21.9419 19.4501H22.0838L22.0936 19.4833Z" fill="#3B3D45"/>
|
||||
<path d="M19.6412 11.0745C19.7972 11.0745 19.9475 11.0851 20.0956 11.0717C20.2633 11.0565 20.3834 11.1165 20.5057 11.2292C21.212 11.88 21.9257 12.5229 22.637 13.1683C22.6728 13.2008 22.7093 13.2324 22.7552 13.273C22.798 13.2362 22.8381 13.2034 22.8764 13.1686C23.6096 12.5012 24.3422 11.8331 25.0743 11.1645C25.1047 11.1332 25.1414 11.1088 25.182 11.0929C25.2226 11.077 25.2662 11.07 25.3097 11.0724C25.49 11.0797 25.6707 11.0745 25.8608 11.0745V16.9751C25.7643 17.0033 24.4678 17.0089 24.313 16.9785V13.9903L24.283 13.976C23.7784 14.4362 23.2738 14.8964 22.7577 15.3671C22.241 14.9017 21.7305 14.4418 21.22 13.9819L21.1906 13.9927C21.1893 14.2421 21.1902 14.4915 21.19 14.7409C21.1899 14.9888 21.1899 15.2367 21.19 15.4846V16.9894H19.654C19.6253 16.8901 19.6119 11.4083 19.6412 11.0745Z" fill="#3B3D45"/>
|
||||
<path d="M5.46747 11.0815H6.99421C7.02504 11.1797 7.03107 16.8479 6.99951 16.9909H5.47141C5.46299 16.6155 5.46875 16.2414 5.4677 15.8675C5.46665 15.4966 5.46747 15.1258 5.46747 14.7453H3.57536V16.9708C3.46003 17.0052 2.15667 17.0085 2.0271 16.9777V11.0822H3.56924V13.1648C3.67944 13.1966 5.30094 13.2025 5.46607 13.172C5.46653 13.0053 5.46719 12.8346 5.46742 12.6638C5.46765 12.4867 5.46767 12.3096 5.46747 12.1325C5.46747 11.9599 5.46747 11.7872 5.46747 11.6145C5.46747 11.4422 5.46747 11.2698 5.46747 11.0815Z" fill="#3B3D45"/>
|
||||
<path d="M8.82422 16.9889V11.0991C8.91477 11.0695 12.2707 11.0579 12.4901 11.0877V12.3429C12.4409 12.3464 12.3901 12.3531 12.3393 12.3532C11.7417 12.354 11.144 12.3541 10.5463 12.3537H10.3801V13.33H12.2476V14.6287H10.3968C10.3659 14.7399 10.3574 15.5145 10.3825 15.7289C10.4298 15.7321 10.4805 15.7384 10.5312 15.7384C11.1289 15.7391 11.7265 15.7393 12.3242 15.7389H12.4905V16.9889H8.82422Z" fill="#3B3D45"/>
|
||||
<path d="M14.2399 16.991C14.2118 16.833 14.2175 11.1893 14.2453 11.082H15.7664V15.4368C15.832 15.4403 15.8835 15.4452 15.935 15.4452C16.5371 15.4458 17.1392 15.4459 17.7413 15.4456C17.7932 15.4456 17.845 15.4456 17.9042 15.4456V16.991L14.2399 16.991Z" fill="#3B3D45"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.7 KiB |
@@ -5,6 +5,9 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Helm Dashboard</title>
|
||||
<link rel="stylesheet"
|
||||
href="https://fonts.googleapis.com/css2?family=Roboto&family=Inter&family=Poppins:wght@600&family=Inter:wght@500&family=Roboto+Slab:wght@400&family=Roboto+Slab:wght@700&family=Roboto:wght@700"/>
|
||||
|
||||
<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://cdn.jsdelivr.net/npm/bootstrap-icons@1.9.1/font/bootstrap-icons.css">
|
||||
@@ -14,186 +17,262 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
<nav class="navbar navbar-expand-lg bg-light rounded mb-2 mt-2">
|
||||
<div class="container-fluid">
|
||||
<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: 0.8rem;">by <a href="https://komodor.io">komodor.io</a></span>
|
||||
<div class="container-fluid gx-0">
|
||||
<!-- TOP BAR -->
|
||||
<nav class="navbar navbar-expand bg-white mb-0 p-0" id="topNav">
|
||||
<div class="container-fluid m-0 p-0">
|
||||
<div class="navbar-brand">
|
||||
<a href="/"><img src="static/logo.png" alt="Logo"></a>
|
||||
<div>
|
||||
<h1><a href="/">Helm Dashboard</a></h1>
|
||||
<p><span class="mr-1">by</span><a href="https://komodor.io"><img src="static/komodor-logo.svg"
|
||||
alt="komodor.io"></a></p>
|
||||
</div>
|
||||
</div>
|
||||
<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="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="/">Installed Charts</a>
|
||||
</li>
|
||||
<!-- TODO
|
||||
<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" style="margin-top: 0.5rem">K8s Context:</label>
|
||||
<select id="cluster" class="form-control"></select>
|
||||
</form>
|
||||
<i class="btn bi-power text-muted" title="Shut down the Helm Dashboard application"></i>
|
||||
</div>
|
||||
<div class="separator-vertical mx-3"><span></span></div>
|
||||
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item mx-2">
|
||||
<a class="nav-link px-3 active" aria-current="page" href="/">Installed</a>
|
||||
</li>
|
||||
<!-- TODO
|
||||
<li class="nav-item mx-2">
|
||||
<a href="#" class="nav-link px-3">Repository</a>
|
||||
</li>
|
||||
-->
|
||||
<!-- TODO
|
||||
<li class="nav-item">
|
||||
<a class="nav-link disabled">Provisional Charts</a>
|
||||
</li>
|
||||
-->
|
||||
</ul>
|
||||
<div class="separator-vertical"><span></span></div>
|
||||
<i class="btn bi-power text-muted p-2 m-1 mx-2" title="Shut down the Helm Dashboard application"></i>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="bg-light p-5 pt-0 rounded display-none" id="sectionDetails">
|
||||
<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">
|
||||
<!-- /TOP BAR -->
|
||||
|
||||
<div class="row mt-3 pt-3 mx-0 me-5" id="sectionList" style="display: none">
|
||||
<div class="col-2 ms-3">
|
||||
<!-- FILTER BLOCK -->
|
||||
<div class="p-2 ps-2 bg-white rounded-1 b-shadow" id="filters">
|
||||
<form>
|
||||
<h4>Clusters</h4>
|
||||
<ul class="list-unstyled" id="cluster">
|
||||
</ul>
|
||||
|
||||
<!-- TODO
|
||||
<h4 class="mt-4">Namespaces</h4>
|
||||
<ul class="list-unstyled" id="namespaces">
|
||||
</ul>
|
||||
-->
|
||||
</form>
|
||||
</div>
|
||||
<!-- /FILTER BLOCK -->
|
||||
|
||||
</div>
|
||||
<h1><span class="name"></span>, revision <span class="rev"></span>
|
||||
<span class="float-end" id="actionButtons">
|
||||
<button id="btnUpgrade" class="opacity-10 btn btn-sm bg-secondary text-light bg-opacity-50 rounded-0 me-0 rounded-start ">Checking...</button><button id="btnUpgradeCheck" class="btn btn-sm text-muted btn-light border-secondary rounded-0 rounded-end ms-0" title="Check for newer chart version from repo"><i class="bi-repeat"></i><span class="spinner-border spinner-border-sm" style="display: none" role="status" aria-hidden="true"></span></button>
|
||||
|
||||
<button id="btnRollback" class="btn btn-sm bg-primary border border-secondary text-light" title="Rollback to this revision"><i class="bi-rewind-fill"></i> <span>Rollback</span></button>
|
||||
<button id="btnUninstall" class="btn btn-sm bg-danger border border-secondary text-light" title="Uninstall the chart"><i class="bi-trash-fill"></i> Uninstall</button>
|
||||
</span>
|
||||
</h1>
|
||||
Chart <b id="chartName"></b>: <i id="revDescr"></i>
|
||||
<!-- INSTALLED LIST -->
|
||||
<div class="col ms-2" id="installedList">
|
||||
<div class="col rounded rounded-1 b-shadow header">
|
||||
<div class="bg-white rounded-top m-0">
|
||||
<h2 class="m-0 p-1"><img class="m-2 mx-3 me-2" src="static/helm-gray.svg" alt="Installed Charts">Installed
|
||||
Charts (<span></span>)</h2>
|
||||
</div>
|
||||
<div class="bg-secondary rounded-bottom m-0 row p-2">
|
||||
<div class="col-4 hdr-name">Name</div>
|
||||
<div class="col-3">Chart Status</div>
|
||||
<div class="col-2">Chart</div>
|
||||
<div class="col-1">Revision</div>
|
||||
<div class="col-1">Namespace</div>
|
||||
<div class="col-1">Updated</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="mt-2">
|
||||
<div class="nav nav-tabs" id="nav-tab" role="tablist">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#nav-resources" data-tab="resources"
|
||||
type="button" role="tab" aria-controls="nav-resources" aria-selected="false">Resources
|
||||
</button>
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#nav-manifest" data-tab="manifests"
|
||||
type="button" role="tab" aria-controls="nav-manifest-diff" aria-selected="false">Manifests
|
||||
</button>
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#nav-manifest" data-tab="values"
|
||||
type="button" role="tab" aria-controls="nav-disabled" aria-selected="false">
|
||||
Parameterized Values
|
||||
</button>
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#nav-manifest" data-tab="notes"
|
||||
type="button" role="tab" aria-controls="nav-disabled" aria-selected="false">Notes
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane p-3" id="nav-resources" role="tabpanel">
|
||||
|
||||
</div>
|
||||
<div class="tab-pane" id="nav-manifest" role="tabpanel">
|
||||
<nav class="navbar bg-light">
|
||||
<form class="container-fluid" id="modePanel">
|
||||
<label class="form-check-label" for="diffModeNone">
|
||||
<input class="form-check-input" type="radio" name="diffMode" id="diffModeNone"
|
||||
data-mode="view">
|
||||
View Current
|
||||
</label>
|
||||
<label class="form-check-label" for="diffModePrev">
|
||||
<input class="form-check-input" type="radio" name="diffMode" id="diffModePrev"
|
||||
data-mode="diff-prev">
|
||||
Diff with previous
|
||||
</label>
|
||||
<label class="form-check-label" for="diffModeRev">
|
||||
<input class="form-check-input" type="radio" name="diffMode" id="diffModeRev"
|
||||
data-mode="diff-rev">
|
||||
Diff with specific revision: <input class="form-input" size="3" id="specRev">
|
||||
</label>
|
||||
<label class="form-check-label" for="userDefinedVals">
|
||||
<input class="form-check-input" type="checkbox" id="userDefinedVals"> User-defined only
|
||||
</label>
|
||||
</form>
|
||||
</nav>
|
||||
|
||||
<div id="manifestText" class="mt-2 bg-white"></div>
|
||||
</div>
|
||||
<div class="tab-pane" id="nav-disabled" role="tabpanel" aria-labelledby="nav-disabled-tab"
|
||||
tabindex="0">...
|
||||
</div>
|
||||
<div class="body"></div>
|
||||
</div>
|
||||
<!-- /INSTALLED LIST -->
|
||||
</div>
|
||||
|
||||
<div class="bg-light p-5 rounded display-none" id="sectionList">
|
||||
<h1>Charts List</h1>
|
||||
<div id="charts" class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
|
||||
|
||||
<div class="row pt-0 mx-0 me-0" id="sectionDetails" style="display: none">
|
||||
<div class="col-2 ms-3 ps-1 pt-4 rev-list">
|
||||
<h3 class="fw-bold small">Revisions</h3>
|
||||
<ul class="list-unstyled">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col ms-2 rev-details bg-white b-shadow pt-4 px-5">
|
||||
<div><span class="rev-status fw-bold me-3"></span></div>
|
||||
<div>
|
||||
<h1 class="name float-start">Name</h1>
|
||||
<div id="actionButtons" class="float-end">
|
||||
<span><button id="btnUpgrade"
|
||||
class="opacity-10 btn btn-sm btn-light bg-white rounded-0 me-0 rounded-start border-secondary">
|
||||
<img src="static/action.svg"> <span>Checking...</span>
|
||||
</button></span><span><button
|
||||
id="btnUpgradeCheck"
|
||||
class="btn btn-sm text-muted btn-light bg-white border-secondary rounded-0 rounded-end ms-0 me-2"
|
||||
title="Check for newer chart version from repo"><i class="bi-repeat"></i><span
|
||||
class="spinner-border spinner-border-sm" style="display: none" role="status"
|
||||
aria-hidden="true"></span></button></span>
|
||||
|
||||
<div id="errorAlert" class="display-none alert alert-sm alert-danger alert-dismissible position-absolute position-absolute top-0 start-50 translate-middle-x mt-3 border-danger" role="alert">
|
||||
<h4 class="alert-heading"><i class="bi-exclamation-triangle-fill"></i> <span></span></h4>
|
||||
<hr>
|
||||
<p style="white-space: pre-wrap"></p>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" id="describeModal"
|
||||
tabindex="-1" aria-labelledby="describeModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog modal-dialog-scrollable modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="describeModalLabel"></h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<button id="btnRollback" class="btn btn-sm btn-light bg-white border border-secondary me-2"
|
||||
title="Rollback to this revision"><img src="static/action.svg"> <span>Rollback</span>
|
||||
</button>
|
||||
<button id="btnUninstall" class="btn btn-sm btn-light bg-white border border-secondary"
|
||||
title="Uninstall the chart"><img src="static/action.svg"> Uninstall
|
||||
</button>
|
||||
</div>
|
||||
<div class="fs-2"> </div>
|
||||
</div>
|
||||
<div class="modal-body" id="describeModalBody">
|
||||
|
||||
<div>
|
||||
Revision <span class="rev fw-bold me-4"></span>
|
||||
Upgraded on <span class="rev-date"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" id="confirmModal"
|
||||
tabindex="-1" aria-labelledby="describeModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog modal-dialog-scrollable modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="confirmModalLabel"></h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<div class="rev-tags mt-3">
|
||||
<span class="rounded rounded-1 me-2 p-1 px-2 bg-tag text-dark">namespace: <span
|
||||
class="rev-ns fw-bold"></span></span>
|
||||
<span class="rounded rounded-1 me-2 p-1 px-2 bg-tag text-dark">chart version: <span
|
||||
class="rev-chart fw-bold"></span></span>
|
||||
<span class="rounded rounded-1 me-2 p-1 px-2 bg-tag text-dark">app version: <span
|
||||
class="rev-app fw-bold"></span></span>
|
||||
</div>
|
||||
<div class="modal-body" id="confirmModalBody">
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary">Confirm</button>
|
||||
<div id="revDescr" class="mt-3 mb-4"></div>
|
||||
|
||||
<nav class="mt-2">
|
||||
<div class="nav nav-tabs" id="nav-tab" role="tablist">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#nav-resources" data-tab="resources"
|
||||
type="button" role="tab" aria-controls="nav-resources" aria-selected="false" tabindex="-1">
|
||||
Resources
|
||||
</button>
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#nav-manifest" data-tab="manifests"
|
||||
type="button" role="tab" aria-controls="nav-manifest-diff" aria-selected="false"
|
||||
tabindex="-1">Manifests
|
||||
</button>
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#nav-manifest" data-tab="values"
|
||||
type="button" role="tab" aria-controls="nav-disabled" aria-selected="false" tabindex="-1">
|
||||
Parameterized Values
|
||||
</button>
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#nav-manifest" data-tab="notes"
|
||||
type="button" role="tab" aria-controls="nav-disabled" aria-selected="false" tabindex="-1">
|
||||
Notes
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane p-3 container-fluid" id="nav-resources" role="tabpanel">
|
||||
<div class="row bg-secondary rounded px-3 py-2 mb-2 fw-bold small"
|
||||
style="text-transform: uppercase">
|
||||
<div class="col-2">Kind</div>
|
||||
<div class="col-4">Name</div>
|
||||
<div class="col-5">Status</div>
|
||||
<div class="col-1">Describe</div>
|
||||
</div>
|
||||
<div class="body"></div>
|
||||
</div>
|
||||
<div class="tab-pane" id="nav-manifest" role="tabpanel">
|
||||
<nav class="navbar bg-light">
|
||||
<form class="container-fluid" id="modePanel">
|
||||
<label class="form-check-label" for="diffModeNone">
|
||||
<input class="form-check-input" type="radio" name="diffMode" id="diffModeNone"
|
||||
data-mode="view">
|
||||
View Current
|
||||
</label>
|
||||
<label class="form-check-label" for="diffModePrev">
|
||||
<input class="form-check-input" type="radio" name="diffMode" id="diffModePrev"
|
||||
data-mode="diff-prev">
|
||||
Diff with previous
|
||||
</label>
|
||||
<label class="form-check-label" for="diffModeRev">
|
||||
<input class="form-check-input" type="radio" name="diffMode" id="diffModeRev"
|
||||
data-mode="diff-rev">
|
||||
Diff with specific revision: <input class="form-input" size="3" id="specRev">
|
||||
</label>
|
||||
<label class="form-check-label" for="userDefinedVals">
|
||||
<input class="form-check-input" type="checkbox" id="userDefinedVals"> User-defined only
|
||||
</label>
|
||||
</form>
|
||||
</nav>
|
||||
|
||||
<div id="manifestText" class="mt-2 bg-white"></div>
|
||||
</div>
|
||||
<div class="tab-pane" id="nav-disabled" role="tabpanel" aria-labelledby="nav-disabled-tab"
|
||||
tabindex="0">...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal" id="upgradeModal"
|
||||
tabindex="-1" aria-labelledby="describeModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog modal-dialog-scrollable modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="upgradeModalLabel">
|
||||
Upgrade <b class='text-success name'></b> from version <b class='text-success ver-old'></b> to <select class='fw-bold text-success ver-new'></select>
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body" id="upgradeModalBody">
|
||||
<!-- Modals -->
|
||||
<div id="errorAlert"
|
||||
class="display-none alert alert-sm alert-danger alert-dismissible position-absolute position-absolute top-0 start-50 translate-middle-x mt-3 border-danger"
|
||||
role="alert">
|
||||
<h4 class="alert-heading"><i class="bi-exclamation-triangle-fill"></i> <span></span></h4>
|
||||
<hr>
|
||||
<p style="white-space: pre-wrap"></p>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-success">Confirm Upgrade</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="offcanvas offcanvas-end rounded-start" tabindex="-1" id="describeModal"
|
||||
aria-labelledby="describeModalLabel">
|
||||
<div class="offcanvas-header">
|
||||
<h5 id="describeModalLabel"></h5>
|
||||
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body" id="describeModalBody">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<footer class="text-center small mt-3">
|
||||
Brought to you by <img src="https://komodor.com/wp-content/uploads/2021/05/favicon.png" style="height: 1rem"> <a href="https://komodor.io">Komodor.io</a> |
|
||||
<i class="bi-github"></i>
|
||||
<a href="https://github.com/komodorio/helm-dashboard">Project page on GitHub</a>
|
||||
<div class="offcanvas offcanvas-end rounded-start" tabindex="-1" id="confirmModal" aria-labelledby="confirmModalLabel">
|
||||
<div class="offcanvas-header">
|
||||
<h5 id="confirmModalLabel"></h5>
|
||||
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body" id="confirmModalBody">
|
||||
</div>
|
||||
<div class="offcanvas-footer p-3">
|
||||
<button type="button" class="btn btn-primary float-end btn-confirm">Confirm</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="offcanvas offcanvas-end rounded-start" tabindex="-1" id="upgradeModal" aria-labelledby="upgradeModalLabel">
|
||||
<div class="offcanvas-header">
|
||||
<h5 id="upgradeModalLabel">
|
||||
Upgrade <b class='text-success name'></b> from version <b class='text-success ver-old'></b> to
|
||||
<select class='fw-bold text-success ver-new'></select>
|
||||
</h5>
|
||||
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body" id="upgradeModalBody">
|
||||
</div>
|
||||
<div class="offcanvas-footer p-3">
|
||||
<button type="button" class="btn btn-primary float-end btn-confirm">Confirm Upgrade</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="container-fluid small mt-3" style="z-index: -50">
|
||||
<div class="row align-items-end justify-content-end">
|
||||
<div class="col-3"></div>
|
||||
<div class="col-4 text-center bg-white bg-opacity-50 p-2 px-3 rounded b-shadow">
|
||||
Brought to you by <img src="https://komodor.com/wp-content/uploads/2021/05/favicon.png"
|
||||
style="height: 1rem"> <a class="me-4"
|
||||
href="https://komodor.io">Komodor.io</a>
|
||||
<i class="bi-github"></i>
|
||||
<a href="https://github.com/komodorio/helm-dashboard">Project page on GitHub</a>
|
||||
</div>
|
||||
<div class="col-3"></div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<img src="static/topographic.svg" class="position-absolute bottom-0 left-0" style="z-index: -100; height: 100%;"/>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa"
|
||||
@@ -207,6 +286,11 @@
|
||||
integrity="sha256-0H3Nuz3aug3afVbUlsu12Puxva3CP4EhJtPExqs54Vg=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/luxon@3.0.3/build/global/luxon.min.js"
|
||||
integrity="sha256-RH4TKnKcKyde0s2jc5BW3pXZl/5annY3fcZI9VrV5WQ=" crossorigin="anonymous"></script>
|
||||
<script src="static/list-view.js"></script>
|
||||
<script src="static/revisions-view.js"></script>
|
||||
<script src="static/details-view.js"></script>
|
||||
<script src="static/actions.js"></script>
|
||||
<script src="static/scripts.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
16
pkg/dashboard/static/komodor-logo.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<svg width="53" height="13" viewBox="0 0 53 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_36_1097)">
|
||||
<path d="M5.86295 4.90639H4.0672L1.355 7.52039V2.1665H0V11.0071H1.355V8.93513L2.42853 7.98768L4.57123 11.0071H6.23823L3.39732 7.11706L5.86295 4.90639Z" fill="#1347FF"/>
|
||||
<path d="M19.4109 4.90652L18.7279 5.58935L18.0559 4.90652H15.6142L14.8004 5.74086V4.90652H13.5217V11.0073H14.8789V6.73737L15.6011 6.01827H17.1634L17.5387 6.38531V11.0073H18.8959V6.49839L19.3847 6.01827H21.1804L21.5557 6.38531V11.0073H22.9108V5.99267L21.8263 4.90652H19.4109Z" fill="#1347FF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.46283 5.99267L7.54726 4.90652H11.2544L12.3389 5.99267V9.92112L11.2544 11.0073H7.54726L6.46283 9.92112V5.99267ZM10.6086 9.89549L10.9708 9.52848H10.973V6.38531L10.6107 6.01827H8.19531L7.8331 6.38531V9.52848L8.19315 9.89549H10.6086Z" fill="#1347FF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M43.2791 4.90652L42.1947 5.99267V9.92112L43.2791 11.0073H46.9863L48.0707 9.92112V5.99267L46.9863 4.90652H43.2791ZM46.7028 9.52848L46.3405 9.89549H43.9252L43.5629 9.52848V6.38531L43.9252 6.01827H46.3405L46.7028 6.38531V9.52848Z" fill="#1347FF"/>
|
||||
<path d="M50.5323 5.81555L51.4355 4.90652H53.0002V6.16979H51.3332L50.6108 6.8782V11.0073H49.2536V4.90652H50.5323V5.81555Z" fill="#1347FF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M25.0906 4.90652L24.0061 5.99267V9.92112L25.0906 11.0073H33.1027L34.1871 9.92112V5.99267L33.1027 4.90652H25.0906ZM32.817 9.52848L32.4547 9.89549H25.7343L25.3721 9.52848V6.38531L25.7343 6.01827H32.4547L32.817 6.38531V9.52848Z" fill="#1347FF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M38.895 4.90639L39.6437 5.66392V2.1665H40.9984V11.0071H39.6437V10.2624L38.895 11.0071H36.3116L35.2272 9.92098V5.99252L36.3116 4.90639H38.895ZM38.9213 9.89538L39.6437 9.18905V6.73725L38.9213 6.01813H36.9577L36.5823 6.38516V9.52834L36.9577 9.89538H38.9213Z" fill="#1347FF"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_36_1097">
|
||||
<rect width="53" height="13" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
50
pkg/dashboard/static/list-view.js
Normal file
@@ -0,0 +1,50 @@
|
||||
function loadChartsList() {
|
||||
$("#sectionList").show()
|
||||
const chartsCards = $("#installedList .body")
|
||||
chartsCards.empty().append("<div><span class=\"spinner-border spinner-border-sm\" role=\"status\" aria-hidden=\"true\"></span> Loading...</div>")
|
||||
$.getJSON("/api/helm/charts").fail(function (xhr) {
|
||||
reportError("Failed to get list of charts", xhr)
|
||||
}).done(function (data) {
|
||||
chartsCards.empty()
|
||||
$("#installedList .header h2 span").text(data.length)
|
||||
data.forEach(function (elm) {
|
||||
let card = buildChartCard(elm);
|
||||
chartsCards.append(card)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function buildChartCard(elm) {
|
||||
const card = $(`<div class="row m-0 py-3 bg-white rounded-1 b-shadow border-4 border-start">
|
||||
<div class="col-4 rel-name"><span class="link">release-name</span><div></div></div>
|
||||
<div class="col-3 rel-status"><span></span><div></div></div>
|
||||
<div class="col-2 rel-chart text-nowrap"><span></span><div>Chart Version</div></div>
|
||||
<div class="col-1 rel-rev"><span>#0</span><div>Revision</div></div>
|
||||
<div class="col-1 rel-ns text-nowrap"><span>default</span><div>Namespace</div></div>
|
||||
<div class="col-1 rel-date text-nowrap"><span>today</span><div>Updated</div></div>
|
||||
</div>`)
|
||||
|
||||
card.find(".rel-name span").text(elm.name)
|
||||
card.find(".rel-rev span").text("#" + elm.revision)
|
||||
card.find(".rel-ns span").text(elm.namespace)
|
||||
card.find(".rel-chart span").text(elm.chart)
|
||||
card.find(".rel-date span").text(getAge(elm))
|
||||
|
||||
statusStyle(elm.status, card, card.find(".rel-status span"))
|
||||
|
||||
card.find("a").attr("href", '#namespace=' + elm.namespace + '&name=' + elm.name)
|
||||
|
||||
card.find(".rel-name span").data("chart", elm).click(function () {
|
||||
const self = $(this)
|
||||
$("#sectionList").hide()
|
||||
|
||||
let chart = self.data("chart");
|
||||
setHashParam("namespace", chart.namespace)
|
||||
setHashParam("chart", chart.name)
|
||||
|
||||
loadChartHistory(chart.namespace, chart.name, elm.chart_name)
|
||||
})
|
||||
return card;
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 17 KiB |
49
pkg/dashboard/static/logo.svg
Normal file
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="32"
|
||||
height="37"
|
||||
viewBox="0 0 32 37"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="logo.svg"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="34.810811"
|
||||
inkscape:cx="13.228649"
|
||||
inkscape:cy="17.552019"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2059"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<rect
|
||||
style="opacity:0.455635;fill:#ffffff;stroke-width:18.0094;fill-opacity:1"
|
||||
id="rect1031"
|
||||
width="17.224331"
|
||||
height="10.929513"
|
||||
x="7.3572245"
|
||||
y="12.500892"
|
||||
ry="0" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M18 5V2.29761C18 1.02617 17.1002 0 15.9958 0C14.8915 0 14 1.03576 14 2.29761V5H18ZM28.8285 11.364L30.7394 9.45308C31.6384 8.55404 31.7278 7.19222 30.9469 6.4113C30.166 5.63038 28.8032 5.73239 27.9109 6.62466L26.0001 8.53553L28.8285 11.364ZM1.62465 9.45308L3.53553 11.364L6.36396 8.53553L4.45308 6.62466C3.56081 5.73239 2.19804 5.63038 1.41712 6.4113C0.636208 7.19222 0.72561 8.55404 1.62465 9.45308ZM6 12.8164L7.78385 11H24.2163L26 12.8085V23.1915L24.2163 25H7.78372L6 23.1915V12.8164ZM8.94831 12.977L8.25128 13.6683V22.3438L8.94831 23.0351H23.0733L23.7446 22.3426V13.6694L23.0733 12.977H8.94831ZM20.1736 17.4485C20.1736 18.7679 19.4222 19.8375 18.4953 19.8375C17.5684 19.8375 16.817 18.7679 16.817 17.4485C16.817 16.1291 17.5684 15.0595 18.4953 15.0595C19.4222 15.0595 20.1736 16.1291 20.1736 17.4485ZM13.5045 19.8375C14.4314 19.8375 15.1828 18.7679 15.1828 17.4485C15.1828 16.1291 14.4314 15.0595 13.5045 15.0595C12.5776 15.0595 11.8262 16.1291 11.8262 17.4485C11.8262 18.7679 12.5776 19.8375 13.5045 19.8375ZM14.3641 34.0662V31.3638H18.3641V34.0662C18.3641 35.328 17.4726 36.3638 16.3682 36.3638C15.2638 36.3638 14.3641 35.3376 14.3641 34.0662ZM1.62465 26.9107L3.53553 24.9998L6.36396 27.8282L4.45308 29.7391C3.56081 30.6314 2.19804 30.7334 1.41712 29.9525C0.636204 29.1716 0.725608 27.8097 1.62465 26.9107ZM28.8285 24.9998L30.7394 26.9107C31.6384 27.8097 31.7278 29.1716 30.9469 29.9525C30.166 30.7334 28.8032 30.6314 27.9109 29.7391L26.0001 27.8282L28.8285 24.9998Z"
|
||||
fill="#1347FF"
|
||||
id="path2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
63
pkg/dashboard/static/revisions-view.js
Normal file
@@ -0,0 +1,63 @@
|
||||
const revRow = $("#sectionDetails .rev-list ul");
|
||||
|
||||
function loadChartHistory(namespace, name) {
|
||||
$("#sectionDetails").show()
|
||||
$("#sectionDetails .name").text(name)
|
||||
revRow.empty().append("<li><span class=\"spinner-border spinner-border-sm\" role=\"status\" aria-hidden=\"true\"></span></li>")
|
||||
$.getJSON("/api/helm/charts/history?name=" + name + "&namespace=" + namespace).fail(function (xhr) {
|
||||
reportError("Failed to get chart details", xhr)
|
||||
}).done(function (data) {
|
||||
fillChartHistory(data, namespace, name);
|
||||
|
||||
checkUpgradeable(data[data.length - 1].chart_name)
|
||||
|
||||
const rev = getHashParam("revision")
|
||||
if (rev) {
|
||||
revRow.find(".rev-" + rev).click()
|
||||
} else {
|
||||
revRow.find("li:first-child").click()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function fillChartHistory(data, namespace, name) {
|
||||
revRow.empty()
|
||||
data.reverse()
|
||||
for (let x = 0; x < data.length; x++) {
|
||||
const elm = data[x]
|
||||
$("#specRev").val(elm.revision).data("first-rev", elm.revision)
|
||||
|
||||
if (!x) {
|
||||
$("#specRev").data("last-rev", elm.revision).data("last-chart-ver", elm.chart_ver)
|
||||
}
|
||||
|
||||
const rev = $(`<li class="px-2 pt-5 pb-4 mb-2 rounded border border-secondary bg-secondary position-relative">
|
||||
<div class="rev-status position-absolute top-0 m-2 mb-5 start-0 fw-bold"></div>
|
||||
<div class="rev-number position-absolute top-0 m-2 mb-5 end-0 fw-bold fs-6"></div>
|
||||
<div class="rev-changes position-absolute bottom-0 start-0 m-2 text-muted small"></div>
|
||||
<div class="position-absolute bottom-0 end-0 m-2 text-muted small">AGE: <span class="rev-age"></span></div>
|
||||
</li>`)
|
||||
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-age").text(getAge(elm, data[x - 1])).parent().attr("title", elm.updated)
|
||||
statusStyle(elm.status, rev.find(".rev-status"), rev.find(".rev-status"))
|
||||
|
||||
const nxt = data[x + 1];
|
||||
if (nxt && isNewerVersion(elm.chart_ver, nxt.chart_ver)) {
|
||||
rev.find(".rev-changes").html("<span class='strike'>" + nxt.chart_ver + "</span> <i class='text-danger bi-arrow-down-right'></i> " + elm.chart_ver)
|
||||
} else if (nxt && isNewerVersion(nxt.chart_ver, elm.chart_ver)) {
|
||||
rev.find(".rev-changes").html("<span class='strike'>" + nxt.chart_ver + "</span> <i class='text-success bi-arrow-up-right'></i> " + elm.chart_ver)
|
||||
}
|
||||
|
||||
rev.data("elm", elm)
|
||||
rev.addClass("rev-" + elm.revision)
|
||||
rev.click(function () {
|
||||
revisionClicked(namespace, name, $(this))
|
||||
})
|
||||
|
||||
revRow.append(rev)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,26 @@
|
||||
const clusterSelect = $("#cluster");
|
||||
const chartsCards = $("#charts");
|
||||
const revRow = $("#sectionDetails .row");
|
||||
$(function () {
|
||||
const clusterSelect = $("#cluster");
|
||||
clusterSelect.change(function () {
|
||||
Cookies.set("context", clusterSelect.find("input:radio:checked").val())
|
||||
window.location.href = "/"
|
||||
})
|
||||
|
||||
$.getJSON("/api/kube/contexts").fail(function (xhr) {
|
||||
reportError("Failed to get list of clusters", xhr)
|
||||
}).done(function (data) {
|
||||
const context = Cookies.get("context")
|
||||
fillClusterList(data, context);
|
||||
|
||||
const namespace = getHashParam("namespace")
|
||||
const chart = getHashParam("chart")
|
||||
if (!chart) {
|
||||
loadChartsList()
|
||||
} else {
|
||||
loadChartHistory(namespace, chart)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
function reportError(err, xhr) {
|
||||
$("#errorAlert h4 span").text(err)
|
||||
@@ -10,322 +30,7 @@ function reportError(err, xhr) {
|
||||
$("#errorAlert").show()
|
||||
}
|
||||
|
||||
function revisionClicked(namespace, name, self) {
|
||||
let active = "active border-primary border-2 bg-opacity-25 bg-primary";
|
||||
let inactive = "border-secondary bg-white";
|
||||
revRow.find(".active").removeClass(active).addClass(inactive)
|
||||
self.removeClass(inactive).addClass(active)
|
||||
const elm = self.data("elm")
|
||||
setHashParam("revision", elm.revision)
|
||||
$("#sectionDetails h1 span.rev").text(elm.revision)
|
||||
$("#chartName").text(elm.chart)
|
||||
$("#revDescr").text(elm.description).removeClass("text-danger")
|
||||
if (elm.status === "failed") {
|
||||
$("#revDescr").addClass("text-danger")
|
||||
}
|
||||
|
||||
const rev = $("#specRev").data("last-rev") == elm.revision ? elm.revision - 1 : elm.revision
|
||||
console.log(rev, $("#specRev").data("first-rev"))
|
||||
if (!rev || getHashParam("revision") === $("#specRev").data("first-rev")) {
|
||||
$("#btnRollback").hide()
|
||||
} else {
|
||||
$("#btnRollback").show().data("rev", rev).find("span").text("Rollback to #" + rev)
|
||||
}
|
||||
|
||||
const tab = getHashParam("tab")
|
||||
if (!tab) {
|
||||
$("#nav-tab [data-tab=resources]").click()
|
||||
} else {
|
||||
$("#nav-tab [data-tab=" + tab + "]").click()
|
||||
}
|
||||
}
|
||||
|
||||
$("#nav-tab [data-tab]").click(function () {
|
||||
const self = $(this)
|
||||
setHashParam("tab", self.data("tab"))
|
||||
|
||||
if (self.data("tab") === "values") {
|
||||
$("#userDefinedVals").parent().show()
|
||||
} else {
|
||||
$("#userDefinedVals").parent().hide()
|
||||
}
|
||||
|
||||
const flag = getHashParam("udv") === "true";
|
||||
$("#userDefinedVals").prop("checked", flag)
|
||||
|
||||
if (self.data("tab") === "resources") {
|
||||
showResources(getHashParam("namespace"), getHashParam("chart"), getHashParam("revision"))
|
||||
} else {
|
||||
const mode = getHashParam("mode")
|
||||
if (!mode) {
|
||||
$("#modePanel [data-mode=view]").trigger('click')
|
||||
} else {
|
||||
$("#modePanel [data-mode=" + mode + "]").trigger('click')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
$("#modePanel [data-mode]").click(function () {
|
||||
const self = $(this)
|
||||
const mode = self.data("mode")
|
||||
setHashParam("mode", mode)
|
||||
loadContentWrapper()
|
||||
})
|
||||
|
||||
|
||||
$("#userDefinedVals").change(function () {
|
||||
const self = $(this)
|
||||
const flag = $("#userDefinedVals").prop("checked");
|
||||
setHashParam("udv", flag)
|
||||
loadContentWrapper()
|
||||
})
|
||||
|
||||
function loadContentWrapper() {
|
||||
let revDiff = 0
|
||||
const revision = parseInt(getHashParam("revision"));
|
||||
if (revision === $("#specRev").data("first-rev")) {
|
||||
revDiff = 0
|
||||
} else if (getHashParam("mode") === "diff-prev") {
|
||||
revDiff = revision - 1
|
||||
} else if (getHashParam("mode") === "diff-rev") {
|
||||
revDiff = $("#specRev").val()
|
||||
}
|
||||
|
||||
const flag = $("#userDefinedVals").prop("checked");
|
||||
loadContent(getHashParam("tab"), getHashParam("namespace"), getHashParam("chart"), revision, revDiff, flag)
|
||||
}
|
||||
|
||||
function loadContent(mode, namespace, name, revision, revDiff, flag) {
|
||||
let qstr = "name=" + name + "&namespace=" + namespace + "&revision=" + revision
|
||||
if (revDiff) {
|
||||
qstr += "&revisionDiff=" + revDiff
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
qstr += "&flag=" + flag
|
||||
}
|
||||
|
||||
let url = "/api/helm/charts/" + mode
|
||||
url += "?" + qstr
|
||||
const diffDisplay = $("#manifestText");
|
||||
diffDisplay.empty().append('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>')
|
||||
$.get(url).fail(function (xhr) {
|
||||
reportError("Failed to get diff of " + mode, xhr)
|
||||
}).done(function (data) {
|
||||
diffDisplay.empty();
|
||||
if (data === "") {
|
||||
diffDisplay.text("No differences to display")
|
||||
} else {
|
||||
if (revDiff) {
|
||||
const targetElement = document.getElementById('manifestText');
|
||||
const configuration = {
|
||||
inputFormat: 'diff', outputFormat: 'side-by-side',
|
||||
|
||||
drawFileList: false, showFiles: false, highlight: true, //matching: 'lines',
|
||||
};
|
||||
const diff2htmlUi = new Diff2HtmlUI(targetElement, data, configuration);
|
||||
diff2htmlUi.draw()
|
||||
} else {
|
||||
data = hljs.highlight(data, {language: 'yaml'}).value
|
||||
const code = $("#manifestText").empty().append("<pre class='bg-white rounded p-3'></pre>").find("pre");
|
||||
code.html(data)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
$('#specRev').keyup(function (event) {
|
||||
let keycode = (event.keyCode ? event.keyCode : event.which);
|
||||
if (keycode == '13') {
|
||||
$("#diffModeRev").click()
|
||||
}
|
||||
event.preventDefault()
|
||||
});
|
||||
|
||||
function fillChartHistory(data, namespace, name) {
|
||||
revRow.empty()
|
||||
for (let x = 0; x < data.length; x++) {
|
||||
const elm = data[x]
|
||||
$("#specRev").val(elm.revision).data("last-rev", elm.revision).data("last-chart-ver", elm.chart_ver)
|
||||
|
||||
if (!x) {
|
||||
$("#specRev").data("first-rev", elm.revision)
|
||||
}
|
||||
|
||||
const rev = $(`<div class="col-md-2 p-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 ver:</span> <span class="app-ver"></span><br/>
|
||||
<p class="small mt-3 mb-0"><span class="text-muted">Age:</span> <span class="rev-age"></span><br/>
|
||||
<span class="text-muted rev-date"></span><br/></p>
|
||||
</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-age").text(getAge(elm, data[x + 1]))
|
||||
rev.find(".rev-status").text(elm.status)
|
||||
rev.find(".fa").attr("title", elm.action)
|
||||
|
||||
if (elm.status === "failed") {
|
||||
rev.find(".rev-status").parent().addClass("text-danger")
|
||||
}
|
||||
|
||||
switch (elm.action) {
|
||||
case "app_upgrade":
|
||||
rev.find(".app-ver").append(" <i class='bi-chevron-double-up text-success'></i>")
|
||||
break
|
||||
case "app_downgrade":
|
||||
rev.find(".app-ver").append(" <i class='bi-chevron-double-down text-danger'></i>")
|
||||
break
|
||||
case "chart_upgrade":
|
||||
rev.find(".chart-ver").append(" <i class='bi-chevron-up text-success'></i>")
|
||||
break
|
||||
case "chart_downgrade":
|
||||
rev.find(".chart-ver").append(" <i class='bi-chevron-down text-danger'></i>")
|
||||
break
|
||||
case "reconfigure": // ?
|
||||
break
|
||||
}
|
||||
|
||||
rev.data("elm", elm)
|
||||
rev.addClass("rev-" + elm.revision)
|
||||
rev.click(function () {
|
||||
revisionClicked(namespace, name, $(this))
|
||||
})
|
||||
|
||||
revRow.append(rev)
|
||||
}
|
||||
}
|
||||
|
||||
function loadChartHistory(namespace, name) {
|
||||
$("#sectionDetails").show()
|
||||
$("#sectionDetails h1 span.name").text(name)
|
||||
revRow.empty().append("<div><span class=\"spinner-border spinner-border-sm\" role=\"status\" aria-hidden=\"true\"></span></div>")
|
||||
$.getJSON("/api/helm/charts/history?name=" + name + "&namespace=" + namespace).fail(function (xhr) {
|
||||
reportError("Failed to get chart details", xhr)
|
||||
}).done(function (data) {
|
||||
fillChartHistory(data, namespace, name);
|
||||
|
||||
checkUpgradeable(data[data.length - 1].chart_name)
|
||||
|
||||
const rev = getHashParam("revision")
|
||||
if (rev) {
|
||||
revRow.find(".rev-" + rev).click()
|
||||
} else {
|
||||
revRow.find("div.col-md-2:last-child").click()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
$("#btnUpgradeCheck").click(function () {
|
||||
const self = $(this)
|
||||
self.find(".bi-repeat").hide()
|
||||
self.find(".spinner-border").show()
|
||||
const repoName = self.data("repo")
|
||||
$("#btnUpgrade").text("Checking...")
|
||||
$.post("/api/helm/repo/update?name=" + repoName).fail(function (xhr) {
|
||||
reportError("Failed to update chart repo", xhr)
|
||||
}).done(function () {
|
||||
self.find(".spinner-border").hide()
|
||||
self.find(".bi-repeat").show()
|
||||
|
||||
checkUpgradeable(self.data("chart"))
|
||||
$("#btnUpgradeCheck").prop("disabled", true).find(".fa").removeClass("fa-spin fa-spinner").addClass("fa-times")
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
function checkUpgradeable(name) {
|
||||
$.getJSON("/api/helm/repo/search?name=" + name).fail(function (xhr) {
|
||||
reportError("Failed to find chart in repo", xhr)
|
||||
}).done(function (data) {
|
||||
if (!data) {
|
||||
return
|
||||
}
|
||||
|
||||
$('#upgradeModalLabel select').empty()
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
$('#upgradeModalLabel select').append("<option value='" + data[i].version + "'>" + data[i].version + "</option>")
|
||||
}
|
||||
|
||||
const elm = data[0]
|
||||
$("#btnUpgradeCheck").data("repo", elm.name.split('/').shift())
|
||||
$("#btnUpgradeCheck").data("chart", elm.name.split('/').pop())
|
||||
|
||||
const verCur = $("#specRev").data("last-chart-ver");
|
||||
const canUpgrade = isNewerVersion(verCur, elm.version);
|
||||
$("#btnUpgradeCheck").prop("disabled", false)
|
||||
if (canUpgrade) {
|
||||
$("#btnUpgrade").removeClass("bg-secondary bg-opacity-50").addClass("bg-success").text("Upgrade to " + elm.version)
|
||||
} else {
|
||||
$("#btnUpgrade").removeClass("bg-success").addClass("bg-secondary bg-opacity-50").text("No upgrades")
|
||||
}
|
||||
|
||||
$("#btnUpgrade").off("click").click(function () {
|
||||
popUpUpgrade($(this), verCur, elm)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
$('#upgradeModalLabel select').change(function () {
|
||||
const self = $(this)
|
||||
|
||||
$("#upgradeModalBody").empty().append('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>')
|
||||
$("#upgradeModal .btn-success").prop("disabled", true)
|
||||
$.get(self.data("url") + "&version=" + self.val()).fail(function (xhr) {
|
||||
reportError("Failed to get upgrade", xhr)
|
||||
}).done(function (data) {
|
||||
$("#upgradeModalBody").empty();
|
||||
$("#upgradeModal .btn-success").prop("disabled", false)
|
||||
|
||||
const targetElement = document.getElementById('upgradeModalBody');
|
||||
const configuration = {
|
||||
inputFormat: 'diff', outputFormat: 'side-by-side',
|
||||
drawFileList: false, showFiles: false, highlight: true,
|
||||
};
|
||||
const diff2htmlUi = new Diff2HtmlUI(targetElement, data, configuration);
|
||||
diff2htmlUi.draw()
|
||||
$("#upgradeModalBody").prepend("<p>Following changes will happen to cluster:</p>")
|
||||
if (!data) {
|
||||
$("#upgradeModalBody").html("No changes will happen to cluster")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
$("#upgradeModal .btn-secondary").click(function () {
|
||||
const self = $(this)
|
||||
self.find(".fa").removeClass("fa-cloud-download").addClass("fa-spin fa-spinner").prop("disabled", true)
|
||||
$("#btnUpgradeCheck").click()
|
||||
$("#upgradeModal .btn-close").click()
|
||||
})
|
||||
|
||||
function popUpUpgrade(self, verCur, elm) {
|
||||
const name = getHashParam("chart");
|
||||
let url = "/api/helm/charts/install?namespace=" + getHashParam("namespace") + "&name=" + name + "&chart=" + elm.name;
|
||||
$('#upgradeModalLabel select').data("url", url)
|
||||
|
||||
$("#upgradeModalLabel .name").text(name)
|
||||
$("#upgradeModalLabel .ver-old").text(verCur)
|
||||
|
||||
$('#upgradeModalLabel select').val(elm.version).trigger("change")
|
||||
|
||||
const myModal = new bootstrap.Modal(document.getElementById('upgradeModal'), {});
|
||||
myModal.show()
|
||||
|
||||
$("#upgradeModal .btn-success").prop("disabled", true).off('click').click(function () {
|
||||
$("#upgradeModal .btn-success").prop("disabled", true).prepend('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>')
|
||||
$.ajax({
|
||||
url: url + "&version=" + $('#upgradeModalLabel select').val(),
|
||||
type: 'POST',
|
||||
}).fail(function (xhr) {
|
||||
reportError("Failed to upgrade the chart", xhr)
|
||||
}).done(function (data) {
|
||||
setHashParam("revision", data.version)
|
||||
window.location.reload()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function getHashParam(name) {
|
||||
const params = new URLSearchParams(window.location.hash.substring(1))
|
||||
@@ -338,95 +43,49 @@ function setHashParam(name, val) {
|
||||
window.location.hash = new URLSearchParams(params).toString()
|
||||
}
|
||||
|
||||
function buildChartCard(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")
|
||||
function statusStyle(status, card, txt) {
|
||||
txt.addClass("text-uppercase")
|
||||
txt.html("<span class='fs-6'>●</span> " + status)
|
||||
txt.removeClass("text-failed text-deployed text-pending text-other")
|
||||
if (status === "failed") {
|
||||
card.addClass("border-failed")
|
||||
txt.addClass("text-failed")
|
||||
// TODO: add failure description here
|
||||
} else if (status === "deployed") {
|
||||
card.addClass("border-deployed")
|
||||
txt.addClass("text-deployed")
|
||||
} else if (status.startsWith("pending-")) {
|
||||
card.addClass("border-pending")
|
||||
txt.addClass("text-pending")
|
||||
} else {
|
||||
header.find(".badge").addClass("bg-light text-dark")
|
||||
card.addClass("border-other")
|
||||
txt.addClass("text-other")
|
||||
}
|
||||
|
||||
header.append($('<h5 class="card-title"><a href="#namespace=' + elm.namespace + '&name=' + elm.name + '" class="link-dark" style="text-decoration: none">' + elm.name + '</a></h5>'))
|
||||
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");
|
||||
setHashParam("namespace", chart.namespace)
|
||||
setHashParam("chart", chart.name)
|
||||
|
||||
loadChartHistory(chart.namespace, chart.name, elm.chart_name)
|
||||
})
|
||||
return card;
|
||||
}
|
||||
|
||||
function loadChartsList() {
|
||||
$("#sectionList").show()
|
||||
chartsCards.empty().append("<div><span class=\"spinner-border spinner-border-sm\" role=\"status\" aria-hidden=\"true\"></span> Loading...</div>")
|
||||
$.getJSON("/api/helm/charts").fail(function (xhr) {
|
||||
reportError("Failed to get list of charts", xhr)
|
||||
}).done(function (data) {
|
||||
chartsCards.empty()
|
||||
data.forEach(function (elm) {
|
||||
let card = buildChartCard(elm);
|
||||
chartsCards.append($("<div class='col'></div>").append(card))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
$(function () {
|
||||
clusterSelect.change(function () {
|
||||
Cookies.set("context", clusterSelect.val())
|
||||
window.location.href = "/"
|
||||
})
|
||||
|
||||
$.getJSON("/api/kube/contexts").fail(function (xhr) {
|
||||
reportError("Failed to get list of clusters", xhr)
|
||||
}).done(function (data) {
|
||||
const context = Cookies.get("context")
|
||||
|
||||
data.forEach(function (elm) {
|
||||
// aws CLI uses complicated context names, the suffix does not work well
|
||||
// maybe we should have an `if` statement here
|
||||
let label = elm.Name //+ " (" + elm.Cluster + "/" + elm.AuthInfo + "/" + elm.Namespace + ")"
|
||||
let opt = $("<option></option>").val(elm.Name).text(label)
|
||||
if (elm.IsCurrent && !context) {
|
||||
opt.attr("selected", "selected")
|
||||
} else if (context && elm.Name === context) {
|
||||
opt.attr("selected", "selected")
|
||||
$.ajaxSetup({
|
||||
headers: {
|
||||
'x-kubecontext': context
|
||||
}
|
||||
});
|
||||
}
|
||||
clusterSelect.append(opt)
|
||||
})
|
||||
|
||||
const namespace = getHashParam("namespace")
|
||||
const chart = getHashParam("chart")
|
||||
if (!chart) {
|
||||
loadChartsList()
|
||||
} else {
|
||||
loadChartHistory(namespace, chart)
|
||||
function fillClusterList(data, context) {
|
||||
data.forEach(function (elm) {
|
||||
// aws CLI uses complicated context names, the suffix does not work well
|
||||
// maybe we should have an `if` statement here
|
||||
let label = elm.Name //+ " (" + elm.Cluster + "/" + elm.AuthInfo + "/" + elm.Namespace + ")"
|
||||
let opt = $('<li><label><input type="radio" name="cluster" class="me-2"/><span></span></label></li>');
|
||||
opt.attr('title', label)
|
||||
opt.find("input").val(elm.Name).text(label)
|
||||
opt.find("span").text(label)
|
||||
if (elm.IsCurrent && !context) {
|
||||
opt.find("input").prop("checked", true)
|
||||
} else if (context && elm.Name === context) {
|
||||
opt.find("input").prop("checked", true)
|
||||
$.ajaxSetup({
|
||||
headers: {
|
||||
'x-kubecontext': context
|
||||
}
|
||||
});
|
||||
}
|
||||
$("#cluster").append(opt)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function getAge(obj1, obj2) {
|
||||
const date = luxon.DateTime.fromISO(obj1.updated);
|
||||
@@ -449,53 +108,6 @@ function getAge(obj1, obj2) {
|
||||
return "n/a"
|
||||
}
|
||||
|
||||
function showResources(namespace, chart, revision) {
|
||||
$("#nav-resources").empty().append('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>');
|
||||
let qstr = "name=" + chart + "&namespace=" + namespace + "&revision=" + revision
|
||||
let url = "/api/helm/charts/resources"
|
||||
url += "?" + qstr
|
||||
$.getJSON(url).fail(function (xhr) {
|
||||
reportError("Failed to get list of resources", xhr)
|
||||
}).done(function (data) {
|
||||
$("#nav-resources").empty();
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const res = data[i]
|
||||
const resBlock = $(`
|
||||
<div class="input-group row">
|
||||
<span class="input-group-text col-sm-2"><em class="text-muted small">` + res.kind + `</em></span>
|
||||
<span class="input-group-text col-sm-6">` + res.metadata.name + `</span>
|
||||
<span class="form-control col-sm-4"><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> <span class="text-muted small">Getting status...</span></span>
|
||||
</div>`)
|
||||
$("#nav-resources").append(resBlock)
|
||||
let ns = res.metadata.namespace ? res.metadata.namespace : namespace
|
||||
$.getJSON("/api/kube/resources/" + res.kind.toLowerCase() + "?name=" + res.metadata.name + "&namespace=" + ns).fail(function () {
|
||||
//reportError("Failed to get list of resources")
|
||||
}).done(function (data) {
|
||||
const badge = $("<span class='badge me-2'></span>").text(data.status.phase);
|
||||
if (["Available", "Active", "Established"].includes(data.status.phase)) {
|
||||
badge.addClass("bg-success")
|
||||
} else if (["Exists"].includes(data.status.phase)) {
|
||||
badge.addClass("bg-success bg-opacity-50")
|
||||
} else if (["Progressing"].includes(data.status.phase)) {
|
||||
badge.addClass("bg-warning")
|
||||
} else {
|
||||
badge.addClass("bg-danger")
|
||||
}
|
||||
|
||||
const statusBlock = resBlock.find(".form-control.col-sm-4");
|
||||
statusBlock.empty().append(badge).append("<span class='text-muted small'>" + (data.status.message ? data.status.message : '') + "</span>")
|
||||
|
||||
if (badge.text() !== "NotFound") {
|
||||
statusBlock.prepend("<i class=\"btn bi-zoom-in float-end text-muted\"></i>")
|
||||
statusBlock.find(".bi-zoom-in").click(function () {
|
||||
showDescribe(ns, res.kind, res.metadata.name)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
$(".bi-power").click(function () {
|
||||
$(".bi-power").attr("disabled", "disabled").removeClass(".bi-power").append('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>')
|
||||
$.ajax({
|
||||
@@ -506,104 +118,6 @@ $(".bi-power").click(function () {
|
||||
})
|
||||
})
|
||||
|
||||
function showDescribe(ns, kind, name) {
|
||||
$("#describeModalLabel").text("Describe " + kind + ": " + ns + " / " + name)
|
||||
$("#describeModalBody").empty().append('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>')
|
||||
|
||||
const myModal = new bootstrap.Modal(document.getElementById('describeModal'), {});
|
||||
myModal.show()
|
||||
$.get("/api/kube/describe/" + kind.toLowerCase() + "?name=" + name + "&namespace=" + ns).fail(function (xhr) {
|
||||
reportError("Failed to describe resource", xhr)
|
||||
}).done(function (data) {
|
||||
data = hljs.highlight(data, {language: 'yaml'}).value
|
||||
$("#describeModalBody").empty().append("<pre class='bg-white rounded p-3'></pre>").find("pre").html(data)
|
||||
})
|
||||
}
|
||||
|
||||
$("#btnUninstall").click(function () {
|
||||
const chart = getHashParam('chart');
|
||||
const namespace = getHashParam('namespace');
|
||||
const revision = $("#specRev").data("last-rev")
|
||||
$("#confirmModalLabel").html("Uninstall <b class='text-danger'>" + chart + "</b> from namespace <b class='text-danger'>" + namespace + "</b>")
|
||||
$("#confirmModalBody").empty().append('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>')
|
||||
$("#confirmModal .btn-primary").prop("disabled", true).off('click').click(function () {
|
||||
$("#confirmModal .btn-primary").prop("disabled", true).append('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>')
|
||||
const url = "/api/helm/charts?namespace=" + namespace + "&name=" + chart;
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: 'DELETE',
|
||||
}).fail(function (xhr) {
|
||||
reportError("Failed to delete the chart", xhr)
|
||||
}).done(function () {
|
||||
window.location.href = "/"
|
||||
})
|
||||
})
|
||||
|
||||
const myModal = new bootstrap.Modal(document.getElementById('confirmModal'), {});
|
||||
myModal.show()
|
||||
|
||||
let qstr = "name=" + chart + "&namespace=" + namespace + "&revision=" + revision
|
||||
let url = "/api/helm/charts/resources"
|
||||
url += "?" + qstr
|
||||
$.getJSON(url).fail(function (xhr) {
|
||||
reportError("Failed to get list of resources", xhr)
|
||||
}).done(function (data) {
|
||||
$("#confirmModalBody").empty().append("<p>Following resources will be deleted from the cluster:</p>");
|
||||
$("#confirmModal .btn-primary").prop("disabled", false)
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const res = data[i]
|
||||
$("#confirmModalBody").append("<p class='row'><i class='col-sm-3 text-end'>" + res.kind + "</i><b class='col-sm-9'>" + res.metadata.name + "</b></p>")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
$("#btnRollback").click(function () {
|
||||
const chart = getHashParam('chart');
|
||||
const namespace = getHashParam('namespace');
|
||||
const revisionNew = $("#btnRollback").data("rev")
|
||||
const revisionCur = $("#specRev").data("last-rev")
|
||||
$("#confirmModalLabel").html("Rollback <b class='text-danger'>" + chart + "</b> from revision " + revisionCur + " to " + revisionNew)
|
||||
$("#confirmModalBody").empty().append('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>')
|
||||
$("#confirmModal .btn-primary").prop("disabled", true).off('click').click(function () {
|
||||
$("#confirmModal .btn-primary").prop("disabled", true).append('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>')
|
||||
const url = "/api/helm/charts/rollback?namespace=" + namespace + "&name=" + chart + "&revision=" + revisionNew;
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: 'POST',
|
||||
}).fail(function (xhr) {
|
||||
reportError("Failed to rollback the chart", xhr)
|
||||
}).done(function () {
|
||||
window.location.reload()
|
||||
})
|
||||
})
|
||||
|
||||
const myModal = new bootstrap.Modal(document.getElementById('confirmModal'), {});
|
||||
myModal.show()
|
||||
|
||||
let qstr = "name=" + chart + "&namespace=" + namespace + "&revision=" + revisionNew + "&revisionDiff=" + revisionCur
|
||||
let url = "/api/helm/charts/manifests"
|
||||
url += "?" + qstr
|
||||
$.get(url).fail(function (xhr) {
|
||||
reportError("Failed to get list of resources", xhr)
|
||||
}).done(function (data) {
|
||||
$("#confirmModalBody").empty();
|
||||
$("#confirmModal .btn-primary").prop("disabled", false)
|
||||
|
||||
const targetElement = document.getElementById('confirmModalBody');
|
||||
const configuration = {
|
||||
inputFormat: 'diff', outputFormat: 'side-by-side',
|
||||
drawFileList: false, showFiles: false, highlight: true,
|
||||
};
|
||||
const diff2htmlUi = new Diff2HtmlUI(targetElement, data, configuration);
|
||||
diff2htmlUi.draw()
|
||||
if (data) {
|
||||
$("#confirmModalBody").prepend("<p>Following changes will happen to cluster:</p>")
|
||||
} else {
|
||||
$("#confirmModalBody").html("<p>No changes will happen to cluster</p>")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
function isNewerVersion(oldVer, newVer) {
|
||||
const oldParts = oldVer.split('.')
|
||||
const newParts = newVer.split('.')
|
||||
|
||||
@@ -1,9 +1,132 @@
|
||||
#charts .card, #sectionDetails .row > div {
|
||||
cursor: pointer;
|
||||
.strike {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.bg-primary .text-muted {
|
||||
color: white!important;
|
||||
.text-muted {
|
||||
color: #707583 !important;
|
||||
}
|
||||
|
||||
.border-other {
|
||||
border-color: #9195A1 !important;
|
||||
}
|
||||
|
||||
.text-other {
|
||||
color: #9195A1 !important;
|
||||
}
|
||||
|
||||
.border-failed {
|
||||
border-color: #FC1683 !important;
|
||||
}
|
||||
|
||||
.text-failed {
|
||||
color: #FC1683 !important;
|
||||
}
|
||||
|
||||
.border-deployed {
|
||||
border-color: #1BE99A !important;
|
||||
}
|
||||
|
||||
.text-deployed {
|
||||
color: #1FA470 !important;
|
||||
}
|
||||
|
||||
.border-pending {
|
||||
border-color: #5AB0FF !important;
|
||||
}
|
||||
|
||||
.text-pending {
|
||||
color: #5AB0FF !important;
|
||||
}
|
||||
|
||||
.bg-tag {
|
||||
background-color: #D6EFFE;
|
||||
}
|
||||
|
||||
.bg-tag.text-dark {
|
||||
color: #333333 !important;
|
||||
}
|
||||
|
||||
.text-uppercase {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.offcanvas {
|
||||
width: auto!important;
|
||||
max-width: 90%;
|
||||
min-width: 60%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
min-height: 50rem;
|
||||
font-size: 14px;
|
||||
|
||||
background-color: #F4F7FA;
|
||||
font-family: Roboto, serif;
|
||||
color: #3D4048;
|
||||
}
|
||||
|
||||
body > .container-fluid {
|
||||
min-height: 100% !important;
|
||||
}
|
||||
|
||||
#topNav.navbar {
|
||||
box-shadow: 0 1px 4px rgba(22, 24, 31, 0.1);
|
||||
}
|
||||
|
||||
.navbar-brand > div {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.navbar-brand > div p span {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-family: Poppins, serif;
|
||||
font-size: 0.6rem !important;
|
||||
color: #707583;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.navbar-brand h1 {
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
line-height: 50%;
|
||||
}
|
||||
|
||||
.navbar-brand h1 a {
|
||||
font-size: 1.1rem !important;
|
||||
color: #0023A3 !important;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.navbar-brand > a > img {
|
||||
vertical-align: middle;
|
||||
height: 2.5rem;
|
||||
display: inline-block;
|
||||
margin: 0.5rem 0.8rem
|
||||
}
|
||||
|
||||
.navbar-brand p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.navbar-brand p a {
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
.navbar-brand p img {
|
||||
height: 1.25rem;
|
||||
margin-left: 0.25rem;
|
||||
}
|
||||
|
||||
#topNav .navbar i.btn {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.d2h-file-collapse, .d2h-tag {
|
||||
@@ -12,4 +135,156 @@
|
||||
|
||||
.display-none {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.separator-vertical span {
|
||||
font-size: 2rem;
|
||||
border-left: 1px solid #DCDDDF;
|
||||
margin: 0.25rem 0;
|
||||
}
|
||||
|
||||
#topNav .nav-link {
|
||||
color: #3B3D45 !important;
|
||||
}
|
||||
|
||||
#topNav .nav-link.active {
|
||||
background: #EBEFFF;
|
||||
border-radius: 2px;
|
||||
color: #1347FF !important;
|
||||
}
|
||||
|
||||
.b-shadow {
|
||||
box-shadow: 0 0 4px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
#filters h4 {
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
#filters {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 0.8rem;
|
||||
line-height: 175%;
|
||||
}
|
||||
|
||||
#cluster input, #cluster span {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#installedList > div, #installedList .body > div {
|
||||
margin-bottom: 0.75rem !important;
|
||||
}
|
||||
|
||||
#installedList h2 {
|
||||
font-family: Inter, serif;
|
||||
font-weight: 700;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
|
||||
.bg-secondary {
|
||||
background: #ECEFF2 !important;
|
||||
}
|
||||
|
||||
.border-secondary {
|
||||
border-color: #DCDDDF !important;
|
||||
}
|
||||
|
||||
#installedList .header {
|
||||
font-family: Roboto, serif;
|
||||
font-weight: 600;
|
||||
font-size: 0.6rem;
|
||||
color: #3B3D45;
|
||||
}
|
||||
|
||||
#installedList .header .row {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
#installedList .hdr-name {
|
||||
padding-left: 5.5rem
|
||||
}
|
||||
|
||||
#installedList .body {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
#installedList .body .row div div {
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
span.link {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#installedList .body .row:hover span.link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#installedList .rel-name {
|
||||
padding-left: 5.5rem;
|
||||
background-image: url("helm-gray-50.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center left;
|
||||
background-position-x: 1.1rem;
|
||||
background-size: 3rem;
|
||||
}
|
||||
|
||||
#installedList .rel-name span {
|
||||
font-family: Roboto Slab, sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
#sectionDetails h1 {
|
||||
font-family: Roboto Slab, sans-serif;
|
||||
font-weight: 400;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
|
||||
#installedList .rel-name div {
|
||||
height: 2rem;
|
||||
min-height: 2rem;
|
||||
max-height: 2rem;
|
||||
}
|
||||
|
||||
#installedList .rel-status span {
|
||||
text-transform: uppercase;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
#installedList .rel-chart span, #installedList .rel-rev span, #installedList .rel-ns span, #installedList .rel-date span {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
#installedList .rel-chart div, #installedList .rel-rev div, #installedList .rel-ns div, #installedList .rel-date div {
|
||||
text-transform: uppercase;
|
||||
color: #707583;
|
||||
}
|
||||
|
||||
#actionButtons button > * {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.d2h-code-side-linenumber {
|
||||
position: static;
|
||||
}
|
||||
|
||||
.nav-tabs {
|
||||
border: none;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link {
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link.active {
|
||||
border: none;
|
||||
border-bottom: 3px solid #3B3D45;
|
||||
}
|
||||
15
pkg/dashboard/static/topographic.svg
Normal file
|
After Width: | Height: | Size: 77 KiB |