Add action buttons to service detail page

This commit is contained in:
cuigh 2018-06-25 16:53:30 +08:00
parent 1eadf2934b
commit 81c2439ea4
6 changed files with 198 additions and 78 deletions

View File

@ -1781,6 +1781,68 @@ var Swirl;
})(Config = Swirl.Config || (Swirl.Config = {})); })(Config = Swirl.Config || (Swirl.Config = {}));
})(Swirl || (Swirl = {})); })(Swirl || (Swirl = {}));
var Swirl; var Swirl;
(function (Swirl) {
var Container;
(function (Container) {
class ExecPage {
constructor() {
this.$cmd = $("#txt-cmd");
this.$connect = $("#btn-connect");
this.$disconnect = $("#btn-disconnect");
this.$connect.click(this.connect.bind(this));
this.$disconnect.click(this.disconnect.bind(this));
Terminal.applyAddon(fit);
}
connect(e) {
this.$connect.hide();
this.$disconnect.show();
let url = location.host + location.pathname.substring(0, location.pathname.lastIndexOf("/")) + "/connect?cmd=" + encodeURIComponent(this.$cmd.val());
let ws = new WebSocket("ws://" + url);
ws.onopen = () => {
this.term = new Terminal();
this.term.on('data', (data) => {
if (ws.readyState == WebSocket.OPEN) {
ws.send(data);
}
});
this.term.open(document.getElementById('terminal-container'));
this.term.focus();
let width = Math.floor(($('#terminal-container').width() - 20) / 8.39);
let height = 30;
this.term.resize(width, height);
this.term.setOption('cursorBlink', true);
this.term.fit();
window.onresize = () => {
this.term.fit();
};
ws.onmessage = (e) => {
this.term.write(e.data);
};
ws.onerror = function (error) {
console.log("error: " + error);
};
ws.onclose = () => {
console.log("close");
};
};
this.ws = ws;
}
disconnect(e) {
if (this.ws && this.ws.readyState != WebSocket.CLOSED) {
this.ws.close();
}
if (this.term) {
this.term.destroy();
this.term = null;
}
this.$connect.show();
this.$disconnect.hide();
}
}
Container.ExecPage = ExecPage;
})(Container = Swirl.Container || (Swirl.Container = {}));
})(Swirl || (Swirl = {}));
var Swirl;
(function (Swirl) { (function (Swirl) {
var Container; var Container;
(function (Container) { (function (Container) {
@ -2449,21 +2511,20 @@ var Swirl;
let $tr = $(e.target).closest("tr"); let $tr = $(e.target).closest("tr");
let name = $tr.find("td:eq(0)").text().trim(); let name = $tr.find("td:eq(0)").text().trim();
Modal.confirm(`Are you sure to remove service: <strong>${name}</strong>?`, "Delete service", (dlg, e) => { Modal.confirm(`Are you sure to remove service: <strong>${name}</strong>?`, "Delete service", (dlg, e) => {
$ajax.post(`${name}/delete`, { names: name }).trigger(e.target).encoder("form").json(() => { $ajax.post(`${name}/delete`).trigger(e.target).encoder("form").json(() => {
$tr.remove(); $tr.remove();
dlg.close(); dlg.close();
}); });
}); });
} }
scaleService(e) { scaleService(e) {
let $target = $(e.target), $tr = $target.closest("tr"); let $target = $(e.target), $tr = $target.closest("tr"), name = $tr.find("td:eq(0)").text().trim();
let data = { let data = {
name: $tr.find("td:eq(0)").text().trim(),
count: $target.data("replicas"), count: $target.data("replicas"),
}; };
Modal.confirm(`<input name="count" value="${data.count}" class="input" placeholder="Replicas">`, "Scale service", dlg => { Modal.confirm(`<input name="count" value="${data.count}" class="input" placeholder="Replicas">`, "Scale service", dlg => {
data.count = dlg.find("input[name=count]").val(); data.count = dlg.find("input[name=count]").val();
$ajax.post(`${data.name}/scale`, data).encoder("form").json(() => { $ajax.post(`${name}/scale`, data).encoder("form").json(() => {
location.reload(); location.reload();
}); });
}); });
@ -2471,7 +2532,7 @@ var Swirl;
rollbackService(e) { rollbackService(e) {
let $tr = $(e.target).closest("tr"), name = $tr.find("td:eq(0)").text().trim(); let $tr = $(e.target).closest("tr"), name = $tr.find("td:eq(0)").text().trim();
Modal.confirm(`Are you sure to rollback service: <strong>${name}</strong>?`, "Rollback service", dlg => { Modal.confirm(`Are you sure to rollback service: <strong>${name}</strong>?`, "Rollback service", dlg => {
$ajax.post(`${name}/rollback`, { name: name }).encoder("form").json(() => { $ajax.post(`${name}/rollback`).encoder("form").json(() => {
dlg.close(); dlg.close();
}); });
}); });
@ -2479,7 +2540,7 @@ var Swirl;
restartService(e) { restartService(e) {
let $tr = $(e.target).closest("tr"), name = $tr.find("td:eq(0)").text().trim(); let $tr = $(e.target).closest("tr"), name = $tr.find("td:eq(0)").text().trim();
Modal.confirm(`Are you sure to restart service: <strong>${name}</strong>?`, "Restart service", dlg => { Modal.confirm(`Are you sure to restart service: <strong>${name}</strong>?`, "Restart service", dlg => {
$ajax.post(`${name}/restart`, { name: name }).encoder("form").json(() => { $ajax.post(`${name}/restart`).encoder("form").json(() => {
dlg.close(); dlg.close();
}); });
}); });
@ -2837,64 +2898,53 @@ var Swirl;
})(Swirl || (Swirl = {})); })(Swirl || (Swirl = {}));
var Swirl; var Swirl;
(function (Swirl) { (function (Swirl) {
var Container; var Service;
(function (Container) { (function (Service) {
class ExecPage { var Modal = Swirl.Core.Modal;
class DetailPage {
constructor() { constructor() {
this.$cmd = $("#txt-cmd"); $("#btn-delete").click(this.deleteService.bind(this));
this.$connect = $("#btn-connect"); $("#btn-scale").click(this.scaleService.bind(this));
this.$disconnect = $("#btn-disconnect"); $("#btn-restart").click(this.restartService.bind(this));
this.$connect.click(this.connect.bind(this)); $("#btn-rollback").click(this.rollbackService.bind(this));
this.$disconnect.click(this.disconnect.bind(this));
Terminal.applyAddon(fit);
} }
connect(e) { deleteService(e) {
this.$connect.hide(); let name = $("#h2-name").text().trim();
this.$disconnect.show(); Modal.confirm(`Are you sure to remove service: <strong>${name}</strong>?`, "Delete service", (dlg, e) => {
let url = location.host + location.pathname.substring(0, location.pathname.lastIndexOf("/")) + "/connect?cmd=" + encodeURIComponent(this.$cmd.val()); $ajax.post(`delete`).trigger(e.target).encoder("form").json(() => {
let ws = new WebSocket("ws://" + url); location.href = "/service/";
ws.onopen = () => {
this.term = new Terminal();
this.term.on('data', (data) => {
if (ws.readyState == WebSocket.OPEN) {
ws.send(data);
}
}); });
this.term.open(document.getElementById('terminal-container')); });
this.term.focus();
let width = Math.floor(($('#terminal-container').width() - 20) / 8.39);
let height = 30;
this.term.resize(width, height);
this.term.setOption('cursorBlink', true);
this.term.fit();
window.onresize = () => {
this.term.fit();
};
ws.onmessage = (e) => {
this.term.write(e.data);
};
ws.onerror = function (error) {
console.log("error: " + error);
};
ws.onclose = () => {
console.log("close");
};
};
this.ws = ws;
} }
disconnect(e) { scaleService(e) {
if (this.ws && this.ws.readyState != WebSocket.CLOSED) { let data = {
this.ws.close(); count: $("#span-replicas").text().trim(),
} };
if (this.term) { Modal.confirm(`<input name="count" value="${data.count}" class="input" placeholder="Replicas">`, "Scale service", dlg => {
this.term.destroy(); data.count = dlg.find("input[name=count]").val();
this.term = null; $ajax.post(`scale`, data).trigger(e.target).encoder("form").json(() => {
} location.reload();
this.$connect.show(); });
this.$disconnect.hide(); });
}
rollbackService(e) {
let name = $("#h2-name").text().trim();
Modal.confirm(`Are you sure to rollback service: <strong>${name}</strong>?`, "Rollback service", dlg => {
$ajax.post(`rollback`).trigger(e.target).encoder("form").json(() => {
location.reload();
});
});
}
restartService(e) {
let name = $("#h2-name").text().trim();
Modal.confirm(`Are you sure to restart service: <strong>${name}</strong>?`, "Restart service", dlg => {
$ajax.post(`restart`).trigger(e.target).encoder("form").json(() => {
location.reload();
});
});
} }
} }
Container.ExecPage = ExecPage; Service.DetailPage = DetailPage;
})(Container = Swirl.Container || (Swirl.Container = {})); })(Service = Swirl.Service || (Swirl.Service = {}));
})(Swirl || (Swirl = {})); })(Swirl || (Swirl = {}));
//# sourceMappingURL=swirl.js.map //# sourceMappingURL=swirl.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,53 @@
///<reference path="../core/core.ts" />
namespace Swirl.Service {
import Modal = Swirl.Core.Modal;
import AjaxResult = Swirl.Core.AjaxResult;
export class DetailPage {
constructor() {
$("#btn-delete").click(this.deleteService.bind(this));
$("#btn-scale").click(this.scaleService.bind(this));
$("#btn-restart").click(this.restartService.bind(this));
$("#btn-rollback").click(this.rollbackService.bind(this));
}
private deleteService(e: JQueryEventObject) {
let name = $("#h2-name").text().trim();
Modal.confirm(`Are you sure to remove service: <strong>${name}</strong>?`, "Delete service", (dlg, e) => {
$ajax.post(`delete`).trigger(e.target).encoder("form").json<AjaxResult>(() => {
location.href = "/service/";
})
});
}
private scaleService(e: JQueryEventObject) {
let data = {
count: $("#span-replicas").text().trim(),
};
Modal.confirm(`<input name="count" value="${data.count}" class="input" placeholder="Replicas">`, "Scale service", dlg => {
data.count = dlg.find("input[name=count]").val();
$ajax.post(`scale`, data).trigger(e.target).encoder("form").json<AjaxResult>(() => {
location.reload();
})
});
}
private rollbackService(e: JQueryEventObject) {
let name = $("#h2-name").text().trim();
Modal.confirm(`Are you sure to rollback service: <strong>${name}</strong>?`, "Rollback service", dlg => {
$ajax.post(`rollback`).trigger(e.target).encoder("form").json<AjaxResult>(() => {
location.reload();
})
});
}
private restartService(e: JQueryEventObject) {
let name = $("#h2-name").text().trim();
Modal.confirm(`Are you sure to restart service: <strong>${name}</strong>?`, "Restart service", dlg => {
$ajax.post(`restart`).trigger(e.target).encoder("form").json<AjaxResult>(() => {
location.reload();
})
});
}
}
}

View File

@ -21,7 +21,7 @@ namespace Swirl.Service {
let $tr = $(e.target).closest("tr"); let $tr = $(e.target).closest("tr");
let name = $tr.find("td:eq(0)").text().trim(); let name = $tr.find("td:eq(0)").text().trim();
Modal.confirm(`Are you sure to remove service: <strong>${name}</strong>?`, "Delete service", (dlg, e) => { Modal.confirm(`Are you sure to remove service: <strong>${name}</strong>?`, "Delete service", (dlg, e) => {
$ajax.post(`${name}/delete`, {names: name}).trigger(e.target).encoder("form").json<AjaxResult>(() => { $ajax.post(`${name}/delete`).trigger(e.target).encoder("form").json<AjaxResult>(() => {
$tr.remove(); $tr.remove();
dlg.close(); dlg.close();
}) })
@ -30,14 +30,14 @@ namespace Swirl.Service {
private scaleService(e: JQueryEventObject) { private scaleService(e: JQueryEventObject) {
let $target = $(e.target), let $target = $(e.target),
$tr = $target.closest("tr"); $tr = $target.closest("tr"),
name = $tr.find("td:eq(0)").text().trim();
let data = { let data = {
name: $tr.find("td:eq(0)").text().trim(),
count: $target.data("replicas"), count: $target.data("replicas"),
}; };
Modal.confirm(`<input name="count" value="${data.count}" class="input" placeholder="Replicas">`, "Scale service", dlg => { Modal.confirm(`<input name="count" value="${data.count}" class="input" placeholder="Replicas">`, "Scale service", dlg => {
data.count = dlg.find("input[name=count]").val(); data.count = dlg.find("input[name=count]").val();
$ajax.post(`${data.name}/scale`, data).encoder("form").json<AjaxResult>(() => { $ajax.post(`${name}/scale`, data).encoder("form").json<AjaxResult>(() => {
location.reload(); location.reload();
}) })
}); });
@ -47,7 +47,7 @@ namespace Swirl.Service {
let $tr = $(e.target).closest("tr"), let $tr = $(e.target).closest("tr"),
name = $tr.find("td:eq(0)").text().trim(); name = $tr.find("td:eq(0)").text().trim();
Modal.confirm(`Are you sure to rollback service: <strong>${name}</strong>?`, "Rollback service", dlg => { Modal.confirm(`Are you sure to rollback service: <strong>${name}</strong>?`, "Rollback service", dlg => {
$ajax.post(`${name}/rollback`, {name: name}).encoder("form").json<AjaxResult>(() => { $ajax.post(`${name}/rollback`).encoder("form").json<AjaxResult>(() => {
dlg.close(); dlg.close();
}) })
}); });
@ -57,7 +57,7 @@ namespace Swirl.Service {
let $tr = $(e.target).closest("tr"), let $tr = $(e.target).closest("tr"),
name = $tr.find("td:eq(0)").text().trim(); name = $tr.find("td:eq(0)").text().trim();
Modal.confirm(`Are you sure to restart service: <strong>${name}</strong>?`, "Restart service", dlg => { Modal.confirm(`Are you sure to restart service: <strong>${name}</strong>?`, "Restart service", dlg => {
$ajax.post(`${name}/restart`, {name: name}).encoder("form").json<AjaxResult>(() => { $ajax.post(`${name}/restart`).encoder("form").json<AjaxResult>(() => {
dlg.close(); dlg.close();
}) })
}); });

View File

@ -2,7 +2,6 @@ package controller
import ( import (
"strconv" "strconv"
"strings"
"time" "time"
"github.com/cuigh/auxo/data" "github.com/cuigh/auxo/data"
@ -145,14 +144,12 @@ func serviceFetchLogs(ctx web.Context) error {
} }
func serviceDelete(ctx web.Context) error { func serviceDelete(ctx web.Context) error {
names := strings.Split(ctx.F("names"), ",") name := ctx.P("name")
for _, name := range names { err := docker.ServiceRemove(name)
if err := docker.ServiceRemove(name); err != nil { if err == nil {
return ajaxResult(ctx, err)
}
biz.Event.CreateService(model.EventActionDelete, name, ctx.User()) biz.Event.CreateService(model.EventActionDelete, name, ctx.User())
} }
return ajaxSuccess(ctx, nil) return ajaxResult(ctx, err)
} }
func serviceNew(ctx web.Context) error { func serviceNew(ctx web.Context) error {
@ -266,7 +263,7 @@ func serviceUpdate(ctx web.Context) error {
} }
func serviceScale(ctx web.Context) error { func serviceScale(ctx web.Context) error {
name := ctx.F("name") name := ctx.P("name")
count, err := strconv.Atoi(ctx.F("count")) count, err := strconv.Atoi(ctx.F("count"))
if err != nil { if err != nil {
return err return err
@ -280,7 +277,7 @@ func serviceScale(ctx web.Context) error {
} }
func serviceRollback(ctx web.Context) error { func serviceRollback(ctx web.Context) error {
name := ctx.F("name") name := ctx.P("name")
err := docker.ServiceRollback(name) err := docker.ServiceRollback(name)
if err == nil { if err == nil {
biz.Event.CreateService(model.EventActionRollback, name, ctx.User()) biz.Event.CreateService(model.EventActionRollback, name, ctx.User())
@ -289,7 +286,7 @@ func serviceRollback(ctx web.Context) error {
} }
func serviceRestart(ctx web.Context) error { func serviceRestart(ctx web.Context) error {
name := ctx.F("name") name := ctx.P("name")
err := docker.ServiceRestart(name) err := docker.ServiceRestart(name)
if err == nil { if err == nil {
biz.Event.CreateService(model.EventActionRestart, name, ctx.User()) biz.Event.CreateService(model.EventActionRestart, name, ctx.User())

View File

@ -1,6 +1,10 @@
{{ extends "_base" }} {{ extends "_base" }}
{{ import "../_modules/detail" }} {{ import "../_modules/detail" }}
{{ block script() }}
<script>$(() => new Swirl.Service.DetailPage())</script>
{{ end }}
{{ block body_content() }} {{ block body_content() }}
<div class="container"> <div class="container">
<nav class="breadcrumb has-succeeds-separator is-small is-marginless" aria-label="breadcrumbs"> <nav class="breadcrumb has-succeeds-separator is-small is-marginless" aria-label="breadcrumbs">
@ -15,7 +19,7 @@
<section class="hero is-small is-light"> <section class="hero is-small is-light">
<div class="hero-body"> <div class="hero-body">
<div class="container"> <div class="container">
<h2 class="title is-2"> <h2 id="h2-name" class="title is-2">
{{ .Service.Spec.Name }} {{ .Service.Spec.Name }}
</h2> </h2>
</div> </div>
@ -37,6 +41,22 @@
<section class="section"> <section class="section">
<div class="container"> <div class="container">
<div class="buttons">
<button id="btn-delete" class="button is-danger">
<span class="icon"><i class="far fa-trash-alt"></i></span><span>{{ i18n("button.delete") }}</span>
</button>
{{ if .Service.Spec.Mode.Replicated }}
<button id="btn-scale" class="button is-dark">
<span class="icon"><i class="fas fa-adjust"></i></span><span>{{ i18n("button.scale") }}</span>
</button>
{{ end }}
<button id="btn-restart" class="button is-dark">
<span class="icon"><i class="fas fa-redo"></i></span><span>{{ i18n("button.restart") }}</span>
</button>
<button id="btn-rollback" class="button is-dark">
<span class="icon"><i class="fas fa-reply"></i></span><span>{{ i18n("button.rollback") }}</span>
</button>
</div>
<div class="message is-primary"> <div class="message is-primary">
<div class="message-body"> <div class="message-body">
<dl class="is-horizontal is-marginless"> <dl class="is-horizontal is-marginless">
@ -49,7 +69,7 @@
<div class="tags has-addons"> <div class="tags has-addons">
<span class="tag is-info">{{if .Service.Spec.Mode.Replicated}}replicated{{else}}global{{end}}</span> <span class="tag is-info">{{if .Service.Spec.Mode.Replicated}}replicated{{else}}global{{end}}</span>
{{if .Service.Spec.Mode.Replicated}} {{if .Service.Spec.Mode.Replicated}}
<span class="tag is-success">{{.Service.Replicas}}</span> <span id="span-replicas" class="tag is-success">{{.Service.Replicas}}</span>
{{end}} {{end}}
</div> </div>
</dd> </dd>