mirror of
https://github.com/cuigh/swirl
synced 2025-04-30 10:33:23 +00:00
2037 lines
83 KiB
Go
2037 lines
83 KiB
Go
var Swirl;
|
|
(function (Swirl) {
|
|
var Core;
|
|
(function (Core) {
|
|
class Modal {
|
|
constructor(modal) {
|
|
this.$modal = $(modal);
|
|
this.find(".modal-background, .modal-close, .modal-card-head .delete, .modal-card-foot .dismiss").click(e => this.close());
|
|
}
|
|
static initialize() {
|
|
if (!Modal.initialized) {
|
|
$('.modal-trigger').click(function () {
|
|
let target = $(this).data('target');
|
|
let dlg = new Modal("#" + target);
|
|
dlg.show();
|
|
});
|
|
$(document).on('keyup', function (e) {
|
|
if (e.keyCode === 27) {
|
|
Modal.active && Modal.active.close();
|
|
}
|
|
});
|
|
Modal.initialized = true;
|
|
}
|
|
}
|
|
static close() {
|
|
Modal.active && Modal.active.close();
|
|
}
|
|
static current() {
|
|
return Modal.active;
|
|
}
|
|
static alert(content, title, callback) {
|
|
title = title || "Prompt";
|
|
let $elem = $(`<div class="modal">
|
|
<div class="modal-background"></div>
|
|
<div class="modal-card">
|
|
<header class="modal-card-head">
|
|
<p class="modal-card-title">${title}</p>
|
|
<button class="delete"></button>
|
|
</header>
|
|
<section class="modal-card-body">${content}</section>
|
|
<footer class="modal-card-foot">
|
|
<button class="button is-primary">OK</button>
|
|
</footer>
|
|
</div>
|
|
</div>`).appendTo("body");
|
|
let dlg = new Modal($elem);
|
|
callback = callback || function (dlg, e) { dlg.close(); };
|
|
$elem.find(".modal-card-foot>button:first").click(e => callback(dlg, e));
|
|
dlg.deletable = true;
|
|
dlg.show();
|
|
return dlg;
|
|
}
|
|
static confirm(content, title, callback) {
|
|
title = title || "Confirm";
|
|
let $elem = $(`<div class="modal">
|
|
<div class="modal-background"></div>
|
|
<div class="modal-card">
|
|
<header class="modal-card-head">
|
|
<p class="modal-card-title">${title}</p>
|
|
<button class="delete"></button>
|
|
</header>
|
|
<section class="modal-card-body">${content}</section>
|
|
<footer class="modal-card-foot">
|
|
<button class="button is-primary">Confirm</button>
|
|
<button class="button dismiss">Cancel</button>
|
|
</footer>
|
|
</div>
|
|
</div>`).appendTo("body");
|
|
let dlg = new Modal($elem);
|
|
if (callback) {
|
|
$elem.find(".modal-card-foot>button:first").click(e => callback(dlg, e));
|
|
}
|
|
dlg.deletable = true;
|
|
dlg.show();
|
|
return dlg;
|
|
}
|
|
show() {
|
|
Modal.active && Modal.active.close();
|
|
$('html').addClass('is-clipped');
|
|
this.$modal.addClass('is-active').focus();
|
|
this.error();
|
|
Modal.active = this;
|
|
}
|
|
close() {
|
|
$('html').removeClass('is-clipped');
|
|
if (this.deletable) {
|
|
this.$modal.remove();
|
|
}
|
|
else {
|
|
this.$modal.removeClass('is-active');
|
|
}
|
|
Modal.active = null;
|
|
}
|
|
error(msg) {
|
|
let $error = this.find(".modal-card-error");
|
|
if (msg) {
|
|
if (!$error.length) {
|
|
$error = $('<section class="modal-card-error"></section>').insertAfter(this.find(".modal-card-body"));
|
|
}
|
|
$error.html(msg).show();
|
|
}
|
|
else {
|
|
$error.hide();
|
|
}
|
|
}
|
|
find(selector) {
|
|
if (typeof selector === "string") {
|
|
return this.$modal.find(selector);
|
|
}
|
|
else if (selector instanceof Element) {
|
|
return this.$modal.find(selector);
|
|
}
|
|
return this.$modal.find(selector);
|
|
}
|
|
}
|
|
Core.Modal = Modal;
|
|
class Notification {
|
|
constructor(options) {
|
|
this.options = $.extend({}, {
|
|
type: "primary",
|
|
time: 5,
|
|
}, options);
|
|
}
|
|
static show(type, msg, time) {
|
|
let n = new Notification({
|
|
type: type,
|
|
message: msg,
|
|
time: time,
|
|
});
|
|
n.show();
|
|
return n;
|
|
}
|
|
show() {
|
|
this.$elem = $(`<div class="notification is-${this.options.type} has-text-centered is-marginless is-radiusless is-top" style="display:none">${this.options.message}</div>`).appendTo("body").fadeIn(250);
|
|
if (this.options.time > 0) {
|
|
setTimeout(() => this.hide(), this.options.time * 1000);
|
|
}
|
|
}
|
|
hide() {
|
|
this.$elem.fadeTo("slow", 0.01, () => this.$elem.remove());
|
|
}
|
|
}
|
|
Core.Notification = Notification;
|
|
class Tab {
|
|
constructor(tab, content) {
|
|
this.$tab = $(tab);
|
|
this.$content = $(content);
|
|
this.active = this.$tab.find("li.is-active").index();
|
|
if (this.active == -1) {
|
|
this.select(0);
|
|
}
|
|
this.$tab.find("li").click(e => {
|
|
let $li = $(e.target).closest("li");
|
|
if (!$li.hasClass("is-active")) {
|
|
this.select($li.index());
|
|
}
|
|
});
|
|
}
|
|
static initialize() {
|
|
if (!Tab.initialized) {
|
|
$('.tabs').each((i, elem) => {
|
|
let target = $(elem).data("target");
|
|
new Tab(elem, "#" + target);
|
|
});
|
|
Tab.initialized = true;
|
|
}
|
|
}
|
|
select(index) {
|
|
if (this.active != index) {
|
|
this.$tab.find(`li.is-active`).removeClass("is-active");
|
|
this.$tab.find(`li:eq(${index})`).addClass("is-active");
|
|
this.$content.children(":visible").hide();
|
|
$(this.$content.children()[index]).show();
|
|
this.active = index;
|
|
}
|
|
}
|
|
}
|
|
Core.Tab = Tab;
|
|
})(Core = Swirl.Core || (Swirl.Core = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
/*!
|
|
* Swirl Ajax Library v1.0.0
|
|
* Copyright 2017 cuigh. All rights reserved.
|
|
*
|
|
* @author cuigh(noname@live.com)
|
|
*/
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Core;
|
|
(function (Core) {
|
|
class AjaxResult {
|
|
}
|
|
Core.AjaxResult = AjaxResult;
|
|
class AjaxOptions {
|
|
constructor() {
|
|
this.timeout = 30000;
|
|
this.async = true;
|
|
this.encoder = "json";
|
|
}
|
|
static getDefaultOptions() {
|
|
return AjaxOptions.defaultOptions;
|
|
}
|
|
static setDefaultOptions(options) {
|
|
if (options) {
|
|
AjaxOptions.defaultOptions = options;
|
|
}
|
|
}
|
|
}
|
|
AjaxOptions.defaultOptions = new AjaxOptions();
|
|
Core.AjaxOptions = AjaxOptions;
|
|
let AjaxMethod;
|
|
(function (AjaxMethod) {
|
|
AjaxMethod[AjaxMethod["GET"] = 0] = "GET";
|
|
AjaxMethod[AjaxMethod["POST"] = 1] = "POST";
|
|
AjaxMethod[AjaxMethod["PUT"] = 2] = "PUT";
|
|
AjaxMethod[AjaxMethod["DELETE"] = 3] = "DELETE";
|
|
AjaxMethod[AjaxMethod["HEAD"] = 4] = "HEAD";
|
|
AjaxMethod[AjaxMethod["TRACE"] = 5] = "TRACE";
|
|
AjaxMethod[AjaxMethod["OPTIONS"] = 6] = "OPTIONS";
|
|
AjaxMethod[AjaxMethod["CONNECT"] = 7] = "CONNECT";
|
|
AjaxMethod[AjaxMethod["PATCH"] = 8] = "PATCH";
|
|
})(AjaxMethod = Core.AjaxMethod || (Core.AjaxMethod = {}));
|
|
class AjaxRequest {
|
|
constructor(url, method, data) {
|
|
this.options = $.extend({
|
|
url: url,
|
|
method: method,
|
|
data: data,
|
|
preHandler: AjaxRequest.preHandler,
|
|
postHandler: AjaxRequest.postHandler,
|
|
errorHandler: AjaxRequest.errorHandler,
|
|
}, AjaxOptions.getDefaultOptions());
|
|
}
|
|
preHandler(handler) {
|
|
this.options.preHandler = handler;
|
|
return this;
|
|
}
|
|
postHandler(handler) {
|
|
this.options.postHandler = handler;
|
|
return this;
|
|
}
|
|
errorHandler(handler) {
|
|
this.options.errorHandler = handler;
|
|
return this;
|
|
}
|
|
timeout(timeout) {
|
|
this.options.timeout = timeout;
|
|
return this;
|
|
}
|
|
async(async) {
|
|
this.options.async = async;
|
|
return this;
|
|
}
|
|
trigger(elem) {
|
|
this.options.trigger = elem;
|
|
return this;
|
|
}
|
|
json(callback) {
|
|
return this.result("json", callback);
|
|
}
|
|
text(callback) {
|
|
return this.result("text", callback);
|
|
}
|
|
html(callback) {
|
|
return this.result("html", callback);
|
|
}
|
|
result(dataType, callback) {
|
|
this.options.dataType = dataType;
|
|
this.options.preHandler && this.options.preHandler(this.options);
|
|
let settings = this.buildSettings();
|
|
if (callback) {
|
|
$.ajax(settings).done(callback).always(() => {
|
|
this.options.postHandler && this.options.postHandler(this.options);
|
|
}).fail((xhr, textStatus, error) => {
|
|
this.options.errorHandler && this.options.errorHandler(xhr, textStatus, error);
|
|
});
|
|
}
|
|
else {
|
|
return new Promise((resolve, _) => {
|
|
$.ajax(settings).done((r) => {
|
|
resolve(r);
|
|
}).always(() => {
|
|
AjaxRequest.postHandler && AjaxRequest.postHandler(this.options);
|
|
}).fail((xhr, textStatus, error) => {
|
|
AjaxRequest.errorHandler && AjaxRequest.errorHandler(xhr, textStatus, error);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
buildSettings() {
|
|
return {
|
|
url: this.options.url,
|
|
method: AjaxMethod[this.options.method],
|
|
data: this.options.data,
|
|
dataType: this.options.dataType,
|
|
timeout: this.options.timeout,
|
|
async: this.options.async,
|
|
};
|
|
}
|
|
}
|
|
AjaxRequest.preHandler = options => {
|
|
options.trigger && $(options.trigger).prop("disabled", true);
|
|
};
|
|
AjaxRequest.postHandler = options => {
|
|
options.trigger && $(options.trigger).prop("disabled", false);
|
|
};
|
|
AjaxRequest.errorHandler = (xhr, status, err) => {
|
|
let msg;
|
|
if (xhr.responseJSON) {
|
|
let err = xhr.responseJSON;
|
|
msg = err.message;
|
|
if (err.code) {
|
|
msg += `(${err.code})`;
|
|
}
|
|
}
|
|
else if (xhr.status >= 400) {
|
|
msg = xhr.responseText || err || status;
|
|
}
|
|
else {
|
|
return;
|
|
}
|
|
Core.Notification.show("danger", `AJAX: ${msg}`);
|
|
};
|
|
Core.AjaxRequest = AjaxRequest;
|
|
class AjaxGetRequest extends AjaxRequest {
|
|
jsonp(callback) {
|
|
return this.result("jsonp", callback);
|
|
}
|
|
}
|
|
Core.AjaxGetRequest = AjaxGetRequest;
|
|
class AjaxPostRequest extends AjaxRequest {
|
|
encoder(encoder) {
|
|
this.options.encoder = encoder;
|
|
return this;
|
|
}
|
|
buildSettings() {
|
|
let settings = super.buildSettings();
|
|
switch (this.options.encoder) {
|
|
case "none":
|
|
settings.contentType = false;
|
|
break;
|
|
case "json":
|
|
settings.contentType = "application/json; charset=UTF-8";
|
|
settings.data = JSON.stringify(this.options.data);
|
|
break;
|
|
case "form":
|
|
settings.contentType = "application/x-www-form-urlencoded; charset=UTF-8";
|
|
break;
|
|
}
|
|
return settings;
|
|
}
|
|
}
|
|
Core.AjaxPostRequest = AjaxPostRequest;
|
|
class Ajax {
|
|
constructor() {
|
|
}
|
|
static get(url, args) {
|
|
return new AjaxGetRequest(url, AjaxMethod.GET, args);
|
|
}
|
|
static post(url, data) {
|
|
return new AjaxPostRequest(url, AjaxMethod.POST, data);
|
|
}
|
|
}
|
|
Core.Ajax = Ajax;
|
|
})(Core = Swirl.Core || (Swirl.Core = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
let $ajax = Swirl.Core.Ajax;
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Core;
|
|
(function (Core) {
|
|
class NativeRule {
|
|
validate($form, $input, arg) {
|
|
let el = $input[0];
|
|
return { ok: el.checkValidity ? el.checkValidity() : true };
|
|
}
|
|
}
|
|
class RequiredRule {
|
|
validate($form, $input, arg) {
|
|
return { ok: $.trim($input.val()).length > 0 };
|
|
}
|
|
}
|
|
class CheckedRule {
|
|
validate($form, $input, arg) {
|
|
let count = parseInt(arg);
|
|
let siblings = $form.find(`:input:checked[name='${$input.attr("name")}']`);
|
|
return { ok: siblings.length >= count };
|
|
}
|
|
}
|
|
class EmailRule {
|
|
validate($form, $input, arg) {
|
|
const regex = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i;
|
|
let value = $.trim($input.val());
|
|
return { ok: !value || regex.test(value) };
|
|
}
|
|
}
|
|
class UrlRule {
|
|
validate($form, $input, arg) {
|
|
const regex = /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i;
|
|
let value = $.trim($input.val());
|
|
return { ok: !value || regex.test(value) };
|
|
}
|
|
}
|
|
class IPRule {
|
|
validate($form, $input, arg) {
|
|
const regex = /^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})$/i;
|
|
let value = $.trim($input.val());
|
|
return { ok: !value || regex.test(value) };
|
|
}
|
|
}
|
|
class MatchValidator {
|
|
validate($form, $input, arg) {
|
|
return { ok: $input.val() == $('#' + arg).val() };
|
|
}
|
|
}
|
|
class LengthRule {
|
|
validate($form, $input, arg) {
|
|
let r = { ok: true };
|
|
if (arg) {
|
|
let len = this.getLength($.trim($input.val()));
|
|
let args = arg.split('~');
|
|
if (args.length == 1) {
|
|
if ($.isNumeric(args[0])) {
|
|
r.ok = len >= parseInt(args[0]);
|
|
}
|
|
}
|
|
else {
|
|
if ($.isNumeric(args[0]) && $.isNumeric(args[1])) {
|
|
r.ok = len >= parseInt(args[0]) && len <= parseInt(args[1]);
|
|
}
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
getLength(value) {
|
|
return value.length;
|
|
}
|
|
}
|
|
class WidthRule extends LengthRule {
|
|
getLength(value) {
|
|
var doubleByteChars = value.match(/[^\x00-\xff]/ig);
|
|
return value.length + (doubleByteChars == null ? 0 : doubleByteChars.length);
|
|
}
|
|
}
|
|
class IntegerRule {
|
|
validate($form, $input, arg) {
|
|
const regex = /^\d*$/;
|
|
return { ok: regex.test($.trim($input.val())) };
|
|
}
|
|
}
|
|
class RegexRule {
|
|
validate($form, $input, arg) {
|
|
let regex = new RegExp(arg, 'i');
|
|
let value = $.trim($input.val());
|
|
return { ok: !value || regex.test(value) };
|
|
}
|
|
}
|
|
class RemoteRule {
|
|
validate($form, $input, arg) {
|
|
if (!arg) {
|
|
throw new Error("服务器验证地址未设置");
|
|
}
|
|
let value = $.trim($input.val());
|
|
let r = { ok: false };
|
|
$ajax.post(arg, { value: value }).encoder("form").async(false).json(result => {
|
|
r.ok = !result.error;
|
|
r.error = result.error;
|
|
});
|
|
return r;
|
|
}
|
|
}
|
|
class Validator {
|
|
constructor(elem, options) {
|
|
this.form = $(elem);
|
|
this.options = options;
|
|
if (this.form.is("form")) {
|
|
this.form.attr("novalidate", "true");
|
|
}
|
|
this.form.on("click", ':radio[data-v-rule],:checkbox[data-v-rule]', this.checkValue.bind(this));
|
|
this.form.on("change", 'select[data-v-rule],input[type="file"][data-v-rule]', this.checkValue.bind(this));
|
|
this.form.on("blur", ':input[data-v-rule]:not(select,:radio,:checkbox,:file)', this.checkValue.bind(this));
|
|
}
|
|
checkValue(e) {
|
|
let $input = $(e.target);
|
|
let result = this.validateInput($input);
|
|
Validator.mark($input, result);
|
|
}
|
|
static bind(elem, options) {
|
|
let v = $(elem).data("validator");
|
|
if (!v) {
|
|
v = new Validator(elem, options);
|
|
$(elem).data("validator", v);
|
|
}
|
|
return v;
|
|
}
|
|
validate() {
|
|
let results = [];
|
|
this.form.find(Validator.selector).each((i, el) => {
|
|
let $input = $(el);
|
|
let result = this.validateInput($input);
|
|
if (result != null) {
|
|
results.push(result);
|
|
}
|
|
Validator.mark($input, result);
|
|
});
|
|
return results;
|
|
}
|
|
reset() {
|
|
this.form.find(Validator.selector).each((i, el) => {
|
|
let $input = $(el);
|
|
Validator.marker.reset($input);
|
|
});
|
|
}
|
|
static register(name, rule, msg) {
|
|
this.rules[name] = rule;
|
|
this.messages[name] = msg;
|
|
}
|
|
static setMessage(name, msg) {
|
|
this.messages[name] = msg;
|
|
}
|
|
static setMarker(marker) {
|
|
this.marker = marker;
|
|
}
|
|
validateInput($input) {
|
|
let errors = [];
|
|
let rules = ($input.data('v-rule') || 'native').split(';');
|
|
rules.forEach(name => {
|
|
let rule = Validator.rules[name];
|
|
if (rule) {
|
|
let arg = $input.data("v-arg-" + name);
|
|
let r = rule.validate(this.form, $input, arg);
|
|
if (!r.ok) {
|
|
errors.push(r.error || Validator.getMessge($input, name));
|
|
}
|
|
}
|
|
});
|
|
return (errors.length == 0) ? null : {
|
|
input: $input,
|
|
errors: errors,
|
|
};
|
|
}
|
|
static mark($input, result) {
|
|
if (Validator.marker != null) {
|
|
if (result) {
|
|
Validator.marker.setError($input, result.errors);
|
|
}
|
|
else {
|
|
Validator.marker.clearError($input);
|
|
}
|
|
}
|
|
}
|
|
static getMessge($input, rule) {
|
|
if (rule == 'native')
|
|
return $input[0].validationMessage;
|
|
else {
|
|
let msg = $input.data('v-msg-' + rule);
|
|
if (!msg)
|
|
msg = this.messages[rule];
|
|
return msg;
|
|
}
|
|
}
|
|
}
|
|
Validator.selector = ':input[data-v-rule]:not(:submit,:button,:reset,:image,:disabled)';
|
|
Validator.messages = {
|
|
"required": "This field is required",
|
|
"checked": "Number of checked items is invalid",
|
|
"email": "Please input a valid email address",
|
|
"match": "Input confirmation doesn't match",
|
|
"length": "The length of the field does not meet the requirements",
|
|
"width": "The width of the field does not meet the requirements",
|
|
"url": "Please input a valid url",
|
|
"ip": "Please input a valid IPV4 address",
|
|
"integer": "Please input an integer",
|
|
"regex": "Input is invalid",
|
|
"remote": "Input is invalid",
|
|
};
|
|
Validator.rules = {
|
|
"native": new NativeRule(),
|
|
"required": new RequiredRule(),
|
|
"checked": new CheckedRule(),
|
|
"email": new EmailRule(),
|
|
"match": new MatchValidator(),
|
|
"length": new LengthRule(),
|
|
"width": new WidthRule(),
|
|
"url": new UrlRule(),
|
|
"ip": new IPRule(),
|
|
"integer": new IntegerRule(),
|
|
"regex": new RegexRule(),
|
|
"remote": new RemoteRule(),
|
|
};
|
|
Core.Validator = Validator;
|
|
})(Core = Swirl.Core || (Swirl.Core = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
/*!
|
|
* Swirl Form Library v1.0.0
|
|
* Copyright 2017 cuigh. All rights reserved.
|
|
* see also: https://github.com/A1rPun/transForm.js
|
|
*
|
|
* @author cuigh(noname@live.com)
|
|
*/
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Core;
|
|
(function (Core) {
|
|
class FormOptions {
|
|
constructor() {
|
|
this.delimiter = ".";
|
|
this.skipDisabled = true;
|
|
this.skipReadOnly = false;
|
|
this.skipEmpty = false;
|
|
this.useIdOnEmptyName = true;
|
|
this.triggerChange = false;
|
|
}
|
|
}
|
|
Core.FormOptions = FormOptions;
|
|
class Form {
|
|
constructor(elem, options) {
|
|
this.form = $(elem);
|
|
this.options = $.extend(new FormOptions(), options);
|
|
this.validator = Core.Validator.bind(this.form);
|
|
}
|
|
reset() {
|
|
this.form.get(0).reset();
|
|
if (this.validator) {
|
|
this.validator.reset();
|
|
}
|
|
}
|
|
clear() {
|
|
let inputs = this.getFields();
|
|
inputs.each((i, input) => {
|
|
this.clearInput(input);
|
|
});
|
|
if (this.validator) {
|
|
this.validator.reset();
|
|
}
|
|
}
|
|
submit(url) {
|
|
let data = this.serialize();
|
|
return Core.Ajax.post(url || this.form.attr("action"), data);
|
|
}
|
|
validate() {
|
|
if (!this.validator) {
|
|
return true;
|
|
}
|
|
return this.validator.validate().length == 0;
|
|
}
|
|
serialize(nodeCallback) {
|
|
let result = {}, inputs = this.getFields();
|
|
for (let i = 0, l = inputs.length; i < l; i++) {
|
|
let input = inputs[i], key = input.name || this.options.useIdOnEmptyName && input.id;
|
|
if (!key)
|
|
continue;
|
|
let entry = null;
|
|
if (nodeCallback)
|
|
entry = nodeCallback(input);
|
|
if (!entry)
|
|
entry = this.getEntryFromInput(input, key);
|
|
if (typeof entry.value === 'undefined' || entry.value === null
|
|
|| (this.options.skipEmpty && (!entry.value || (this.isArray(entry.value) && !entry.value.length))))
|
|
continue;
|
|
this.saveEntryToResult(result, entry, input, this.options.delimiter);
|
|
}
|
|
return result;
|
|
}
|
|
deserialize(data, nodeCallback) {
|
|
let inputs = this.getFields();
|
|
for (let i = 0, l = inputs.length; i < l; i++) {
|
|
let input = inputs[i], key = input.name || this.options.useIdOnEmptyName && input.id, value = this.getFieldValue(key, data);
|
|
if (typeof value === 'undefined' || value === null) {
|
|
this.clearInput(input);
|
|
continue;
|
|
}
|
|
let mutated = nodeCallback && nodeCallback(input, value);
|
|
if (!mutated)
|
|
this.setValueToInput(input, value);
|
|
}
|
|
}
|
|
static automate() {
|
|
$('form[data-form]').each(function (i, elem) {
|
|
let $form = $(elem);
|
|
let form = new Form($form);
|
|
let type = $form.data("form");
|
|
if (type == "form") {
|
|
$form.submit(e => { return form.validate(); });
|
|
return;
|
|
}
|
|
$form.submit(function () {
|
|
if (!form.validate()) {
|
|
return false;
|
|
}
|
|
let request = form.submit($form.attr("action")).trigger($form.find('button[type="submit"]'));
|
|
if (type == "ajax-form") {
|
|
request.encoder("form");
|
|
}
|
|
request.json((r) => {
|
|
if (r.success) {
|
|
let url = r.url || $form.data("url");
|
|
if (url) {
|
|
if (url === "-") {
|
|
location.reload();
|
|
}
|
|
else {
|
|
location.href = url;
|
|
}
|
|
}
|
|
else {
|
|
let msg = r.message || $form.data("message");
|
|
Core.Notification.show("info", `SUCCESS: ${msg}`, 3);
|
|
}
|
|
}
|
|
else {
|
|
let msg = r.message;
|
|
if (r.code) {
|
|
msg += `({r.code})`;
|
|
}
|
|
Core.Notification.show("danger", `FAILED: ${msg}`);
|
|
}
|
|
});
|
|
return false;
|
|
});
|
|
});
|
|
}
|
|
getEntryFromInput(input, key) {
|
|
let nodeType = input.type && input.type.toLowerCase(), entry = { name: key }, dataType = $(input).data("type");
|
|
switch (nodeType) {
|
|
case 'radio':
|
|
if (input.checked)
|
|
entry.value = input.value === 'on' ? true : input.value;
|
|
break;
|
|
case 'checkbox':
|
|
entry.value = input.checked ? (input.value === 'on' ? true : input.value) : false;
|
|
break;
|
|
case 'select-multiple':
|
|
entry.value = [];
|
|
for (let i = 0, l = input.options.length; i < l; i++)
|
|
if (input.options[i].selected)
|
|
entry.value.push(input.options[i].value);
|
|
break;
|
|
case 'file':
|
|
entry.value = input.value.split('\\').pop();
|
|
break;
|
|
case 'button':
|
|
case 'submit':
|
|
case 'reset':
|
|
break;
|
|
default:
|
|
entry.value = input.value;
|
|
}
|
|
switch (dataType) {
|
|
case "integer":
|
|
entry.value = parseInt(entry.value);
|
|
break;
|
|
case "float":
|
|
entry.value = parseFloat(entry.value);
|
|
break;
|
|
case "bool":
|
|
entry.value = (entry.value === "true") || (entry.value === "1");
|
|
break;
|
|
}
|
|
return entry;
|
|
}
|
|
saveEntryToResult(parent, entry, input, delimiter) {
|
|
if (/\[]$/.test(entry.name) && !entry.value)
|
|
return;
|
|
let parts = this.parseString(entry.name, delimiter);
|
|
for (let i = 0, l = parts.length; i < l; i++) {
|
|
let part = parts[i];
|
|
if (i === l - 1) {
|
|
parent[part] = entry.value;
|
|
}
|
|
else {
|
|
let index = parts[i + 1];
|
|
if (!index || $.isNumeric(index)) {
|
|
if (!this.isArray(parent[part]))
|
|
parent[part] = [];
|
|
if (i === l - 2) {
|
|
parent[part].push(entry.value);
|
|
}
|
|
else {
|
|
if (!this.isObject(parent[part][index]))
|
|
parent[part][index] = {};
|
|
parent = parent[part][index];
|
|
}
|
|
i++;
|
|
}
|
|
else {
|
|
if (!this.isObject(parent[part]))
|
|
parent[part] = {};
|
|
parent = parent[part];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
clearInput(input) {
|
|
let nodeType = input.type && input.type.toLowerCase();
|
|
switch (nodeType) {
|
|
case 'select-one':
|
|
input.selectedIndex = 0;
|
|
break;
|
|
case 'select-multiple':
|
|
for (let i = input.options.length; i--;)
|
|
input.options[i].selected = false;
|
|
break;
|
|
case 'radio':
|
|
case 'checkbox':
|
|
if (input.checked)
|
|
input.checked = false;
|
|
break;
|
|
case 'button':
|
|
case 'submit':
|
|
case 'reset':
|
|
case 'file':
|
|
break;
|
|
default:
|
|
input.value = '';
|
|
}
|
|
if (this.options.triggerChange) {
|
|
$(input).change();
|
|
}
|
|
}
|
|
parseString(str, delimiter) {
|
|
let result = [], split = str.split(delimiter), len = split.length;
|
|
for (let i = 0; i < len; i++) {
|
|
let s = split[i].split('['), l = s.length;
|
|
for (let j = 0; j < l; j++) {
|
|
let key = s[j];
|
|
if (!key) {
|
|
if (j === 0)
|
|
continue;
|
|
if (j !== l - 1)
|
|
throw new Error(`Undefined key is not the last part of the name > ${str}`);
|
|
}
|
|
if (key && key[key.length - 1] === ']')
|
|
key = key.slice(0, -1);
|
|
result.push(key);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
getFields() {
|
|
let inputs = this.form.find("input,select,textarea").filter(':not([data-form-ignore="true"])');
|
|
if (this.options.skipDisabled)
|
|
inputs = inputs.filter(":not([disabled])");
|
|
if (this.options.skipReadOnly)
|
|
inputs = inputs.filter(":not([readonly])");
|
|
return inputs;
|
|
}
|
|
getFieldValue(key, ref) {
|
|
if (!key || !ref)
|
|
return;
|
|
let parts = this.parseString(key, this.options.delimiter);
|
|
for (let i = 0, l = parts.length; i < l; i++) {
|
|
let part = ref[parts[i]];
|
|
if (typeof part === 'undefined' || part === null)
|
|
return;
|
|
if (i === l - 1) {
|
|
return part;
|
|
}
|
|
else {
|
|
let index = parts[i + 1];
|
|
if (index === '') {
|
|
return part;
|
|
}
|
|
else if ($.isNumeric(index)) {
|
|
if (i === l - 2)
|
|
return part[index];
|
|
else
|
|
ref = part[index];
|
|
i++;
|
|
}
|
|
else {
|
|
ref = part;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
setValueToInput(input, value) {
|
|
let nodeType = input.type && input.type.toLowerCase();
|
|
switch (nodeType) {
|
|
case 'radio':
|
|
if (value == input.value)
|
|
input.checked = true;
|
|
break;
|
|
case 'checkbox':
|
|
input.checked = this.isArray(value)
|
|
? this.contains(value, input.value)
|
|
: value === true || value == input.value;
|
|
break;
|
|
case 'select-multiple':
|
|
if (this.isArray(value))
|
|
for (let i = input.options.length; i--;)
|
|
input.options[i].selected = this.contains(value, input.options[i].value);
|
|
else
|
|
input.value = value;
|
|
break;
|
|
case 'button':
|
|
case 'submit':
|
|
case 'reset':
|
|
case 'file':
|
|
break;
|
|
default:
|
|
input.value = value;
|
|
}
|
|
if (this.options.triggerChange) {
|
|
$(input).change();
|
|
}
|
|
}
|
|
contains(array, value) {
|
|
for (let item of array) {
|
|
if (item == value)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
isObject(obj) {
|
|
return typeof obj === 'object';
|
|
}
|
|
isArray(arr) {
|
|
return Array.isArray(arr);
|
|
}
|
|
}
|
|
Core.Form = Form;
|
|
})(Core = Swirl.Core || (Swirl.Core = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Core;
|
|
(function (Core) {
|
|
class Dispatcher {
|
|
constructor(attr) {
|
|
this.events = {};
|
|
this.attr = attr || "action";
|
|
}
|
|
static bind(elem, event = "click") {
|
|
return new Dispatcher().bind(elem, event);
|
|
}
|
|
on(action, handler) {
|
|
this.events[action] = handler;
|
|
return this;
|
|
}
|
|
off(action) {
|
|
delete this.events[action];
|
|
return this;
|
|
}
|
|
bind(elem, event = "click") {
|
|
$(elem).on(event, this.handle.bind(this));
|
|
return this;
|
|
}
|
|
handle(e) {
|
|
let action = $(e.target).closest("[data-" + this.attr + "]").data(this.attr);
|
|
if (action) {
|
|
let handler = this.events[action];
|
|
if (handler) {
|
|
e.stopPropagation();
|
|
handler(e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Core.Dispatcher = Dispatcher;
|
|
})(Core = Swirl.Core || (Swirl.Core = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
/*!
|
|
* Swirl Table Library v1.0.0
|
|
* Copyright 2017 cuigh. All rights reserved.
|
|
*
|
|
* @author cuigh(noname@live.com)
|
|
*/
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Core;
|
|
(function (Core) {
|
|
class Table {
|
|
constructor(table) {
|
|
this.$table = $(table);
|
|
this.dispatcher = Core.Dispatcher.bind(this.$table);
|
|
}
|
|
on(action, handler) {
|
|
this.dispatcher.on(action, handler);
|
|
return this;
|
|
}
|
|
}
|
|
Core.Table = Table;
|
|
class ListTable extends Table {
|
|
constructor(table) {
|
|
super(table);
|
|
this.on("check-all", e => {
|
|
let checked = e.target.checked;
|
|
this.$table.find("tbody>tr").each((i, elem) => {
|
|
$(elem).find("td:first>:checkbox").prop("checked", checked);
|
|
});
|
|
});
|
|
this.on("check", () => {
|
|
let rows = this.$table.find("tbody>tr").length;
|
|
let checkedRows = this.selectedRows().length;
|
|
this.$table.find("thead>tr>th:first>:checkbox").prop("checked", checkedRows > 0 && rows == checkedRows);
|
|
});
|
|
}
|
|
selectedRows() {
|
|
return this.$table.find("tbody>tr").filter((i, elem) => {
|
|
let cb = $(elem).find("td:first>:checkbox");
|
|
return cb.prop("checked");
|
|
});
|
|
}
|
|
selectedKeys() {
|
|
let keys = [];
|
|
this.$table.find("tbody>tr").each((i, elem) => {
|
|
let cb = $(elem).find("td:first>:checkbox");
|
|
if (cb.prop("checked")) {
|
|
keys.push(cb.val());
|
|
}
|
|
});
|
|
return keys;
|
|
}
|
|
}
|
|
Core.ListTable = ListTable;
|
|
class EditTable extends Table {
|
|
constructor(elem) {
|
|
super(elem);
|
|
this.name = this.$table.data("name");
|
|
this.alias = this.name.replace(".", "-");
|
|
this.index = this.$table.find("tbody>tr").length;
|
|
super.on("add-" + this.alias, this.addRow.bind(this)).on("delete-" + this.alias, OptionTable.deleteRow);
|
|
}
|
|
addRow() {
|
|
this.$table.find("tbody").append(this.render());
|
|
this.index++;
|
|
}
|
|
static deleteRow(e) {
|
|
$(e.target).closest("tr").remove();
|
|
}
|
|
}
|
|
Core.EditTable = EditTable;
|
|
class OptionTable extends EditTable {
|
|
constructor(elem) {
|
|
super(elem);
|
|
}
|
|
render() {
|
|
return `<tr>
|
|
<td><input name="${this.name}s[${this.index}].name" class="input is-small" type="text"></td>
|
|
<td><input name="${this.name}s[${this.index}].value" class="input is-small" type="text"></td>
|
|
<td>
|
|
<a class="button is-small is-danger is-outlined" data-action="delete-${this.alias}">
|
|
<span class="icon is-small"><i class="fa fa-trash"></i></span>
|
|
</a>
|
|
</td>
|
|
</tr>`;
|
|
}
|
|
}
|
|
Core.OptionTable = OptionTable;
|
|
})(Core = Swirl.Core || (Swirl.Core = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Core;
|
|
(function (Core) {
|
|
class BulmaMarker {
|
|
setError($input, errors) {
|
|
let $field = this.getField($input);
|
|
$input.removeClass('is-success').addClass('is-danger');
|
|
let $errors = $field.find('div.errors');
|
|
if (!$errors.length) {
|
|
$errors = $('<div class="errors"/>').appendTo($field);
|
|
}
|
|
$errors.empty().append($.map(errors, (err) => `<p class="help is-danger">${err}</p>`)).show();
|
|
}
|
|
clearError($input) {
|
|
let $field = this.getField($input);
|
|
$input.removeClass('is-danger').addClass('is-success');
|
|
let $errors = $field.find("div.errors");
|
|
$errors.empty().hide();
|
|
}
|
|
reset($input) {
|
|
let $field = this.getField($input);
|
|
$input.removeClass('is-danger is-success');
|
|
let $errors = $field.find("div.errors");
|
|
$errors.empty().hide();
|
|
}
|
|
getField($input) {
|
|
let $field = $input.closest(".field");
|
|
if ($field.hasClass("has-addons") || $field.hasClass("is-grouped")) {
|
|
$field = $field.parent();
|
|
}
|
|
return $field;
|
|
}
|
|
}
|
|
$(() => {
|
|
$('.navbar-burger').click(function () {
|
|
let $el = $(this);
|
|
let $target = $('#' + $el.data('target'));
|
|
$el.toggleClass('is-active');
|
|
$target.toggleClass('is-active');
|
|
});
|
|
Core.Modal.initialize();
|
|
Core.Tab.initialize();
|
|
Core.AjaxRequest.preHandler = opts => opts.trigger && $(opts.trigger).addClass("is-loading");
|
|
Core.AjaxRequest.postHandler = opts => opts.trigger && $(opts.trigger).removeClass("is-loading");
|
|
Core.Validator.setMarker(new BulmaMarker());
|
|
Core.Form.automate();
|
|
});
|
|
})(Core = Swirl.Core || (Swirl.Core = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Config;
|
|
(function (Config) {
|
|
var Modal = Swirl.Core.Modal;
|
|
var Table = Swirl.Core.ListTable;
|
|
class ListPage {
|
|
constructor() {
|
|
this.table = new Table("#table-items");
|
|
this.table.on("delete-config", this.deleteConfig.bind(this));
|
|
$("#btn-delete").click(this.deleteConfigs.bind(this));
|
|
}
|
|
deleteConfig(e) {
|
|
let $tr = $(e.target).closest("tr");
|
|
let name = $tr.find("td:eq(1)").text().trim();
|
|
let id = $tr.find(":checkbox:first").val();
|
|
Modal.confirm(`Are you sure to remove config: <strong>${name}</strong>?`, "Delete config", (dlg, e) => {
|
|
$ajax.post("delete", { ids: id }).trigger(e.target).encoder("form").json(r => {
|
|
$tr.remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
deleteConfigs(e) {
|
|
let ids = this.table.selectedKeys();
|
|
if (ids.length == 0) {
|
|
Modal.alert("Please select one or more items.");
|
|
return;
|
|
}
|
|
Modal.confirm(`Are you sure to remove ${ids.length} configs?`, "Delete configs", (dlg, e) => {
|
|
$ajax.post("delete", { ids: ids.join(",") }).trigger(e.target).encoder("form").json(r => {
|
|
this.table.selectedRows().remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
Config.ListPage = ListPage;
|
|
})(Config = Swirl.Config || (Swirl.Config = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Config;
|
|
(function (Config) {
|
|
var OptionTable = Swirl.Core.OptionTable;
|
|
class NewPage {
|
|
constructor() {
|
|
new OptionTable("#table-labels");
|
|
}
|
|
}
|
|
Config.NewPage = NewPage;
|
|
})(Config = Swirl.Config || (Swirl.Config = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Container;
|
|
(function (Container) {
|
|
var Modal = Swirl.Core.Modal;
|
|
var Table = Swirl.Core.ListTable;
|
|
class ListPage {
|
|
constructor() {
|
|
this.table = new Table("#table-items");
|
|
this.table.on("delete-container", this.deleteContainer.bind(this));
|
|
$("#btn-delete").click(this.deleteContainers.bind(this));
|
|
}
|
|
deleteContainer(e) {
|
|
let $tr = $(e.target).closest("tr");
|
|
let name = $tr.find("td:eq(1)").text().trim();
|
|
let id = $tr.find(":checkbox:first").val();
|
|
Modal.confirm(`Are you sure to remove container: <strong>${name}</strong>?`, "Delete container", (dlg, e) => {
|
|
$ajax.post("delete", { ids: id }).trigger(e.target).encoder("form").json(() => {
|
|
$tr.remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
deleteContainers() {
|
|
let ids = this.table.selectedKeys();
|
|
if (ids.length == 0) {
|
|
Modal.alert("Please select one or more items.");
|
|
return;
|
|
}
|
|
Modal.confirm(`Are you sure to remove ${ids.length} containers?`, "Delete containers", (dlg, e) => {
|
|
$ajax.post("delete", { ids: ids.join(",") }).trigger(e.target).encoder("form").json(() => {
|
|
this.table.selectedRows().remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
Container.ListPage = ListPage;
|
|
})(Container = Swirl.Container || (Swirl.Container = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Image;
|
|
(function (Image) {
|
|
var Modal = Swirl.Core.Modal;
|
|
var Table = Swirl.Core.ListTable;
|
|
class ListPage {
|
|
constructor() {
|
|
this.table = new Table("#table-items");
|
|
this.table.on("delete-image", this.deleteImage.bind(this));
|
|
$("#btn-delete").click(this.deleteImages.bind(this));
|
|
}
|
|
deleteImage(e) {
|
|
let $tr = $(e.target).closest("tr");
|
|
let name = $tr.find("td:eq(1)").text().trim();
|
|
let id = $tr.find(":checkbox:first").val();
|
|
Modal.confirm(`Are you sure to remove image: <strong>${name}</strong>?`, "Delete image", (dlg, e) => {
|
|
$ajax.post("delete", { ids: id }).trigger(e.target).encoder("form").json(() => {
|
|
$tr.remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
deleteImages() {
|
|
let ids = this.table.selectedKeys();
|
|
if (ids.length == 0) {
|
|
Modal.alert("Please select one or more items.");
|
|
return;
|
|
}
|
|
Modal.confirm(`Are you sure to remove ${ids.length} images?`, "Delete images", (dlg, e) => {
|
|
$ajax.post("delete", { ids: ids.join(",") }).trigger(e.target).encoder("form").json(() => {
|
|
this.table.selectedRows().remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
Image.ListPage = ListPage;
|
|
})(Image = Swirl.Image || (Swirl.Image = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Network;
|
|
(function (Network) {
|
|
var Modal = Swirl.Core.Modal;
|
|
var Dispatcher = Swirl.Core.Dispatcher;
|
|
class DetailPage {
|
|
constructor() {
|
|
let dispatcher = Dispatcher.bind("#table-containers");
|
|
dispatcher.on("disconnect", this.disconnect.bind(this));
|
|
}
|
|
disconnect(e) {
|
|
let $btn = $(e.target);
|
|
let $tr = $btn.closest("tr");
|
|
let id = $btn.val();
|
|
let name = $tr.find("td:first").text().trim();
|
|
Modal.confirm(`Are you sure to disconnect container: <strong>${name}</strong>?`, "Disconnect container", (dlg, e) => {
|
|
$ajax.post("disconnect", { container: id }).trigger($btn).encoder("form").json(r => {
|
|
$tr.remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
Network.DetailPage = DetailPage;
|
|
})(Network = Swirl.Network || (Swirl.Network = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Network;
|
|
(function (Network) {
|
|
var Modal = Swirl.Core.Modal;
|
|
var Dispatcher = Swirl.Core.Dispatcher;
|
|
class ListPage {
|
|
constructor() {
|
|
let dispatcher = Dispatcher.bind("#table-items");
|
|
dispatcher.on("delete-network", this.deleteNetwork.bind(this));
|
|
}
|
|
deleteNetwork(e) {
|
|
let $tr = $(e.target).closest("tr");
|
|
let name = $tr.find("td:first").text().trim();
|
|
Modal.confirm(`Are you sure to remove network: <strong>${name}</strong>?`, "Delete network", (dlg, e) => {
|
|
$ajax.post("delete", { name: name }).trigger(e.target).encoder("form").json(r => {
|
|
$tr.remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
Network.ListPage = ListPage;
|
|
})(Network = Swirl.Network || (Swirl.Network = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Network;
|
|
(function (Network) {
|
|
var OptionTable = Swirl.Core.OptionTable;
|
|
class NewPage {
|
|
constructor() {
|
|
new OptionTable("#table-options");
|
|
new OptionTable("#table-labels");
|
|
$("#drivers :radio[name=driver]").change(e => {
|
|
$("#txt-custom-driver").prop("disabled", $(e.target).val() != "other");
|
|
});
|
|
$("#ipv6_enabled").change(e => {
|
|
let enabled = $(e.target).prop("checked");
|
|
$("#ipv6_subnet,#ipv6_gateway").prop("disabled", !enabled);
|
|
});
|
|
}
|
|
}
|
|
Network.NewPage = NewPage;
|
|
})(Network = Swirl.Network || (Swirl.Network = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Node;
|
|
(function (Node) {
|
|
var OptionTable = Swirl.Core.OptionTable;
|
|
class EditPage {
|
|
constructor() {
|
|
new OptionTable("#table-labels");
|
|
}
|
|
}
|
|
Node.EditPage = EditPage;
|
|
})(Node = Swirl.Node || (Swirl.Node = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Node;
|
|
(function (Node) {
|
|
var Modal = Swirl.Core.Modal;
|
|
var Dispatcher = Swirl.Core.Dispatcher;
|
|
class ListPage {
|
|
constructor() {
|
|
let dispatcher = Dispatcher.bind("#table-items");
|
|
dispatcher.on("delete-node", this.deleteNode.bind(this));
|
|
}
|
|
deleteNode(e) {
|
|
let $btn = $(e.target);
|
|
let $tr = $btn.closest("tr");
|
|
let id = $btn.val();
|
|
let name = $tr.find("td:first").text().trim();
|
|
Modal.confirm(`Are you sure to remove node: <strong>${name}</strong>?`, "Delete node", (dlg, e) => {
|
|
$ajax.post("delete", { id: id }).trigger(e.target).encoder("form").json(r => {
|
|
$tr.remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
Node.ListPage = ListPage;
|
|
})(Node = Swirl.Node || (Swirl.Node = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Registry;
|
|
(function (Registry) {
|
|
var Modal = Swirl.Core.Modal;
|
|
var Dispatcher = Swirl.Core.Dispatcher;
|
|
class ListPage {
|
|
constructor() {
|
|
let dispatcher = Dispatcher.bind("#table-items");
|
|
dispatcher.on("delete-registry", this.deleteRegistry.bind(this));
|
|
dispatcher.on("edit-registry", this.editRegistry.bind(this));
|
|
}
|
|
deleteRegistry(e) {
|
|
let $tr = $(e.target).closest("tr");
|
|
let id = $tr.data("id");
|
|
let name = $tr.find("td:first").text().trim();
|
|
Modal.confirm(`Are you sure to remove registry: <strong>${name}</strong>?`, "Delete registry", (dlg, e) => {
|
|
$ajax.post("delete", { id: id }).trigger(e.target).encoder("form").json(r => {
|
|
$tr.remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
editRegistry(e) {
|
|
let $tr = $(e.target).closest("tr");
|
|
let dlg = new Modal("#dlg-edit");
|
|
dlg.find("input[name=id]").val($tr.data("id"));
|
|
dlg.find("input[name=name]").val($tr.find("td:first").text().trim());
|
|
dlg.find("input[name=url]").val($tr.find("td:eq(1)").text().trim());
|
|
dlg.find("input[name=username]").val($tr.find("td:eq(2)").text().trim());
|
|
dlg.show();
|
|
}
|
|
}
|
|
Registry.ListPage = ListPage;
|
|
})(Registry = Swirl.Registry || (Swirl.Registry = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Role;
|
|
(function (Role) {
|
|
var Dispatcher = Swirl.Core.Dispatcher;
|
|
class EditPage {
|
|
constructor() {
|
|
$("#table-perms").find("tr").each((i, elem) => {
|
|
let $tr = $(elem);
|
|
let $cbs = $tr.find("td :checkbox");
|
|
$tr.find("th>:checkbox").prop("checked", $cbs.length == $cbs.filter(":checked").length);
|
|
});
|
|
Dispatcher.bind("#table-perms", "change")
|
|
.on("check-row", this.checkRow.bind(this))
|
|
.on("check", this.check.bind(this));
|
|
}
|
|
checkRow(e) {
|
|
let $cb = $(e.target);
|
|
let checked = $cb.prop("checked");
|
|
$cb.closest("th").next("td").find(":checkbox").prop("checked", checked);
|
|
}
|
|
check(e) {
|
|
let $cb = $(e.target);
|
|
let $cbs = $cb.closest("td").find(":checkbox");
|
|
let checked = $cbs.length == $cbs.filter(":checked").length;
|
|
$cb.closest("td").prev("th").find(":checkbox").prop("checked", checked);
|
|
}
|
|
}
|
|
Role.EditPage = EditPage;
|
|
})(Role = Swirl.Role || (Swirl.Role = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Role;
|
|
(function (Role) {
|
|
var Modal = Swirl.Core.Modal;
|
|
var Dispatcher = Swirl.Core.Dispatcher;
|
|
class ListPage {
|
|
constructor() {
|
|
Dispatcher.bind("#table-items")
|
|
.on("delete-role", this.deleteUser.bind(this));
|
|
}
|
|
deleteUser(e) {
|
|
let $tr = $(e.target).closest("tr");
|
|
let id = $tr.data("id");
|
|
let name = $tr.find("td:first").text().trim();
|
|
Modal.confirm(`Are you sure to remove role: <strong>${name}</strong>?`, "Delete role", (dlg, e) => {
|
|
$ajax.post("delete", { id: id }).trigger(e.target).encoder("form").json(r => {
|
|
$tr.remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
Role.ListPage = ListPage;
|
|
})(Role = Swirl.Role || (Swirl.Role = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Role;
|
|
(function (Role) {
|
|
var Dispatcher = Swirl.Core.Dispatcher;
|
|
class NewPage {
|
|
constructor() {
|
|
Dispatcher.bind("#table-perms", "change")
|
|
.on("check-row", this.checkRow.bind(this))
|
|
.on("check", this.check.bind(this));
|
|
}
|
|
checkRow(e) {
|
|
let $cb = $(e.target);
|
|
let checked = $cb.prop("checked");
|
|
$cb.closest("th").next("td").find(":checkbox").prop("checked", checked);
|
|
}
|
|
check(e) {
|
|
let $cb = $(e.target);
|
|
let $cbs = $cb.closest("td").find(":checkbox");
|
|
let checked = $cbs.length == $cbs.filter(":checked").length;
|
|
$cb.closest("td").prev("th").find(":checkbox").prop("checked", checked);
|
|
}
|
|
}
|
|
Role.NewPage = NewPage;
|
|
})(Role = Swirl.Role || (Swirl.Role = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Secret;
|
|
(function (Secret) {
|
|
var Modal = Swirl.Core.Modal;
|
|
var Table = Swirl.Core.ListTable;
|
|
class ListPage {
|
|
constructor() {
|
|
this.table = new Table("#table-items");
|
|
this.table.on("delete-secret", this.deleteSecret.bind(this));
|
|
$("#btn-delete").click(this.deleteSecrets.bind(this));
|
|
}
|
|
deleteSecret(e) {
|
|
let $tr = $(e.target).closest("tr");
|
|
let name = $tr.find("td:eq(1)").text().trim();
|
|
let id = $tr.find(":checkbox:first").val();
|
|
Modal.confirm(`Are you sure to remove secret: <strong>${name}</strong>?`, "Delete secret", (dlg, e) => {
|
|
$ajax.post("delete", { ids: id }).trigger(e.target).encoder("form").json(r => {
|
|
$tr.remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
deleteSecrets(e) {
|
|
let ids = this.table.selectedKeys();
|
|
if (ids.length == 0) {
|
|
Modal.alert("Please select one or more items.");
|
|
return;
|
|
}
|
|
Modal.confirm(`Are you sure to remove ${ids.length} secrets?`, "Delete secrets", (dlg, e) => {
|
|
$ajax.post("delete", { ids: ids.join(",") }).trigger(e.target).encoder("form").json(r => {
|
|
this.table.selectedRows().remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
Secret.ListPage = ListPage;
|
|
})(Secret = Swirl.Secret || (Swirl.Secret = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Secret;
|
|
(function (Secret) {
|
|
var OptionTable = Swirl.Core.OptionTable;
|
|
class NewPage {
|
|
constructor() {
|
|
new OptionTable("#table-labels");
|
|
}
|
|
}
|
|
Secret.NewPage = NewPage;
|
|
})(Secret = Swirl.Secret || (Swirl.Secret = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Service;
|
|
(function (Service) {
|
|
var Validator = Swirl.Core.Validator;
|
|
var OptionTable = Swirl.Core.OptionTable;
|
|
var EditTable = Swirl.Core.EditTable;
|
|
var Modal = Swirl.Core.Modal;
|
|
var Table = Swirl.Core.Table;
|
|
class ServiceModeRule {
|
|
constructor($model) {
|
|
this.$mode = $model;
|
|
}
|
|
validate($form, $input, arg) {
|
|
if (this.$mode.val() == "global") {
|
|
return { ok: true };
|
|
}
|
|
const regex = /^(0|[1-9]\d*)$/;
|
|
return { ok: regex.test($.trim($input.val())) };
|
|
}
|
|
}
|
|
class MountTable extends EditTable {
|
|
render() {
|
|
return `<tr>
|
|
<td>
|
|
<div class="select is-small">
|
|
<select name="mounts[${this.index}].type">
|
|
<option value="bind">Bind</option>
|
|
<option value="volume">Volume</option>
|
|
<option value="tmpfs">TempFS</option>
|
|
</select>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<input name="mounts[${this.index}].src" class="input is-small" placeholder="path in host">
|
|
</td>
|
|
<td><input name="mounts[${this.index}].dst" class="input is-small" placeholder="path in container"></td>
|
|
<td>
|
|
<div class="select is-small">
|
|
<select name="mounts[${this.index}].read_only" data-type="bool">
|
|
<option value="false">No</option>
|
|
<option value="true">Yes</option>
|
|
</select>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div class="select is-small">
|
|
<select name="mounts[${this.index}].propagation">
|
|
<option value="">--Select--</option>
|
|
<option value="rprivate">rprivate</option>
|
|
<option value="private">private</option>
|
|
<option value="rshared">rshared</option>
|
|
<option value="shared">shared</option>
|
|
<option value="rslave">rslave</option>
|
|
<option value="slave">slave</option>
|
|
</select>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<a class="button is-small is-outlined is-danger" data-action="delete-mount">
|
|
<span class="icon is-small">
|
|
<i class="fa fa-trash"></i>
|
|
</span>
|
|
</a>
|
|
</td>
|
|
</tr>`;
|
|
}
|
|
}
|
|
class PortTable extends EditTable {
|
|
render() {
|
|
return `<tr>
|
|
<td><input name="endpoint.ports[${this.index}].published_port" class="input is-small" placeholder="port in host" data-type="integer"></td>
|
|
<td>
|
|
<input name="endpoint.ports[${this.index}].target_port" class="input is-small" placeholder="port in container" data-type="integer">
|
|
</td>
|
|
<td>
|
|
<div class="select is-small">
|
|
<select name="endpoint.ports[${this.index}].protocol">
|
|
<option value="false">TCP</option>
|
|
<option value="true">UDP</option>
|
|
</select>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div class="select is-small">
|
|
<select name="endpoint.ports[${this.index}].publish_mode">
|
|
<option value="ingress">ingress</option>
|
|
<option value="host">host</option>
|
|
</select>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<a class="button is-small is-outlined is-danger" data-action="delete-endpoint-port">
|
|
<span class="icon is-small">
|
|
<i class="fa fa-trash"></i>
|
|
</span>
|
|
</a>
|
|
</td>
|
|
</tr>`;
|
|
}
|
|
}
|
|
class ConstraintTable extends EditTable {
|
|
render() {
|
|
return `<tr>
|
|
<td>
|
|
<input name="placement.constraints[${this.index}].name" class="input is-small" placeholder="e.g. node.role/node.hostname/node.id/node.labels.*/engine.labels.*/...">
|
|
</td>
|
|
<td>
|
|
<div class="select is-small">
|
|
<select name="placement.constraints[${this.index}].op">
|
|
<option value="==">==</option>
|
|
<option value="!=">!=</option>
|
|
</select>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<input name="placement.constraints[${this.index}].value" class="input is-small" placeholder="e.g. manager">
|
|
</td>
|
|
<td>
|
|
<a class="button is-small is-outlined is-danger" data-action="delete-constraint">
|
|
<span class="icon is-small">
|
|
<i class="fa fa-trash"></i>
|
|
</span>
|
|
</a>
|
|
</td>
|
|
</tr>`;
|
|
}
|
|
}
|
|
class PreferenceTable extends EditTable {
|
|
render() {
|
|
return `<tr>
|
|
<td>
|
|
<input name="placement.preferences[${this.index}].spread" class="input is-small" placeholder="e.g. engine.labels.az">
|
|
</td>
|
|
<td>
|
|
<a class="button is-small is-outlined is-danger" data-action="delete-preference">
|
|
<span class="icon is-small">
|
|
<i class="fa fa-trash"></i>
|
|
</span>
|
|
</a>
|
|
</td>
|
|
</tr>`;
|
|
}
|
|
}
|
|
class ConfigTable extends Table {
|
|
constructor(elem) {
|
|
super(elem);
|
|
this.name = this.$table.data("name");
|
|
this.$body = this.$table.find("tbody");
|
|
this.index = this.$body.find("tr").length;
|
|
super.on("add-" + this.name, this.showAddDialog.bind(this)).on("delete-" + this.name, ConfigTable.deleteRow);
|
|
}
|
|
addRow(id, name) {
|
|
let field = `${this.name}s[${this.index}]`;
|
|
this.$body.append(`<tr>
|
|
<td>${name}<input name="${field}.id" value="${id}" type="hidden"><input name="${field}.name" value="${name}" type="hidden"></td>
|
|
<td><input name="${field}.file_name" value="${name}" class="input is-small"></td>
|
|
<td><input name="${field}.uid" value="0" class="input is-small"></td>
|
|
<td><input name="${field}.gid" value="0" class="input is-small"></td>
|
|
<td><input name="${field}.mode" value="444" class="input is-small" data-type="integer"></td>
|
|
<td>
|
|
<a class="button is-small is-outlined is-danger" data-action="delete-${this.name}">
|
|
<span class="icon is-small">
|
|
<i class="fa fa-remove"></i>
|
|
</span>
|
|
</a>
|
|
</td>
|
|
</tr>`);
|
|
this.index++;
|
|
}
|
|
showAddDialog(e) {
|
|
let dlg = new Modal("#dlg-add-" + this.name);
|
|
dlg.find(":checked").prop("checked", false);
|
|
dlg.error();
|
|
dlg.show();
|
|
}
|
|
static deleteRow(e) {
|
|
$(e.target).closest("tr").remove();
|
|
}
|
|
}
|
|
class EditPage {
|
|
constructor() {
|
|
this.$mode = $("#cb-mode");
|
|
this.$replicas = $("#txt-replicas");
|
|
new OptionTable("#table-envs");
|
|
new OptionTable("#table-slabels");
|
|
new OptionTable("#table-clabels");
|
|
new OptionTable("#table-log_driver-options");
|
|
new PortTable("#table-endpoint-ports");
|
|
new MountTable("#table-mounts");
|
|
new ConstraintTable("#table-constraints");
|
|
new PreferenceTable("#table-preferences");
|
|
this.secret = new ConfigTable("#table-secrets");
|
|
this.config = new ConfigTable("#table-configs");
|
|
Validator.register("service-mode", new ServiceModeRule(this.$mode), "Please input a valid integer.");
|
|
this.$mode.change(e => this.$replicas.toggle(this.$mode.val() != "global"));
|
|
$("#btn-add-secret").click(() => EditPage.addConfig(this.secret));
|
|
$("#btn-add-config").click(() => EditPage.addConfig(this.config));
|
|
}
|
|
static addConfig(t) {
|
|
let dlg = Modal.current();
|
|
let $cbs = dlg.find(":checked");
|
|
if ($cbs.length == 0) {
|
|
dlg.error(`Please select the ${t.name} files.`);
|
|
}
|
|
else {
|
|
dlg.close();
|
|
$cbs.each((i, cb) => {
|
|
let $cb = $(cb);
|
|
t.addRow($cb.val(), $cb.data("name"));
|
|
});
|
|
}
|
|
}
|
|
}
|
|
Service.EditPage = EditPage;
|
|
class NewPage extends EditPage {
|
|
constructor() {
|
|
super();
|
|
this.$registryUrl = $("#a-registry-url");
|
|
this.$registry = $("#cb-registry");
|
|
this.$registry.change(e => {
|
|
let url = this.$registry.find("option:selected").data("url") || "";
|
|
this.$registryUrl.text(url + "/").toggle(url != "");
|
|
});
|
|
}
|
|
}
|
|
Service.NewPage = NewPage;
|
|
})(Service = Swirl.Service || (Swirl.Service = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Service;
|
|
(function (Service) {
|
|
var Modal = Swirl.Core.Modal;
|
|
var Table = Swirl.Core.ListTable;
|
|
class ListPage {
|
|
constructor() {
|
|
this.table = new Table("#table-items");
|
|
this.table.on("delete-service", this.deleteService.bind(this))
|
|
.on("scale-service", this.scaleService.bind(this))
|
|
.on("rollback-service", this.rollbackService.bind(this));
|
|
$("#btn-delete").click(this.deleteServices.bind(this));
|
|
}
|
|
deleteService(e) {
|
|
let $tr = $(e.target).closest("tr");
|
|
let name = $tr.find("td:eq(1)").text().trim();
|
|
Modal.confirm(`Are you sure to remove service: <strong>${name}</strong>?`, "Delete service", (dlg, e) => {
|
|
$ajax.post("delete", { names: name }).trigger(e.target).encoder("form").json(() => {
|
|
$tr.remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
deleteServices() {
|
|
let names = this.table.selectedKeys();
|
|
if (names.length == 0) {
|
|
Modal.alert("Please select one or more items.");
|
|
return;
|
|
}
|
|
Modal.confirm(`Are you sure to remove ${names.length} services?`, "Delete services", (dlg, e) => {
|
|
$ajax.post("delete", { names: names.join(",") }).trigger(e.target).encoder("form").json(() => {
|
|
this.table.selectedRows().remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
scaleService(e) {
|
|
let $btn = $(e.target).closest("button");
|
|
let $tr = $btn.closest("tr");
|
|
let data = {
|
|
name: $tr.find("td:eq(1)").text().trim(),
|
|
count: $btn.data("replicas"),
|
|
};
|
|
Modal.confirm(`<input name="count" value="${data.count}" class="input" placeholder="Replicas">`, "Scale service", (dlg, e) => {
|
|
data.count = dlg.find("input[name=count]").val();
|
|
$ajax.post("scale", data).trigger(e.target).encoder("form").json(() => {
|
|
location.reload();
|
|
});
|
|
});
|
|
}
|
|
rollbackService(e) {
|
|
let $btn = $(e.target).closest("button"), $tr = $btn.closest("tr"), name = $tr.find("td:eq(1)").text().trim();
|
|
Modal.confirm(`Are you sure to rollback service: <strong>${name}</strong>?`, "Rollback service", (dlg, e) => {
|
|
$ajax.post("rollback", { name: name }).trigger(e.target).encoder("form").json(() => {
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
Service.ListPage = ListPage;
|
|
})(Service = Swirl.Service || (Swirl.Service = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Service;
|
|
(function (Service) {
|
|
var Template;
|
|
(function (Template) {
|
|
var Modal = Swirl.Core.Modal;
|
|
var Dispatcher = Swirl.Core.Dispatcher;
|
|
class ListPage {
|
|
constructor() {
|
|
let dispatcher = Dispatcher.bind("#table-items");
|
|
dispatcher.on("delete-template", this.deleteTemplate.bind(this));
|
|
}
|
|
deleteTemplate(e) {
|
|
let $tr = $(e.target).closest("tr");
|
|
let id = $tr.data("id");
|
|
let name = $tr.find("td:first").text();
|
|
Modal.confirm(`Are you sure to remove template: <strong>${name}</strong>?`, "Delete template", (dlg, e) => {
|
|
$ajax.post("delete", { id: id }).trigger(e.target).encoder("form").json(() => {
|
|
$tr.remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
Template.ListPage = ListPage;
|
|
})(Template = Service.Template || (Service.Template = {}));
|
|
})(Service = Swirl.Service || (Swirl.Service = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Setting;
|
|
(function (Setting) {
|
|
class IndexPage {
|
|
constructor() {
|
|
$("#ldap-enabled").change(e => {
|
|
let enabled = $(e.target).prop("checked");
|
|
$("#fs-ldap").find("input:not(:checkbox)").prop("readonly", !enabled);
|
|
});
|
|
}
|
|
}
|
|
Setting.IndexPage = IndexPage;
|
|
})(Setting = Swirl.Setting || (Swirl.Setting = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Stack;
|
|
(function (Stack) {
|
|
var Archive;
|
|
(function (Archive) {
|
|
var Modal = Swirl.Core.Modal;
|
|
var Dispatcher = Swirl.Core.Dispatcher;
|
|
class ListPage {
|
|
constructor() {
|
|
let dispatcher = Dispatcher.bind("#table-items");
|
|
dispatcher.on("deploy-archive", this.deployArchive.bind(this));
|
|
dispatcher.on("delete-archive", this.deleteArchive.bind(this));
|
|
}
|
|
deployArchive(e) {
|
|
let $tr = $(e.target).closest("tr");
|
|
let id = $tr.data("id");
|
|
let name = $tr.find("td:first").text().trim();
|
|
Modal.confirm(`Are you sure to deploy archive: <strong>${name}</strong>?`, "Deploy archive", (dlg, e) => {
|
|
$ajax.post("deploy", { id: id }).trigger(e.target).encoder("form").json(r => {
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
deleteArchive(e) {
|
|
let $tr = $(e.target).closest("tr");
|
|
let id = $tr.data("id");
|
|
let name = $tr.find("td:first").text().trim();
|
|
Modal.confirm(`Are you sure to remove archive: <strong>${name}</strong>?`, "Delete archive", (dlg, e) => {
|
|
$ajax.post("delete", { id: id }).trigger(e.target).encoder("form").json(r => {
|
|
$tr.remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
Archive.ListPage = ListPage;
|
|
})(Archive = Stack.Archive || (Stack.Archive = {}));
|
|
})(Stack = Swirl.Stack || (Swirl.Stack = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Stack;
|
|
(function (Stack) {
|
|
var Task;
|
|
(function (Task) {
|
|
var Modal = Swirl.Core.Modal;
|
|
var Dispatcher = Swirl.Core.Dispatcher;
|
|
class ListPage {
|
|
constructor() {
|
|
let dispatcher = Dispatcher.bind("#table-items");
|
|
dispatcher.on("delete-stack", this.deleteStack.bind(this));
|
|
}
|
|
deleteStack(e) {
|
|
let $tr = $(e.target).closest("tr");
|
|
let name = $tr.find("td:first").text().trim();
|
|
Modal.confirm(`Are you sure to remove stack: <strong>${name}</strong>?`, "Delete stack", (dlg, e) => {
|
|
$ajax.post("delete", { name: name }).trigger(e.target).encoder("form").json(r => {
|
|
$tr.remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
Task.ListPage = ListPage;
|
|
})(Task = Stack.Task || (Stack.Task = {}));
|
|
})(Stack = Swirl.Stack || (Swirl.Stack = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var User;
|
|
(function (User) {
|
|
var Modal = Swirl.Core.Modal;
|
|
var Dispatcher = Swirl.Core.Dispatcher;
|
|
class ListPage {
|
|
constructor() {
|
|
Dispatcher.bind("#table-items")
|
|
.on("delete-user", this.deleteUser.bind(this))
|
|
.on("block-user", this.blockUser.bind(this))
|
|
.on("unblock-user", this.unblockUser.bind(this));
|
|
}
|
|
deleteUser(e) {
|
|
let $tr = $(e.target).closest("tr");
|
|
let id = $tr.data("id");
|
|
let name = $tr.find("td:first").text().trim();
|
|
Modal.confirm(`Are you sure to remove user: <strong>${name}</strong>?`, "Delete user", (dlg, e) => {
|
|
$ajax.post("delete", { id: id }).trigger(e.target).encoder("form").json(r => {
|
|
$tr.remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
blockUser(e) {
|
|
let $tr = $(e.target).closest("tr");
|
|
let id = $tr.data("id");
|
|
let name = $tr.find("td:first").text().trim();
|
|
Modal.confirm(`Are you sure to block user: <strong>${name}</strong>?`, "Block user", (dlg, e) => {
|
|
$ajax.post("block", { id: id }).trigger(e.target).encoder("form").json(r => {
|
|
location.reload();
|
|
});
|
|
});
|
|
}
|
|
unblockUser(e) {
|
|
let $tr = $(e.target).closest("tr");
|
|
let id = $tr.data("id");
|
|
let name = $tr.find("td:first").text().trim();
|
|
Modal.confirm(`Are you sure to unblock user: <strong>${name}</strong>?`, "Unblock user", (dlg, e) => {
|
|
$ajax.post("unblock", { id: id }).trigger(e.target).encoder("form").json(r => {
|
|
location.reload();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
User.ListPage = ListPage;
|
|
})(User = Swirl.User || (Swirl.User = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Volume;
|
|
(function (Volume) {
|
|
var Modal = Swirl.Core.Modal;
|
|
var Table = Swirl.Core.ListTable;
|
|
class ListPage {
|
|
constructor() {
|
|
this.table = new Table("#table-items");
|
|
this.table.on("delete-volume", this.deleteVolume.bind(this));
|
|
$("#btn-delete").click(this.deleteVolumes.bind(this));
|
|
$("#btn-prune").click(this.pruneVolumes.bind(this));
|
|
}
|
|
deleteVolume(e) {
|
|
let $tr = $(e.target).closest("tr");
|
|
let name = $tr.find("td:eq(1)").text().trim();
|
|
Modal.confirm(`Are you sure to remove volume: <strong>${name}</strong>?`, "Delete volume", (dlg, e) => {
|
|
$ajax.post("delete", { names: name }).trigger(e.target).encoder("form").json(r => {
|
|
$tr.remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
deleteVolumes(e) {
|
|
let names = this.table.selectedKeys();
|
|
if (names.length == 0) {
|
|
Modal.alert("Please select one or more items.");
|
|
return;
|
|
}
|
|
Modal.confirm(`Are you sure to remove ${names.length} volumes?`, "Delete volumes", (dlg, e) => {
|
|
$ajax.post("delete", { names: names.join(",") }).trigger(e.target).encoder("form").json(r => {
|
|
this.table.selectedRows().remove();
|
|
dlg.close();
|
|
});
|
|
});
|
|
}
|
|
pruneVolumes(e) {
|
|
Modal.confirm(`Are you sure to remove all unused volumes?`, "Prune volumes", (dlg, e) => {
|
|
$ajax.post("prune").trigger(e.target).json(r => {
|
|
location.reload();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
Volume.ListPage = ListPage;
|
|
})(Volume = Swirl.Volume || (Swirl.Volume = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
var Swirl;
|
|
(function (Swirl) {
|
|
var Volume;
|
|
(function (Volume) {
|
|
var OptionTable = Swirl.Core.OptionTable;
|
|
class NewPage {
|
|
constructor() {
|
|
new OptionTable("#table-options");
|
|
new OptionTable("#table-labels");
|
|
$("#drivers").find(":radio[name=driver]").change(e => {
|
|
$("#txt-custom-driver").prop("disabled", $(e.target).val() != "other");
|
|
});
|
|
}
|
|
}
|
|
Volume.NewPage = NewPage;
|
|
})(Volume = Swirl.Volume || (Swirl.Volume = {}));
|
|
})(Swirl || (Swirl = {}));
|
|
//# sourceMappingURL=swirl.js.map
|