diff options
author | Simon Rettberg | 2017-07-06 14:39:06 +0200 |
---|---|---|
committer | Simon Rettberg | 2017-07-06 14:39:06 +0200 |
commit | 75c4c1c22c9f44b93602270e5b0cb521ec2aad3b (patch) | |
tree | db7e0fecf3199bd496232e430edf8910eba8d980 /modules-available/syslog | |
parent | [roomplanner] Support : in mac search, use small display of client (diff) | |
download | slx-admin-75c4c1c22c9f44b93602270e5b0cb521ec2aad3b.tar.gz slx-admin-75c4c1c22c9f44b93602270e5b0cb521ec2aad3b.tar.xz slx-admin-75c4c1c22c9f44b93602270e5b0cb521ec2aad3b.zip |
[syslog] Improved filtering with suggestions from existing log
Diffstat (limited to 'modules-available/syslog')
-rw-r--r-- | modules-available/syslog/clientscript.js | 8 | ||||
-rw-r--r-- | modules-available/syslog/config.json | 3 | ||||
-rw-r--r-- | modules-available/syslog/page.inc.php | 12 | ||||
-rw-r--r-- | modules-available/syslog/style.css | 45 | ||||
-rw-r--r-- | modules-available/syslog/templates/page-syslog.html | 101 |
5 files changed, 86 insertions, 83 deletions
diff --git a/modules-available/syslog/clientscript.js b/modules-available/syslog/clientscript.js deleted file mode 100644 index 3d652628..00000000 --- a/modules-available/syslog/clientscript.js +++ /dev/null @@ -1,8 +0,0 @@ -/* - * bootstrap-tagsinput v0.3.9 by Tim Schlechter - * - */ -!function(a){"use strict";function b(b,c){this.itemsArray=[],this.$element=a(b),this.$element.hide(),this.isSelect="SELECT"===b.tagName,this.multiple=this.isSelect&&b.hasAttribute("multiple"),this.objectItems=c&&c.itemValue,this.placeholderText=b.hasAttribute("placeholder")?this.$element.attr("placeholder"):"",this.inputSize=Math.max(1,this.placeholderText.length),this.$container=a('<div class="bootstrap-tagsinput"></div>'),this.$input=a('<input size="'+this.inputSize+'" type="text" placeholder="'+this.placeholderText+'"/>').appendTo(this.$container),this.$element.after(this.$container),this.build(c)}function c(a,b){if("function"!=typeof a[b]){var c=a[b];a[b]=function(a){return a[c]}}}function d(a,b){if("function"!=typeof a[b]){var c=a[b];a[b]=function(){return c}}}function e(a){return a?h.text(a).html():""}function f(a){var b=0;if(document.selection){a.focus();var c=document.selection.createRange();c.moveStart("character",-a.value.length),b=c.text.length}else(a.selectionStart||"0"==a.selectionStart)&&(b=a.selectionStart);return b}var g={tagClass:function(){return"label label-info"},itemValue:function(a){return a?a.toString():a},itemText:function(a){return this.itemValue(a)},freeInput:!0,maxTags:void 0,confirmKeys:[13],onTagExists:function(a,b){b.hide().fadeIn()}};b.prototype={constructor:b,add:function(b,c){var d=this;if(!(d.options.maxTags&&d.itemsArray.length>=d.options.maxTags||b!==!1&&!b)){if("object"==typeof b&&!d.objectItems)throw"Can't add objects when itemValue option is not set";if(!b.toString().match(/^\s*$/)){if(d.isSelect&&!d.multiple&&d.itemsArray.length>0&&d.remove(d.itemsArray[0]),"string"==typeof b&&"INPUT"===this.$element[0].tagName){var f=b.split(",");if(f.length>1){for(var g=0;g<f.length;g++)this.add(f[g],!0);return c||d.pushVal(),void 0}}var h=d.options.itemValue(b),i=d.options.itemText(b),j=d.options.tagClass(b),k=a.grep(d.itemsArray,function(a){return d.options.itemValue(a)===h})[0];if(k){if(d.options.onTagExists){var l=a(".tag",d.$container).filter(function(){return a(this).data("item")===k});d.options.onTagExists(b,l)}}else{d.itemsArray.push(b);var m=a('<span class="tag '+e(j)+'">'+e(i)+'<span data-role="remove"></span></span>');if(m.data("item",b),d.findInputWrapper().before(m),m.after(" "),d.isSelect&&!a('option[value="'+escape(h)+'"]',d.$element)[0]){var n=a("<option selected>"+e(i)+"</option>");n.data("item",b),n.attr("value",h),d.$element.append(n)}c||d.pushVal(),d.options.maxTags===d.itemsArray.length&&d.$container.addClass("bootstrap-tagsinput-max"),d.$element.trigger(a.Event("itemAdded",{item:b}))}}}},remove:function(b,c){var d=this;d.objectItems&&(b="object"==typeof b?a.grep(d.itemsArray,function(a){return d.options.itemValue(a)==d.options.itemValue(b)})[0]:a.grep(d.itemsArray,function(a){return d.options.itemValue(a)==b})[0]),b&&(a(".tag",d.$container).filter(function(){return a(this).data("item")===b}).remove(),a("option",d.$element).filter(function(){return a(this).data("item")===b}).remove(),d.itemsArray.splice(a.inArray(b,d.itemsArray),1)),c||d.pushVal(),d.options.maxTags>d.itemsArray.length&&d.$container.removeClass("bootstrap-tagsinput-max"),d.$element.trigger(a.Event("itemRemoved",{item:b}))},removeAll:function(){var b=this;for(a(".tag",b.$container).remove(),a("option",b.$element).remove();b.itemsArray.length>0;)b.itemsArray.pop();b.pushVal(),b.options.maxTags&&!this.isEnabled()&&this.enable()},refresh:function(){var b=this;a(".tag",b.$container).each(function(){var c=a(this),d=c.data("item"),f=b.options.itemValue(d),g=b.options.itemText(d),h=b.options.tagClass(d);if(c.attr("class",null),c.addClass("tag "+e(h)),c.contents().filter(function(){return 3==this.nodeType})[0].nodeValue=e(g),b.isSelect){var i=a("option",b.$element).filter(function(){return a(this).data("item")===d});i.attr("value",f)}})},items:function(){return this.itemsArray},pushVal:function(){var b=this,c=a.map(b.items(),function(a){return b.options.itemValue(a).toString()});b.$element.val(c,!0).trigger("change")},build:function(b){var e=this;e.options=a.extend({},g,b);var h=e.options.typeahead||{};e.objectItems&&(e.options.freeInput=!1),c(e.options,"itemValue"),c(e.options,"itemText"),c(e.options,"tagClass"),e.options.source&&(h.source=e.options.source),h.source&&a.fn.typeahead&&(d(h,"source"),e.$input.typeahead({source:function(b,c){function d(a){for(var b=[],d=0;d<a.length;d++){var g=e.options.itemText(a[d]);f[g]=a[d],b.push(g)}c(b)}this.map={};var f=this.map,g=h.source(b);a.isFunction(g.success)?g.success(d):a.when(g).then(d)},updater:function(a){e.add(this.map[a])},matcher:function(a){return-1!==a.toLowerCase().indexOf(this.query.trim().toLowerCase())},sorter:function(a){return a.sort()},highlighter:function(a){var b=new RegExp("("+this.query+")","gi");return a.replace(b,"<strong>$1</strong>")}})),e.$container.on("click",a.proxy(function(){e.$input.focus()},e)),e.$container.on("keydown","input",a.proxy(function(b){var c=a(b.target),d=e.findInputWrapper();switch(b.which){case 8:if(0===f(c[0])){var g=d.prev();g&&e.remove(g.data("item"))}break;case 46:if(0===f(c[0])){var h=d.next();h&&e.remove(h.data("item"))}break;case 37:var i=d.prev();0===c.val().length&&i[0]&&(i.before(d),c.focus());break;case 39:var j=d.next();0===c.val().length&&j[0]&&(j.after(d),c.focus());break;default:e.options.freeInput&&a.inArray(b.which,e.options.confirmKeys)>=0&&(e.add(c.val()),c.val(""),b.preventDefault())}c.attr("size",Math.max(this.inputSize,c.val().length))},e)),e.$container.on("click","[data-role=remove]",a.proxy(function(b){e.remove(a(b.target).closest(".tag").data("item"))},e)),e.options.itemValue===g.itemValue&&("INPUT"===e.$element[0].tagName?e.add(e.$element.val()):a("option",e.$element).each(function(){e.add(a(this).attr("value"),!0)}))},destroy:function(){var a=this;a.$container.off("keypress","input"),a.$container.off("click","[role=remove]"),a.$container.remove(),a.$element.removeData("tagsinput"),a.$element.show()},focus:function(){this.$input.focus()},input:function(){return this.$input},findInputWrapper:function(){for(var b=this.$input[0],c=this.$container[0];b&&b.parentNode!==c;)b=b.parentNode;return a(b)}},a.fn.tagsinput=function(c,d){var e=[];return this.each(function(){var f=a(this).data("tagsinput");if(f){var g=f[c](d);void 0!==g&&e.push(g)}else f=new b(this,c),a(this).data("tagsinput",f),e.push(f),"SELECT"===this.tagName&&a("option",a(this)).attr("selected","selected"),a(this).val(a(this).val())}),"string"==typeof c?e.length>1?e:e[0]:e},a.fn.tagsinput.Constructor=b;var h=a("<div />");a(function(){a("input[data-role=tagsinput], select[multiple][data-role=tagsinput]").tagsinput()})}(window.jQuery); -/* -//@ sourceMappingURL=bootstrap-tagsinput.min.js.map -*/
\ No newline at end of file diff --git a/modules-available/syslog/config.json b/modules-available/syslog/config.json index 6778348d..2b718a8e 100644 --- a/modules-available/syslog/config.json +++ b/modules-available/syslog/config.json @@ -1,3 +1,4 @@ { - "category":"main.status" + "category":"main.status", + "dependencies":["js_selectize"] } diff --git a/modules-available/syslog/page.inc.php b/modules-available/syslog/page.inc.php index 486e0248..f2bc4854 100644 --- a/modules-available/syslog/page.inc.php +++ b/modules-available/syslog/page.inc.php @@ -15,6 +15,12 @@ class Page_SysLog extends Page protected function doRender() { + $cutoff = strtotime('-1 month'); + $res = Database::simpleQuery("SELECT logtypeid, Count(*) AS counter FROM clientlog WHERE dateline > $cutoff GROUP BY logtypeid ORDER BY counter ASC"); + $types = array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + $types[$row['logtypeid']] = $row; + } if (isset($_GET['filter'])) { $filter = $_GET['filter']; $not = isset($_GET['not']) ? 'NOT' : ''; @@ -35,6 +41,9 @@ class Page_SysLog extends Page $filterItem = preg_replace('/[^a-z0-9_\-]/', '', trim($filterItem)); if (empty($filterItem) || in_array($filterItem, $whereClause)) continue; $whereClause[] = "'$filterItem'"; + if (!isset($types[$filterItem])) { + $types[$filterItem] = ['logtypeid' => $filterItem, 'counter' => '']; + } } if (!empty($whereClause)) $whereClause = ' WHERE logtypeid ' . $not . ' IN (' . implode(', ', $whereClause) . ')'; } @@ -67,7 +76,8 @@ class Page_SysLog extends Page $paginate->render('page-syslog', array( 'filter' => $filter, 'not' => $not, - 'list' => $lines + 'list' => $lines, + 'types' => json_encode(array_values($types)), )); } diff --git a/modules-available/syslog/style.css b/modules-available/syslog/style.css deleted file mode 100644 index 98cfa7f3..00000000 --- a/modules-available/syslog/style.css +++ /dev/null @@ -1,45 +0,0 @@ -.bootstrap-tagsinput { - background-color: #fff; - border: 1px solid #ccc; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - display: inline-block; - padding: 4px 6px; - margin-bottom: 10px; - color: #555; - vertical-align: middle; - border-radius: 4px; - max-width: 100%; - line-height: 22px; -} -.bootstrap-tagsinput input { - border: none; - box-shadow: none; - outline: none; - background-color: transparent; - padding: 0; - margin: 0; - width: auto !important; - max-width: inherit; -} -.bootstrap-tagsinput input:focus { - border: none; - box-shadow: none; -} -.bootstrap-tagsinput .tag { - margin-right: 2px; - color: white; -} -.bootstrap-tagsinput .tag [data-role="remove"] { - margin-left: 8px; - cursor: pointer; -} -.bootstrap-tagsinput .tag [data-role="remove"]:after { - content: "x"; - padding: 0px 2px; -} -.bootstrap-tagsinput .tag [data-role="remove"]:hover { - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} -.bootstrap-tagsinput .tag [data-role="remove"]:hover:active { - box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); -} diff --git a/modules-available/syslog/templates/page-syslog.html b/modules-available/syslog/templates/page-syslog.html index 98e94291..cb20a93a 100644 --- a/modules-available/syslog/templates/page-syslog.html +++ b/modules-available/syslog/templates/page-syslog.html @@ -1,35 +1,47 @@ <h1>{{lang_clientLog}}</h1> +<style type="text/css"> + .selectize-dropdown { + max-width: 500px; + } +</style> <form method="post" action="?do=SysLog"> <input type="hidden" name="token" value="{{token}}"> + <div class="pull-left"> + <label for="filterstring">{{lang_filter}}</label> + </div> + <div class="clearfix"></div> <div class="input-group"> - <span class="input-group-addon">{{lang_filter}}</span> - <input id="filterstring" type="text" placeholder="id" value="{{filter}}" name="filter" data-role="tagsinput" /> - <span class="input-group-addon"> - <input type="checkbox" name="not" {{#not}}checked="checked"{{/not}}> {{lang_not}} - </span> + <input id="filterstring" placeholder="id" value="{{filter}}" name="filter"> <span class="input-group-btn"> - <button class="btn btn-default" type="submit">{{lang_go}}</button> - </span> + <button class="btn btn-default" type="submit">{{lang_go}}</button> + </span> + </div> + <div class="pull-left"> + <div class="checkbox"> + <input id="notbox" type="checkbox" name="not" {{#not}}checked="checked"{{/not}}> + <label for="notbox">{{lang_not}}</label> + </div> </div> </form> {{{pagenav}}} <table class="table table-striped table-condensed"> <thead> - <th width="1"></th> - <th>{{lang_when}}</th> - <th>{{lang_client}}</th> - <th>{{lang_event}}</th> - <th width="1">{{lang_details}}</th> + <th width="1"></th> + <th>{{lang_when}}</th> + <th>{{lang_client}}</th> + <th>{{lang_event}}</th> + <th width="1">{{lang_details}}</th> </thead> <tbody> {{#list}} <tr> - <td><span class="glyphicon {{icon}}" title="{{logtypeid}}" onclick="$('#filterstring').tagsinput('add', '{{logtypeid}}')"></span></td> + <td><span class="type-button glyphicon {{icon}}" title="{{logtypeid}}"></span></td> <td class="text-right" nowrap="nowrap">{{date}}</td> <td>{{clientip}}</td> <td>{{description}}</td> <td>{{#extra}} - <a class="btn btn-default btn-xs pull-left" onclick="$('#details-body').html($('#extra-{{logid}}').html())" data-toggle="modal" data-target="#myModal">»</a> + <a class="btn btn-default btn-xs pull-left" onclick="$('#details-body').html($('#extra-{{logid}}').html())" + data-toggle="modal" data-target="#myModal">»</a> <div class="hidden" id="extra-{{logid}}">{{extra}}</div> {{/extra}}</td> </tr> @@ -39,20 +51,53 @@ {{{pagenav}}} <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> - <div class="modal-dialog modal-lg"> - <div class="modal-content"> - <div class="modal-header"> - <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button> - <h4 class="modal-title" id="myModalLabel">{{lang_details}}</h4> - </div> - <div class="modal-body"> - <pre id="details-body"></pre> - </div> - <div class="modal-footer"> - <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> - </div> - </div> - </div> + <div class="modal-dialog modal-lg"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span + class="sr-only">Close</span></button> + <h4 class="modal-title" id="myModalLabel">{{lang_details}}</h4> + </div> + <div class="modal-body"> + <pre id="details-body"></pre> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + </div> + </div> + </div> </div> +<script type="application/javascript"><!-- +document.addEventListener('DOMContentLoaded', function () { + + function renderOption(item, escape) { + return '<div><div class="pull-right badge">' + escape(item.counter) + '</div>' + escape(item.logtypeid) + '</div>'; + } + + function renderSelected(item, escape) { + return '<div>' + escape(item.logtypeid) + '</div>'; + } + + var opts = {{{types}}} || []; + var $box = $('#filterstring').selectize({ + options: opts, + plugins: ["remove_button"], + valueField: 'logtypeid', + searchField: "logtypeid", + openOnFocus: true, + create: true, + render: {option: renderOption, item: renderSelected}, + maxItems: null, + highlight: false + }); + var inst = $box[0].selectize; + + $('.type-button').click(function() { + inst.addOption({logtypeid: this.title, counter: ''}); + inst.addItem(this.title, true); + }); +}); +//--></script> + |