mirror of
https://github.com/cuigh/swirl
synced 2024-12-28 14:51:57 +00:00
Refactor dashboard management
This commit is contained in:
parent
f4546d0888
commit
d5b5ff114a
@ -1348,6 +1348,13 @@ var Swirl;
|
||||
this.charts.push(g);
|
||||
}
|
||||
});
|
||||
Core.Dispatcher.bind(this.$panel).on("remove-chart", e => {
|
||||
let name = $(e.target).closest("div.column").data("chart-name");
|
||||
Core.Modal.confirm(`Are you sure to delete chart: <strong>${name}</strong>?`, "Delete chart", dlg => {
|
||||
this.removeGraph(name);
|
||||
dlg.close();
|
||||
});
|
||||
});
|
||||
$(window).resize(e => {
|
||||
$.each(this.charts, (i, g) => {
|
||||
g.resize(0, 0);
|
||||
@ -1409,7 +1416,7 @@ var Swirl;
|
||||
this.loadData();
|
||||
}
|
||||
removeGraph(name) {
|
||||
let index;
|
||||
let index = -1;
|
||||
for (let i = 0; i < this.charts.length; i++) {
|
||||
let c = this.charts[i];
|
||||
if (c.getName() === name) {
|
||||
@ -1417,7 +1424,13 @@ var Swirl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.loadData();
|
||||
if (index >= 0) {
|
||||
console.info(this.charts.length);
|
||||
let $elem = this.charts[index].getElem();
|
||||
this.charts.splice(index, 1);
|
||||
$elem.remove();
|
||||
console.info(this.charts.length);
|
||||
}
|
||||
}
|
||||
save() {
|
||||
let charts = this.charts.map(c => {
|
||||
@ -1432,9 +1445,12 @@ var Swirl;
|
||||
key: this.opts.key || '',
|
||||
charts: charts,
|
||||
};
|
||||
$ajax.post(`/system/chart/save_panel`, args).json((r) => {
|
||||
if (!r.success) {
|
||||
Core.Modal.alert(r.message);
|
||||
$ajax.post(`/system/chart/save_dashboard`, args).json((r) => {
|
||||
if (r.success) {
|
||||
Core.Notification.show("success", "Successfully saved.");
|
||||
}
|
||||
else {
|
||||
Core.Notification.show("danger", r.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -2343,6 +2359,9 @@ var Swirl;
|
||||
$("#btn-add").click(() => {
|
||||
Modal.alert("Coming soon...");
|
||||
});
|
||||
$("#btn-save").click(() => {
|
||||
Modal.alert("Coming soon...");
|
||||
});
|
||||
$cb_time.change(e => {
|
||||
this.panel.setTime($(e.target).val());
|
||||
});
|
||||
|
File diff suppressed because one or more lines are too long
@ -320,6 +320,13 @@ namespace Swirl.Core {
|
||||
}
|
||||
});
|
||||
|
||||
Dispatcher.bind(this.$panel).on("remove-chart", e => {
|
||||
let name = $(e.target).closest("div.column").data("chart-name");
|
||||
Modal.confirm(`Are you sure to delete chart: <strong>${name}</strong>?`, "Delete chart", dlg => {
|
||||
this.removeGraph(name);
|
||||
dlg.close();
|
||||
});
|
||||
});
|
||||
$(window).resize(e => {
|
||||
$.each(this.charts, (i: number, g: Graph) => {
|
||||
g.resize(0, 0);
|
||||
@ -356,7 +363,7 @@ namespace Swirl.Core {
|
||||
}
|
||||
|
||||
addGraph(c: any) {
|
||||
for (let i =0; i< this.charts.length; i++) {
|
||||
for (let i = 0; i < this.charts.length; i++) {
|
||||
let chart = this.charts[i];
|
||||
if (chart.getName() === c.name) {
|
||||
// chart already added.
|
||||
@ -393,15 +400,22 @@ namespace Swirl.Core {
|
||||
|
||||
removeGraph(name: string) {
|
||||
// todo:
|
||||
let index:number;
|
||||
for (let i =0; i< this.charts.length; i++) {
|
||||
let index = -1;
|
||||
for (let i = 0; i < this.charts.length; i++) {
|
||||
let c = this.charts[i];
|
||||
if (c.getName() === name) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.loadData();
|
||||
|
||||
if (index >= 0) {
|
||||
console.info(this.charts.length);
|
||||
let $elem = this.charts[index].getElem();
|
||||
this.charts.splice(index, 1);
|
||||
$elem.remove();
|
||||
console.info(this.charts.length);
|
||||
}
|
||||
}
|
||||
|
||||
save() {
|
||||
@ -418,9 +432,11 @@ namespace Swirl.Core {
|
||||
key: this.opts.key || '',
|
||||
charts: charts,
|
||||
};
|
||||
$ajax.post(`/system/chart/save_panel`, args).json<AjaxResult>((r: AjaxResult) => {
|
||||
if (!r.success) {
|
||||
Modal.alert(r.message);
|
||||
$ajax.post(`/system/chart/save_dashboard`, args).json<AjaxResult>((r: AjaxResult) => {
|
||||
if (r.success) {
|
||||
Notification.show("success", "Successfully saved.");
|
||||
} else {
|
||||
Notification.show("danger", r.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -21,6 +21,9 @@ namespace Swirl.Service {
|
||||
$("#btn-add").click(() => {
|
||||
Modal.alert("Coming soon...");
|
||||
});
|
||||
$("#btn-save").click(() => {
|
||||
Modal.alert("Coming soon...");
|
||||
});
|
||||
$cb_time.change(e => {
|
||||
this.panel.setTime($(e.target).val());
|
||||
});
|
||||
|
28
biz/chart.go
28
biz/chart.go
@ -99,20 +99,34 @@ func (b *chartBiz) GetServiceCharts(name string) (charts []*model.Chart, err err
|
||||
return
|
||||
}
|
||||
|
||||
// nolint: gocyclo
|
||||
func (b *chartBiz) Panel(panel model.ChartPanel) (charts []*model.Chart, err error) {
|
||||
func (b *chartBiz) GetDashboard(name, key string) (dashboard *model.ChartDashboard, err error) {
|
||||
do(func(d dao.Interface) {
|
||||
if len(panel.Charts) == 0 {
|
||||
dashboard, err = d.DashboardGet(name, key)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (b *chartBiz) UpdateDashboard(dashboard *model.ChartDashboard, user web.User) (err error) {
|
||||
do(func(d dao.Interface) {
|
||||
err = d.DashboardUpdate(dashboard)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// nolint: gocyclo
|
||||
func (b *chartBiz) GetDashboardCharts(dashboard *model.ChartDashboard) (charts []*model.Chart, err error) {
|
||||
do(func(d dao.Interface) {
|
||||
if len(dashboard.Charts) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
names := make([]string, len(panel.Charts))
|
||||
for i, c := range panel.Charts {
|
||||
names := make([]string, len(dashboard.Charts))
|
||||
for i, c := range dashboard.Charts {
|
||||
names[i] = c.Name
|
||||
}
|
||||
|
||||
var cs []*model.Chart
|
||||
cs, err = d.ChartBatch(names...)
|
||||
cs, err = b.getCharts(names)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -122,7 +136,7 @@ func (b *chartBiz) Panel(panel model.ChartPanel) (charts []*model.Chart, err err
|
||||
for _, c := range cs {
|
||||
m[c.Name] = c
|
||||
}
|
||||
for _, c := range panel.Charts {
|
||||
for _, c := range dashboard.Charts {
|
||||
if chart := m[c.Name]; chart != nil {
|
||||
if c.Width > 0 {
|
||||
chart.Width = c.Width
|
||||
|
@ -33,13 +33,3 @@ func (b *settingBiz) Update(setting *model.Setting, user web.User) (err error) {
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (b *settingBiz) UpdateDashboard(name string, dashboard *model.ChartPanel, user web.User) (err error) {
|
||||
do(func(d dao.Interface) {
|
||||
err = d.UpdateDashboard(name, dashboard)
|
||||
if err == nil {
|
||||
Event.CreateSetting(model.EventActionUpdate, user)
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cuigh/auxo/data"
|
||||
"github.com/cuigh/auxo/errors"
|
||||
"github.com/cuigh/auxo/net/web"
|
||||
"github.com/cuigh/auxo/util/cast"
|
||||
@ -13,29 +14,29 @@ import (
|
||||
|
||||
// ChartController is a controller of metric chart.
|
||||
type ChartController struct {
|
||||
List web.HandlerFunc `path:"/" name:"chart.list" authorize:"!" desc:"chart list page"`
|
||||
Query web.HandlerFunc `path:"/query" name:"chart.query" authorize:"?" desc:"chart query"`
|
||||
New web.HandlerFunc `path:"/new" name:"chart.new" authorize:"!" desc:"new chart page"`
|
||||
Create web.HandlerFunc `path:"/new" method:"post" name:"chart.create" authorize:"!" desc:"create chart"`
|
||||
Edit web.HandlerFunc `path:"/:name/edit" name:"chart.edit" authorize:"!" desc:"edit chart page"`
|
||||
Delete web.HandlerFunc `path:"/:name/delete" method:"post" name:"chart.delete" authorize:"!" desc:"delete chart"`
|
||||
Update web.HandlerFunc `path:"/:name/edit" method:"post" name:"chart.update" authorize:"!" desc:"update chart"`
|
||||
Data web.HandlerFunc `path:"/data" name:"chart.data" authorize:"?" desc:"fetch chart datas"`
|
||||
SavePanel web.HandlerFunc `path:"/save_panel" method:"post" name:"chart.save_panel" authorize:"!" desc:"save panel"`
|
||||
List web.HandlerFunc `path:"/" name:"chart.list" authorize:"!" desc:"chart list page"`
|
||||
Query web.HandlerFunc `path:"/query" name:"chart.query" authorize:"?" desc:"chart query"`
|
||||
New web.HandlerFunc `path:"/new" name:"chart.new" authorize:"!" desc:"new chart page"`
|
||||
Create web.HandlerFunc `path:"/new" method:"post" name:"chart.create" authorize:"!" desc:"create chart"`
|
||||
Edit web.HandlerFunc `path:"/:name/edit" name:"chart.edit" authorize:"!" desc:"edit chart page"`
|
||||
Delete web.HandlerFunc `path:"/:name/delete" method:"post" name:"chart.delete" authorize:"!" desc:"delete chart"`
|
||||
Update web.HandlerFunc `path:"/:name/edit" method:"post" name:"chart.update" authorize:"!" desc:"update chart"`
|
||||
Data web.HandlerFunc `path:"/data" name:"chart.data" authorize:"?" desc:"fetch chart datas"`
|
||||
SaveDashboard web.HandlerFunc `path:"/save_dashboard" method:"post" name:"chart.save_dashboard" authorize:"!" desc:"save dashboard"`
|
||||
}
|
||||
|
||||
// Chart creates an instance of RoleController
|
||||
func Chart() (c *ChartController) {
|
||||
return &ChartController{
|
||||
List: chartList,
|
||||
Query: chartQuery,
|
||||
New: chartNew,
|
||||
Create: chartCreate,
|
||||
Edit: chartEdit,
|
||||
Update: chartUpdate,
|
||||
Delete: chartDelete,
|
||||
Data: chartData,
|
||||
SavePanel: chartSavePanel,
|
||||
List: chartList,
|
||||
Query: chartQuery,
|
||||
New: chartNew,
|
||||
Create: chartCreate,
|
||||
Edit: chartEdit,
|
||||
Update: chartUpdate,
|
||||
Delete: chartDelete,
|
||||
Data: chartData,
|
||||
SaveDashboard: chartSaveDashboard,
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,31 +116,30 @@ func chartDelete(ctx web.Context) error {
|
||||
|
||||
func chartData(ctx web.Context) error {
|
||||
period := cast.ToDuration(ctx.Q("time"), time.Hour)
|
||||
charts := strings.Split(ctx.Q("charts"), ",")
|
||||
key := ctx.Q("key")
|
||||
datas, err := biz.Chart.FetchDatas(key, charts, period)
|
||||
if err != nil {
|
||||
return err
|
||||
if v := ctx.Q("charts"); v != "" {
|
||||
names := strings.Split(v, ",")
|
||||
key := ctx.Q("key")
|
||||
datas, err := biz.Chart.FetchDatas(key, names, period)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.JSON(datas)
|
||||
}
|
||||
return ctx.JSON(datas)
|
||||
return ctx.JSON(data.Map{})
|
||||
}
|
||||
|
||||
func chartSavePanel(ctx web.Context) error {
|
||||
data := struct {
|
||||
Name string `json:"name"`
|
||||
Key string `json:"key"`
|
||||
model.ChartPanel
|
||||
}{}
|
||||
err := ctx.Bind(&data)
|
||||
func chartSaveDashboard(ctx web.Context) error {
|
||||
dashboard := &model.ChartDashboard{}
|
||||
err := ctx.Bind(dashboard)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch data.Name {
|
||||
switch dashboard.Name {
|
||||
case "home":
|
||||
err = biz.Setting.UpdateDashboard(data.Name, &data.ChartPanel, ctx.User())
|
||||
err = biz.Chart.UpdateDashboard(dashboard, ctx.User())
|
||||
default:
|
||||
err = errors.New("unknown dashboard: " + data.Name)
|
||||
err = errors.New("unknown dashboard: " + dashboard.Name)
|
||||
}
|
||||
return ajaxResult(ctx, err)
|
||||
}
|
||||
|
@ -32,10 +32,10 @@ func Home() (c *HomeController) {
|
||||
|
||||
func homeIndex(ctx web.Context) (err error) {
|
||||
var (
|
||||
count int
|
||||
setting *model.Setting
|
||||
charts []*model.Chart
|
||||
m = newModel(ctx)
|
||||
count int
|
||||
dashboard *model.ChartDashboard
|
||||
charts []*model.Chart
|
||||
m = newModel(ctx)
|
||||
)
|
||||
|
||||
if count, err = docker.NodeCount(); err != nil {
|
||||
@ -58,10 +58,10 @@ func homeIndex(ctx web.Context) (err error) {
|
||||
}
|
||||
m.Set("StackCount", count)
|
||||
|
||||
if setting, err = biz.Setting.Get(); err != nil {
|
||||
if dashboard, err = biz.Chart.GetDashboard("home", ""); err != nil {
|
||||
return
|
||||
}
|
||||
charts, err = biz.Chart.Panel(setting.Dashboard.Home)
|
||||
charts, err = biz.Chart.GetDashboardCharts(dashboard)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -62,7 +62,6 @@ type Interface interface {
|
||||
|
||||
SettingGet() (setting *model.Setting, err error)
|
||||
SettingUpdate(setting *model.Setting) error
|
||||
UpdateDashboard(name string, dashboard *model.ChartPanel) error
|
||||
|
||||
ChartGet(name string) (*model.Chart, error)
|
||||
ChartBatch(names ...string) ([]*model.Chart, error)
|
||||
@ -70,6 +69,9 @@ type Interface interface {
|
||||
ChartCreate(chart *model.Chart) error
|
||||
ChartUpdate(chart *model.Chart) error
|
||||
ChartDelete(name string) error
|
||||
|
||||
DashboardGet(name, key string) (dashboard *model.ChartDashboard, err error)
|
||||
DashboardUpdate(dashboard *model.ChartDashboard) error
|
||||
}
|
||||
|
||||
// Get return a dao instance according to DB_TYPE.
|
||||
|
@ -63,3 +63,29 @@ func (d *Dao) ChartDelete(name string) (err error) {
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) DashboardGet(name, key string) (dashboard *model.ChartDashboard, err error) {
|
||||
d.do(func(db *database) {
|
||||
dashboard = &model.ChartDashboard{
|
||||
Name: name,
|
||||
Key: key,
|
||||
}
|
||||
err = db.C("dashboard").FindId(dashboard.ID()).One(dashboard)
|
||||
if err == mgo.ErrNotFound {
|
||||
dashboard, err = nil, nil
|
||||
} else if err != nil {
|
||||
dashboard = nil
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) DashboardUpdate(dashboard *model.ChartDashboard) (err error) {
|
||||
d.do(func(db *database) {
|
||||
update := bson.M{
|
||||
"$set": dashboard,
|
||||
}
|
||||
_, err = db.C("dashboard").UpsertId(dashboard.ID(), update)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
@ -28,17 +28,3 @@ func (d *Dao) SettingUpdate(setting *model.Setting) (err error) {
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) UpdateDashboard(name string, dashboard *model.ChartPanel) (err error) {
|
||||
d.do(func(db *database) {
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"dashboard": bson.M{
|
||||
name: dashboard,
|
||||
},
|
||||
},
|
||||
}
|
||||
err = db.C("setting").UpdateId(settingID, update)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
@ -43,13 +43,20 @@ type ChartItem struct {
|
||||
Colors []string `json:"colors"`
|
||||
}
|
||||
|
||||
type ChartPanel struct {
|
||||
Refresh bool `json:"refresh"`
|
||||
Period int32 `json:"period"` // minutes
|
||||
Charts []ChartItem `json:"charts"`
|
||||
type ChartDashboard struct {
|
||||
Name string `json:"name"`
|
||||
Key string `json:"key"`
|
||||
Period int32 `json:"period"` // minutes
|
||||
RefreshInterval int32 `json:"refresh_interval"` // seconds, 0 means disabled.
|
||||
Charts []ChartItem `json:"charts"`
|
||||
}
|
||||
|
||||
//type ChartPanel []ChartItem
|
||||
func (cd *ChartDashboard) ID() string {
|
||||
if cd.Key == "" {
|
||||
return cd.Name
|
||||
}
|
||||
return cd.Name + ":" + cd.Key
|
||||
}
|
||||
|
||||
type ChartPoint struct {
|
||||
X int64 `json:"x"`
|
||||
|
@ -47,9 +47,6 @@ type Setting struct {
|
||||
Metrics struct {
|
||||
Prometheus string `bson:"prometheus" json:"prometheus"`
|
||||
} `bson:"metrics" json:"metrics"`
|
||||
Dashboard struct {
|
||||
Home ChartPanel `bson:"home" json:"home"`
|
||||
} `bson:"dashboard" json:"dashboard"`
|
||||
UpdatedBy string `bson:"updated_by" json:"updated_by,omitempty"`
|
||||
UpdatedAt time.Time `bson:"updated_at" json:"updated_at,omitempty"`
|
||||
}
|
||||
|
@ -230,6 +230,7 @@ var Perms = []PermGroup{
|
||||
{Key: "chart.create", Text: "Create"},
|
||||
{Key: "chart.delete", Text: "Delete"},
|
||||
{Key: "chart.update", Text: "Update"},
|
||||
{Key: "chart.save_dashboard", Text: "Save dashboard"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -87,16 +87,16 @@
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">{{ .Title }}</p>
|
||||
<a data-action="remove-chart" class="card-header-icon is-paddingless" aria-label="remove chart">
|
||||
<a data-action="remove-chart" class="card-header-icon" aria-label="remove chart">
|
||||
<span class="icon">
|
||||
<i class="fas fa-times has-text-danger" aria-hidden="true"></i>
|
||||
</span>
|
||||
</a>
|
||||
<a data-action="edit-options" class="card-header-icon" aria-label="edit options">
|
||||
<span class="icon">
|
||||
<i class="fas fa-ellipsis-h has-text-info" aria-hidden="true"></i>
|
||||
</span>
|
||||
</a>
|
||||
{*<a data-action="edit-options" class="card-header-icon" aria-label="edit options">*}
|
||||
{*<span class="icon">*}
|
||||
{*<i class="fas fa-ellipsis-h has-text-info" aria-hidden="true"></i>*}
|
||||
{*</span>*}
|
||||
{*</a>*}
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div style="height: {{ .Height }}px">
|
||||
|
Loading…
Reference in New Issue
Block a user