@@ -561,3 +561,11 @@ input.radio { | |||
#nprogress .bar { | |||
height: 1px; | |||
} | |||
/* Form element background for validation states */ | |||
.has-error .form-control { | |||
background-color: #fbe9e5; | |||
} | |||
.has-success .form-control { | |||
background-color: #eef9e7; | |||
} |
@@ -39,6 +39,7 @@ | |||
<li role="presentation"><a id="configuration_nav" aria-controls="configuration" role="tab" href="#configuration" data-toggle="tab">Configuration</a></li> | |||
<li role="presentation"><a id="symbols_nav" aria-controls="symbols" role="tab" href="#symbols" data-toggle="tab">Symbols</a></li> | |||
<li role="presentation"><a id="scan_nav" aria-controls="scan" role="tab" href="#scan" data-toggle="tab">Scan<span class="learn" style="display: none;">/Learn</span></a></li> | |||
<li role="presentation"><a id="selectors_nav" aria-controls="selectors" role="tab" href="#selectors" data-toggle="tab" style="display: none;">Test selectors</a></li> | |||
<li role="presentation"><a id="history_nav" aria-controls="history" role="tab" href="#history" data-toggle="tab">History</a></li> | |||
</ul> | |||
<form class="navbar-form navbar-right" style="display: none;"> | |||
@@ -315,6 +316,50 @@ | |||
</div> | |||
</div> | |||
<div class="tab-pane" id="selectors"> | |||
<div class="widget-box"> | |||
<div class="widget-title"> | |||
<span class="icon"><i class="glyphicon glyphicon-envelope"></i></span> | |||
<h5>Test Rspamd selectors</h5> | |||
</div> | |||
<div class="widget-content"> | |||
<h5>Message source:</h5> | |||
<div class="row"> | |||
<form class="col-md-12"> | |||
<div class="form-group"> | |||
<textarea class="form-control" id="selectorsMsgArea" rows="9" placeholder="Paste raw message source"></textarea> | |||
</div> | |||
<div class="form-group"> | |||
<button class="btn btn-default pull-right" id="selectorsMsgClean"><i class="glyphicon glyphicon-trash"></i> Clean form</button> | |||
</div> | |||
</form> | |||
</div> | |||
<h5>Selector(s):</h5> | |||
<div class="row"> | |||
<form class="col-md-12"> | |||
<div class="form-group has-feedback"> | |||
<textarea class="form-control" id="selectorsSelArea" rows="1" placeholder="extractor.transform(arg);extractor.transform(arg);..."></textarea> | |||
<span id="selector-feedback-icon" class="glyphicon form-control-feedback"></span> | |||
</div> | |||
<div class="form-group"> | |||
<button type="submit" class="btn btn-default btn-primary" id="selectorsChkMsgBtn"><i class="glyphicon glyphicon-search"></i> Check message</button> | |||
<button class="btn btn-default pull-right" id="selectorsClean"><i class="glyphicon glyphicon-trash"></i> Clean form</button> | |||
</div> | |||
</form> | |||
</div> | |||
<h5>Result:</h5> | |||
<div class="row"> | |||
<form class="col-md-12"> | |||
<div class="form-group"> | |||
<textarea class="form-control" id="selectorsResArea" rows="5" readonly></textarea> | |||
</div> | |||
</form> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="tab-pane" id="history"> | |||
<div class="widget-box"> |
@@ -26,10 +26,10 @@ | |||
/* global jQuery:false, FooTable:false, Visibility:false */ | |||
define(["jquery", "d3pie", "visibility", "nprogress", "stickytabs", "app/stats", "app/graph", "app/config", | |||
"app/symbols", "app/history", "app/upload"], | |||
"app/symbols", "app/history", "app/upload", "app/selectors"], | |||
// eslint-disable-next-line max-params | |||
function ($, D3pie, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_config, | |||
tab_symbols, tab_history, tab_upload) { | |||
tab_symbols, tab_history, tab_upload, tab_selectors) { | |||
"use strict"; | |||
var ui = { | |||
page_size: { | |||
@@ -260,6 +260,7 @@ function ($, D3pie, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_ | |||
$('#selSrv [value="' + e.name + '"]').prop("disabled", true); | |||
} | |||
}); | |||
tab_selectors.checkSelectors(ui); | |||
}, | |||
errorMessage: "Cannot get server status", | |||
server: "All SERVERS" | |||
@@ -272,10 +273,12 @@ function ($, D3pie, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_ | |||
$(".learn").hide(); | |||
$("#resetHistory").attr("disabled", true); | |||
$("#errors-history").hide(); | |||
$("#selectors_nav").hide(); | |||
} else { | |||
$(".learn").show(); | |||
$("#resetHistory").removeAttr("disabled", true); | |||
$("#errors-history").show(); | |||
$("#selectors_nav").show(); | |||
} | |||
var buttons = $("#navBar form.navbar-right"); | |||
@@ -427,6 +430,7 @@ function ($, D3pie, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_ | |||
}); | |||
tab_config.setup(ui); | |||
tab_history.setup(ui, tables); | |||
tab_selectors.setup(ui); | |||
tab_symbols.setup(ui, tables); | |||
tab_upload.setup(ui, tables); | |||
selData = tab_graph.setup(ui); |
@@ -0,0 +1,94 @@ | |||
define(["jquery"], | |||
function ($) { | |||
"use strict"; | |||
var ui = {}; | |||
function enable_disable_check_btn() { | |||
$("#selectorsChkMsgBtn").prop("disabled", ( | |||
$.trim($("#selectorsMsgArea").val()).length === 0 || | |||
!$("#selectorsSelArea").parent().hasClass("has-success") | |||
)); | |||
} | |||
function get_server(rspamd) { | |||
var checked_server = rspamd.getSelector("selSrv"); | |||
return (checked_server === "All SERVERS") ? "local" : checked_server; | |||
} | |||
function checkMsg(rspamd, data) { | |||
var selector = $("#selectorsSelArea").val(); | |||
rspamd.query("plugins/selectors/check_message?selector=" + encodeURIComponent(selector), { | |||
data: data, | |||
method: "POST", | |||
success: function (neighbours_status) { | |||
var json = neighbours_status[0].data; | |||
if (json.success) { | |||
rspamd.alertMessage("alert-success", "Message successfully processed"); | |||
$("#selectorsResArea") | |||
.val(Object.prototype.hasOwnProperty.call(json, "data") ? json.data.toString() : ""); | |||
} else { | |||
rspamd.alertMessage("alert-error", "Unexpected error processing message"); | |||
} | |||
}, | |||
server: get_server(rspamd) | |||
}); | |||
} | |||
ui.checkSelectors = function (rspamd) { | |||
function toggle_form_group_class(remove, add) { | |||
var icon = { | |||
error: "remove", | |||
success: "ok" | |||
}; | |||
$("#selectorsSelArea").parent().removeClass("has-" + remove).addClass("has-" + add); | |||
$("#selector-feedback-icon") | |||
.removeClass("glyphicon-" + icon[remove]).addClass("glyphicon-" + icon[add]).show(); | |||
enable_disable_check_btn(); | |||
} | |||
var selector = $("#selectorsSelArea").val(); | |||
if (selector.length) { | |||
rspamd.query("plugins/selectors/check_selector?selector=" + encodeURIComponent(selector), { | |||
method: "GET", | |||
success: function (json) { | |||
if (json[0].data.success) { | |||
toggle_form_group_class("error", "success"); | |||
} else { | |||
toggle_form_group_class("success", "error"); | |||
} | |||
}, | |||
server: get_server(rspamd) | |||
}); | |||
} else { | |||
$("#selectorsSelArea").parent().removeClass("has-error has-success"); | |||
$("#selector-feedback-icon").hide(); | |||
enable_disable_check_btn(); | |||
} | |||
}; | |||
ui.setup = function (rspamd) { | |||
$("#selectorsMsgClean").on("click", function () { | |||
$("#selectorsChkMsgBtn").attr("disabled", true); | |||
$("#selectorsMsgArea").val(""); | |||
return false; | |||
}); | |||
$("#selectorsClean").on("click", function () { | |||
$("#selectorsSelArea").val(""); | |||
ui.checkSelectors(rspamd); | |||
return false; | |||
}); | |||
$("#selectorsChkMsgBtn").on("click", function () { | |||
$("#selectorsResArea").val(""); | |||
checkMsg(rspamd, $("#selectorsMsgArea").val()); | |||
return false; | |||
}); | |||
$("#selectorsMsgArea").on("input", function () { | |||
enable_disable_check_btn(); | |||
}); | |||
$("#selectorsSelArea").on("input", function () { | |||
ui.checkSelectors(rspamd); | |||
}); | |||
}; | |||
return ui; | |||
}); |