Allow customizing charts of service stats page

This commit is contained in:
cuigh 2018-04-02 18:17:43 +08:00
parent 8d2575d229
commit 43d539e31a
10 changed files with 247 additions and 135 deletions

View File

@ -1375,6 +1375,7 @@ var Swirl;
this.charts = [];
this.opts = $.extend(new ChartDashboardOptions(), opts);
this.$panel = $(elem);
this.dlg = new ChartDialog(this);
charts.forEach(opts => this.createGraph(opts));
Core.Dispatcher.bind(this.$panel).on("remove-chart", e => {
let name = $(e.target).closest("div.column").data("name");
@ -1467,6 +1468,9 @@ var Swirl;
}
});
}
getOptions() {
return this.opts;
}
loadData() {
let args = {
charts: this.charts.map(c => c.getOptions().name).join(","),
@ -1485,69 +1489,72 @@ var Swirl;
}
}
Core.ChartDashboard = ChartDashboard;
class ChartDialog {
constructor(dashboard) {
this.dashboard = dashboard;
this.fb = new Core.FilterBox("#txt-query", this.filterCharts.bind(this));
$("#btn-add").click(this.showAddDlg.bind(this));
$("#btn-add-chart").click(this.addChart.bind(this));
$("#btn-save").click(() => {
this.dashboard.save();
});
}
showAddDlg() {
let $panel = $("#nav-charts");
$panel.find("label.panel-block").remove();
$ajax.get(`/system/chart/query`, { dashboard: this.dashboard.getOptions().name }).json((charts) => {
for (let i = 0; i < charts.length; i++) {
let c = charts[i];
$panel.append(`<label class="panel-block">
<input type="checkbox" value="${c.name}" data-index="${i}">${c.name}: ${c.title}
</label>`);
}
this.charts = charts;
this.$charts = $panel.find("label.panel-block");
});
let dlg = new Core.Modal("#dlg-add-chart");
dlg.show();
}
filterCharts(text) {
if (!text) {
this.$charts.show();
return;
}
this.$charts.each((i, elem) => {
let $elem = $(elem);
let texts = [
this.charts[i].name.toLowerCase(),
this.charts[i].title.toLowerCase(),
this.charts[i].desc.toLowerCase(),
];
for (let i = 0; i < texts.length; i++) {
let index = texts[i].indexOf(text);
if (index >= 0) {
$elem.show();
return;
}
}
$elem.hide();
});
}
addChart() {
this.$charts.each((i, e) => {
if ($(e).find(":checked").length > 0) {
let c = this.charts[i];
this.dashboard.addGraph(c);
}
});
Core.Modal.close();
}
}
})(Core = Swirl.Core || (Swirl.Core = {}));
})(Swirl || (Swirl = {}));
var Swirl;
(function (Swirl) {
var Modal = Swirl.Core.Modal;
var FilterBox = Swirl.Core.FilterBox;
var ChartDashboard = Swirl.Core.ChartDashboard;
class IndexPage {
constructor() {
this.fb = new FilterBox("#txt-query", this.filterCharts.bind(this));
this.dashboard = new ChartDashboard("#div-charts", window.charts, { name: "home" });
$("#btn-add").click(this.showAddDlg.bind(this));
$("#btn-add-chart").click(this.addChart.bind(this));
$("#btn-save").click(() => {
this.dashboard.save();
});
}
showAddDlg() {
let $panel = $("#nav-charts");
$panel.find("label.panel-block").remove();
$ajax.get(`/system/chart/query`, { dashboard: "home" }).json((charts) => {
for (let i = 0; i < charts.length; i++) {
let c = charts[i];
$panel.append(`<label class="panel-block">
<input type="checkbox" value="${c.name}" data-index="${i}">${c.name}: ${c.title}
</label>`);
}
this.charts = charts;
this.$charts = $panel.find("label.panel-block");
});
let dlg = new Modal("#dlg-add-chart");
dlg.show();
}
filterCharts(text) {
if (!text) {
this.$charts.show();
return;
}
this.$charts.each((i, elem) => {
let $elem = $(elem);
let texts = [
this.charts[i].name.toLowerCase(),
this.charts[i].title.toLowerCase(),
this.charts[i].desc.toLowerCase(),
];
for (let i = 0; i < texts.length; i++) {
let index = texts[i].indexOf(text);
if (index >= 0) {
$elem.show();
return;
}
}
$elem.hide();
});
}
addChart() {
this.$charts.each((i, e) => {
if ($(e).find(":checked").length > 0) {
let c = this.charts[i];
this.dashboard.addGraph(c);
}
});
Modal.close();
}
}
Swirl.IndexPage = IndexPage;
@ -2357,7 +2364,6 @@ var Swirl;
(function (Swirl) {
var Service;
(function (Service) {
var Modal = Swirl.Core.Modal;
var ChartDashboard = Swirl.Core.ChartDashboard;
class StatsPage {
constructor() {
@ -2369,12 +2375,6 @@ var Swirl;
name: "service",
key: $("#h2-service-name").text()
});
$("#btn-add").click(() => {
Modal.alert("Coming soon...");
});
$("#btn-save").click(() => {
Modal.alert("Coming soon...");
});
$cb_time.change(e => {
this.dashboard.setPeriod($(e.target).val());
});

File diff suppressed because one or more lines are too long

View File

@ -286,10 +286,13 @@ namespace Swirl.Core {
private opts: ChartDashboardOptions;
private charts: Chart[] = [];
private timer: number;
private dlg: ChartDialog;
constructor(elem: string | Element | JQuery, charts: ChartOptions[], opts?: ChartDashboardOptions) {
this.opts = $.extend(new ChartDashboardOptions(), opts);
this.$panel = $(elem);
this.dlg = new ChartDialog(this);
charts.forEach(opts => this.createGraph(opts));
// events
@ -396,6 +399,10 @@ namespace Swirl.Core {
});
}
getOptions(): ChartDashboardOptions {
return this.opts;
}
private loadData() {
let args: any = {
charts: this.charts.map(c => c.getOptions().name).join(","),
@ -413,4 +420,75 @@ namespace Swirl.Core {
});
}
}
class ChartDialog {
private dashboard: ChartDashboard;
private fb: FilterBox;
private charts: any;
private $charts: JQuery;
constructor(dashboard: ChartDashboard) {
this.dashboard = dashboard;
this.fb = new FilterBox("#txt-query", this.filterCharts.bind(this));
$("#btn-add").click(this.showAddDlg.bind(this));
$("#btn-add-chart").click(this.addChart.bind(this));
$("#btn-save").click(() => {
this.dashboard.save();
});
}
private showAddDlg() {
let $panel = $("#nav-charts");
$panel.find("label.panel-block").remove();
// load charts
$ajax.get(`/system/chart/query`, {dashboard: this.dashboard.getOptions().name}).json((charts: any) => {
for (let i = 0; i < charts.length; i++) {
let c = charts[i];
$panel.append(`<label class="panel-block">
<input type="checkbox" value="${c.name}" data-index="${i}">${c.name}: ${c.title}
</label>`);
}
this.charts = charts;
this.$charts = $panel.find("label.panel-block");
});
let dlg = new Modal("#dlg-add-chart");
dlg.show();
}
private filterCharts(text: string) {
if (!text) {
this.$charts.show();
return;
}
this.$charts.each((i, elem) => {
let $elem = $(elem);
let texts: string[] = [
this.charts[i].name.toLowerCase(),
this.charts[i].title.toLowerCase(),
this.charts[i].desc.toLowerCase(),
];
for (let i = 0; i < texts.length; i++) {
let index = texts[i].indexOf(text);
if (index >= 0) {
$elem.show();
return;
}
}
$elem.hide();
})
}
private addChart() {
this.$charts.each((i, e) => {
if ($(e).find(":checked").length > 0) {
let c = this.charts[i];
this.dashboard.addGraph(c);
}
});
Modal.close();
}
}
}

View File

@ -7,72 +7,72 @@ namespace Swirl {
export class IndexPage {
private dashboard: ChartDashboard;
private fb: FilterBox;
private charts: any;
private $charts: JQuery;
// private fb: FilterBox;
// private charts: any;
// private $charts: JQuery;
constructor() {
this.fb = new FilterBox("#txt-query", this.filterCharts.bind(this));
// this.fb = new FilterBox("#txt-query", this.filterCharts.bind(this));
this.dashboard = new ChartDashboard("#div-charts", window.charts, {name: "home"});
$("#btn-add").click(this.showAddDlg.bind(this));
$("#btn-add-chart").click(this.addChart.bind(this));
$("#btn-save").click(() => {
this.dashboard.save();
});
// $("#btn-add").click(this.showAddDlg.bind(this));
// $("#btn-add-chart").click(this.addChart.bind(this));
// $("#btn-save").click(() => {
// this.dashboard.save();
// });
}
private showAddDlg() {
let $panel = $("#nav-charts");
$panel.find("label.panel-block").remove();
// load charts
$ajax.get(`/system/chart/query`, {dashboard: "home"}).json((charts: any) => {
for (let i = 0; i < charts.length; i++) {
let c = charts[i];
$panel.append(`<label class="panel-block">
<input type="checkbox" value="${c.name}" data-index="${i}">${c.name}: ${c.title}
</label>`);
}
this.charts = charts;
this.$charts = $panel.find("label.panel-block");
});
let dlg = new Modal("#dlg-add-chart");
dlg.show();
}
private filterCharts(text: string) {
if (!text) {
this.$charts.show();
return;
}
this.$charts.each((i, elem) => {
let $elem = $(elem);
let texts: string[] = [
this.charts[i].name.toLowerCase(),
this.charts[i].title.toLowerCase(),
this.charts[i].desc.toLowerCase(),
];
for (let i = 0; i < texts.length; i++) {
let index = texts[i].indexOf(text);
if (index >= 0) {
$elem.show();
return;
}
}
$elem.hide();
})
}
private addChart() {
this.$charts.each((i, e) => {
if ($(e).find(":checked").length > 0) {
let c = this.charts[i];
this.dashboard.addGraph(c);
}
});
Modal.close();
}
// private showAddDlg() {
// let $panel = $("#nav-charts");
// $panel.find("label.panel-block").remove();
//
// // load charts
// $ajax.get(`/system/chart/query`, {dashboard: "home"}).json((charts: any) => {
// for (let i = 0; i < charts.length; i++) {
// let c = charts[i];
// $panel.append(`<label class="panel-block">
// <input type="checkbox" value="${c.name}" data-index="${i}">${c.name}: ${c.title}
// </label>`);
// }
// this.charts = charts;
// this.$charts = $panel.find("label.panel-block");
// });
//
// let dlg = new Modal("#dlg-add-chart");
// dlg.show();
// }
//
// private filterCharts(text: string) {
// if (!text) {
// this.$charts.show();
// return;
// }
//
// this.$charts.each((i, elem) => {
// let $elem = $(elem);
// let texts: string[] = [
// this.charts[i].name.toLowerCase(),
// this.charts[i].title.toLowerCase(),
// this.charts[i].desc.toLowerCase(),
// ];
// for (let i = 0; i < texts.length; i++) {
// let index = texts[i].indexOf(text);
// if (index >= 0) {
// $elem.show();
// return;
// }
// }
// $elem.hide();
// })
// }
//
// private addChart() {
// this.$charts.each((i, e) => {
// if ($(e).find(":checked").length > 0) {
// let c = this.charts[i];
// this.dashboard.addGraph(c);
// }
// });
// Modal.close();
// }
}
}

View File

@ -18,12 +18,12 @@ namespace Swirl.Service {
key: $("#h2-service-name").text()
});
$("#btn-add").click(() => {
Modal.alert("Coming soon...");
});
$("#btn-save").click(() => {
Modal.alert("Coming soon...");
});
// $("#btn-add").click(() => {
// Modal.alert("Coming soon...");
// });
// $("#btn-save").click(() => {
// Modal.alert("Coming soon...");
// });
$cb_time.change(e => {
this.dashboard.setPeriod($(e.target).val());
});

View File

@ -116,7 +116,7 @@ func (b *chartBiz) UpdateDashboard(dashboard *model.ChartDashboard, user web.Use
// nolint: gocyclo
func (b *chartBiz) GetDashboardCharts(dashboard *model.ChartDashboard) (charts []*model.Chart, err error) {
do(func(d dao.Interface) {
if len(dashboard.Charts) == 0 {
if dashboard == nil || len(dashboard.Charts) == 0 {
return
}

View File

@ -136,7 +136,7 @@ func chartSaveDashboard(ctx web.Context) error {
}
switch dashboard.Name {
case "home":
case "home", "service":
err = biz.Chart.UpdateDashboard(dashboard, ctx.User())
default:
err = errors.New("unknown dashboard: " + dashboard.Name)

View File

@ -296,7 +296,15 @@ func serviceStats(ctx web.Context) error {
var charts []*model.Chart
if setting.Metrics.Prometheus != "" {
charts, err = biz.Chart.GetServiceCharts(name)
var dashboard *model.ChartDashboard
if dashboard, err = biz.Chart.GetDashboard("service", name); err != nil {
return err
}
if dashboard == nil {
charts, err = biz.Chart.GetServiceCharts(name)
} else {
charts, err = biz.Chart.GetDashboardCharts(dashboard)
}
}
period := cast.ToDuration(ctx.Q("time"), time.Hour)

View File

@ -28,7 +28,7 @@ func main() {
misc.BindOptions()
app.Name = "Swirl"
app.Version = "0.7.1"
app.Version = "0.7.2"
app.Desc = "A web management UI for Docker, focused on swarm cluster"
app.Action = func(ctx *app.Context) {
err := config.UnmarshalOption("swirl", &misc.Options)

View File

@ -96,4 +96,30 @@
</a>
</div>
</section>
<div id="dlg-add-chart" class="modal">
<div class="modal-background"></div>
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">Add chart</p>
<button class="delete"></button>
</header>
<section class="modal-card-body" style="max-height: 400px; overflow-y: auto">
<nav id="nav-charts" class="panel">
<div class="panel-block">
<p class="control has-icons-left">
<input id="txt-query" class="input is-small" type="text" placeholder="Searching chart...">
<span class="icon is-small is-left">
<i class="fas fa-search"></i>
</span>
</p>
</div>
</nav>
</section>
<footer class="modal-card-foot">
<button id="btn-add-chart" type="button" class="button is-primary">{{ i18n("button.confirm") }}</button>
<button type="button" class="button dismiss">{{ i18n("button.cancel") }}</button>
</footer>
</div>
</div>
{{ end }}