Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor templated JS #46

Merged
merged 1 commit into from
Apr 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions pkg/dashboard/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,28 @@ const (
TemplateFile = "pkg/dashboard/templates/" + TemplateName
)

// TemplateData is passed to the dashboard HTML template
type TemplateData struct {
AuditData validator.AuditData
JSON template.JS
}

// MainHandler gets template data and renders the dashboard with it.
func MainHandler(w http.ResponseWriter, r *http.Request, c conf.Configuration, kubeAPI *kube.API) {
templateData, err := validator.RunAudit(c, kubeAPI)
auditData, err := validator.RunAudit(c, kubeAPI)
if err != nil {
http.Error(w, "Error Fetching Deployments", 500)
http.Error(w, "Error running audit", 500)
return
}
jsonData, err := json.Marshal(auditData)
if err != nil {
http.Error(w, "Error serializing audit data", 500)
return
}
templateData := TemplateData{
AuditData: auditData,
JSON: template.JS(jsonData),
}
tmpl, err := template.New(TemplateName).Funcs(template.FuncMap{
"getWarningWidth": func(rs validator.ResultSummary, fullWidth int) uint {
return uint(float64(rs.Successes+rs.Warnings) / float64(rs.Successes+rs.Warnings+rs.Errors) * float64(fullWidth))
Expand Down
88 changes: 6 additions & 82 deletions pkg/dashboard/templates/dashboard.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/cash/3.0.0-beta.3/cash.min.js"></script>
<script>
window.fairwindsAuditData = {{ .JSON }};
</script>
<script type="text/javascript" src="/static/js/main.js"></script>

</head>
Expand Down Expand Up @@ -46,7 +49,7 @@
</div>
</div>

{{ range $namespace, $results := .NamespacedResults }}
{{ range $namespace, $results := .AuditData.NamespacedResults }}
<div class="namespace">
<h3>Namespace: <strong>{{ $namespace }}</strong></h3>
<table class="namespace-content" cellspacing="0">
Expand Down Expand Up @@ -89,93 +92,14 @@
{{ end }} {{/* end range .Results */}}
</table>
</div>
{{ end }} {{/* end range .NamespacedResults */}}
{{ end }} {{/* end range .AuditData.NamespacedResults */}}
</div>

<div class="footer">
&copy; 2019, <a href="https://reactiveops.com?source=fairwinds">ReactiveOps Inc.</a>
</div>

<script>
$(function () {
var namespaceChart = new Chart("namespaceScoreChart", {
type: 'bar',
data: {
labels: [
{{ range $namespace, $results := .NamespacedResults }}
"{{ $namespace }}",
{{ end }}
],
datasets: [{
label: 'Passing',
data: [
{{ range $namespace, $results := .NamespacedResults }}
"{{ $results.Summary.Successes }}",
{{ end }}
],
backgroundColor: '#8BD2DC',
},{
label: 'Warning',
data: [
{{ range $namespace, $results := .NamespacedResults }}
"{{ $results.Summary.Warnings }}",
{{ end }}
],
backgroundColor: '#f26c21',
},{
label: 'Failing',
data: [
{{ range $namespace, $results := .NamespacedResults }}
"{{ $results.Summary.Errors }}",
{{ end }}
],
backgroundColor: '#a11f4c',
}]
},
options: {
legend: {
display: false,
},
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true,
ticks: {
beginAtZero: true
}
}]
}
}
});

var clusterChart = new Chart("clusterScoreChart", {
type: 'doughnut',
data: {
labels: ["Passing", "Warning", "Failing"],
datasets: [{
data: [{{ .ClusterSummary.Successes }}, {{ .ClusterSummary.Warnings }}, {{ .ClusterSummary.Errors }}],
backgroundColor: ['#8BD2DC','#f26c21','#a11f4c'],
}]
},
options: {
// responsive: false,
cutoutPercentage: 75,
legend: {
display: false,
},
elements: {
center: {
text: '{{ .ClusterSummary.Score }}%',
color: '#333', //Default black
fontStyle: 'Helvetica', //Default Arial
sidePadding: 30 //Default 20 (as a percentage)
}
}
}
});
});
<script src="/static/js/charts.js">
</script>
</body>

Expand Down
85 changes: 85 additions & 0 deletions public/js/charts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
if (!Object.values) {
Object.values = function(obj) {
return Object.keys(obj).map(function(key) {
return obj[key];
})
}
}

$(function () {
var namespaceChart = new Chart("namespaceScoreChart", {
type: 'bar',
data: {
labels: Object.keys(fairwindsAuditData.NamespacedResults),
datasets: [{
label: 'Passing',
data: Object.values(fairwindsAuditData.NamespacedResults)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even Object.values is a bit of a stretch for older browsers unfortunately: https://caniuse.com/#feat=object-values. I don't feel too strongly on this, there's probably not a ton of overlap between people using this tool and people using old browsers, but it certainly could be an issue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's a pain to reimplement that, you could also include all or part of lodash: https://www.jsdelivr.com/package/npm/lodash

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call - wrote a quick polyfill

.map(function(r) { return r.Summary.Successes}),
backgroundColor: '#8BD2DC',
},{
label: 'Warning',
data: Object.values(fairwindsAuditData.NamespacedResults)
.map(function(r) { return r.Summary.Warnings}),
backgroundColor: '#f26c21',
},{
label: 'Failing',
data: Object.values(fairwindsAuditData.NamespacedResults)
.map(function(r) { return r.Summary.Errors}),
backgroundColor: '#a11f4c',
}]
},
options: {
legend: {
display: false,
},
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true,
ticks: {
beginAtZero: true
}
}]
}
}
});

var score = fairwindsAuditData.ClusterSummary.Successes / (
fairwindsAuditData.ClusterSummary.Successes +
fairwindsAuditData.ClusterSummary.Warnings +
fairwindsAuditData.ClusterSummary.Errors);
score = Math.round(score * 100);

var clusterChart = new Chart("clusterScoreChart", {
type: 'doughnut',
data: {
labels: ["Passing", "Warning", "Error"],
datasets: [{
data: [
fairwindsAuditData.ClusterSummary.Successes,
fairwindsAuditData.ClusterSummary.Warnings,
fairwindsAuditData.ClusterSummary.Errors,
],
backgroundColor: ['#8BD2DC','#f26c21','#a11f4c'],
}]
},
options: {
// responsive: false,
cutoutPercentage: 75,
legend: {
display: false,
},
elements: {
center: {
text: score + '%',
color: '#333', //Default black
fontStyle: 'Helvetica', //Default Arial
sidePadding: 30 //Default 20 (as a percentage)
}
}
}
});
});