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

View File

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

View File

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

View File

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

View File

@ -296,7 +296,15 @@ func serviceStats(ctx web.Context) error {
var charts []*model.Chart var charts []*model.Chart
if setting.Metrics.Prometheus != "" { if setting.Metrics.Prometheus != "" {
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) charts, err = biz.Chart.GetServiceCharts(name)
} else {
charts, err = biz.Chart.GetDashboardCharts(dashboard)
}
} }
period := cast.ToDuration(ctx.Q("time"), time.Hour) period := cast.ToDuration(ctx.Q("time"), time.Hour)

View File

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

View File

@ -96,4 +96,30 @@
</a> </a>
</div> </div>
</section> </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 }} {{ end }}