From c00805fd25f0c8b14dfd75d7b38827c50949dbfc Mon Sep 17 00:00:00 2001 From: kulikov-a <36099472+kulikov-a@users.noreply.github.com> Date: Tue, 10 Oct 2023 14:17:00 +0300 Subject: [PATCH] www/nginx: add columns select button to the log viewer (#3411) --- www/nginx/src/opnsense/www/css/nginx/logs.css | 19 +++- .../www/js/nginx/dist/logviewer.min.js | 2 +- .../www/js/nginx/src/controller/LogView.js | 99 ++++++++++++++--- .../www/js/nginx/src/models/LogColumn.js | 5 + .../js/nginx/src/templates/AccessLogLine.html | 9 -- .../js/nginx/src/templates/ErrorLogLine.html | 5 - .../www/js/nginx/src/templates/LogColumn.html | 6 + .../www/js/nginx/src/templates/LogLine.html | 3 + .../src/templates/StreamAccessLogLine.html | 6 - .../www/js/nginx/src/templates/logviewer.html | 105 +++++------------- 10 files changed, 143 insertions(+), 116 deletions(-) create mode 100644 www/nginx/src/opnsense/www/js/nginx/src/models/LogColumn.js delete mode 100644 www/nginx/src/opnsense/www/js/nginx/src/templates/AccessLogLine.html delete mode 100644 www/nginx/src/opnsense/www/js/nginx/src/templates/ErrorLogLine.html create mode 100644 www/nginx/src/opnsense/www/js/nginx/src/templates/LogColumn.html create mode 100644 www/nginx/src/opnsense/www/js/nginx/src/templates/LogLine.html delete mode 100644 www/nginx/src/opnsense/www/js/nginx/src/templates/StreamAccessLogLine.html diff --git a/www/nginx/src/opnsense/www/css/nginx/logs.css b/www/nginx/src/opnsense/www/css/nginx/logs.css index a5ea942e9..9501c1b0d 100644 --- a/www/nginx/src/opnsense/www/css/nginx/logs.css +++ b/www/nginx/src/opnsense/www/css/nginx/logs.css @@ -26,7 +26,11 @@ thead.sticky-top th { position: sticky; - top: 80px; + top: 50px; +} + +tr.filter > th { + padding: 10px 10px 10px 10px !important; } thead.sticky-top tr:first-child th { @@ -38,4 +42,17 @@ tfoot.sticky-bottom th { bottom: 50px; font-weight: normal; font-family: inherit; + padding: 10px 10px 10px 10px !important; +} + +td.referer, td.request_line { + word-break: break-all; +} + +.ngx-dropdown-item { + cursor: pointer; + display: block; + margin: 0; + padding: 3px 20px; + white-space: nowrap; } diff --git a/www/nginx/src/opnsense/www/js/nginx/dist/logviewer.min.js b/www/nginx/src/opnsense/www/js/nginx/dist/logviewer.min.js index 57b389818..9833831fb 100644 --- a/www/nginx/src/opnsense/www/js/nginx/dist/logviewer.min.js +++ b/www/nginx/src/opnsense/www/js/nginx/dist/logviewer.min.js @@ -1 +1 @@ -!function(e){var t={};function n(i){if(t[i])return t[i].exports;var l=t[i]={i:i,l:!1,exports:{}};return e[i].call(l.exports,l,l.exports,n),l.l=!0,l.exports}n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var l in e)n.d(i,l,function(t){return e[t]}.bind(null,l));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=26)}([function(e,t,n){var i=n(2),l=n(4),a=/[&<>"']/g,o=RegExp(a.source);e.exports=function(e){return(e=l(e))&&o.test(e)?e.replace(a,i):e}},function(e,t,n){var i=n(6).Symbol;e.exports=i},function(e,t,n){var i=n(3)({"&":"&","<":"<",">":">",'"':""","'":"'"});e.exports=i},function(e,t){e.exports=function(e){return function(t){return null==e?void 0:e[t]}}},function(e,t,n){var i=n(5);e.exports=function(e){return null==e?"":i(e)}},function(e,t,n){var i=n(1),l=n(9),a=n(10),o=n(11),s=1/0,r=i?i.prototype:void 0,_=r?r.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(a(t))return l(t,e)+"";if(o(t))return _?_.call(t):"";var n=t+"";return"0"==n&&1/t==-s?"-0":n}},function(e,t,n){var i=n(7),l="object"==typeof self&&self&&self.Object===Object&&self,a=i||l||Function("return this")();e.exports=a},function(e,t,n){(function(t){var n="object"==typeof t&&t&&t.Object===Object&&t;e.exports=n}).call(this,n(8))},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t){e.exports=function(e,t){for(var n=-1,i=null==e?0:e.length,l=Array(i);++n\n \n\n'+(null==(__t=_.escape(name))?"":__t)+'\n\n";return __p}},function(module,exports,__webpack_require__){var _={escape:__webpack_require__(0)};module.exports=function(obj){obj||(obj={});var __t,__p="",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,"")}with(obj)__p+='\n\n '+(null==(__t=_.escape(name))?"":__t)+"\n\n";return __p}},function(module,exports,__webpack_require__){var _={escape:__webpack_require__(0)};module.exports=function(obj){obj||(obj={});var __t,__p="";with(obj)__p+=''+(null==(__t=model.escape("time"))?"":__t)+'\n'+(null==(__t=model.escape("remote_ip"))?"":__t)+'\n'+(null==(__t=model.escape("username"))?"":__t)+'\n'+(null==(__t=model.escape("status"))?"":__t)+'\n'+(null==(__t=model.escape("size"))?"":__t)+'\n'+(null==(__t=model.escape("http_referer"))?"":__t)+'\n'+(null==(__t=model.escape("user_agent"))?"":__t)+'\n'+(null==(__t=model.escape("forwarded_for"))?"":__t)+'\n'+(null==(__t=model.escape("request_line"))?"":__t)+"\n";return __p}},function(module,exports,__webpack_require__){var _={escape:__webpack_require__(0)};module.exports=function(obj){obj||(obj={});var __t,__p="";with(obj)__p+=''+(null==(__t=model.escape("time"))?"":__t)+'\n'+(null==(__t=model.escape("remote_ip"))?"":__t)+'\n'+(null==(__t=model.escape("status"))?"":__t)+'\n'+(null==(__t=model.escape("bytes_sent"))?"":__t)+'\n'+(null==(__t=model.escape("bytes_received"))?"":__t)+'\n'+(null==(__t=model.escape("session_time"))?"":__t)+"\n";return __p}},function(module,exports,__webpack_require__){var _={escape:__webpack_require__(0)};module.exports=function(obj){obj||(obj={});var __t,__p="";with(obj)__p+=''+(null==(__t=model.escape("date"))?"":__t)+'\n'+(null==(__t=model.escape("time"))?"":__t)+'\n'+(null==(__t=model.escape("severity"))?"":__t)+'\n'+(null==(__t=model.escape("number"))?"":__t)+'\n'+(null==(__t=model.escape("message"))?"":__t)+"\n";return __p}},function(module,exports,__webpack_require__){var _={escape:__webpack_require__(0)};module.exports=function(obj){obj||(obj={});var __t,__p="",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,"")}with(obj){let count=0;__p+='\n \n \n ',"errors"===log_type||"stream_errors"===log_type?(count=5,__p+="\n \n \n \n \n \n "):"accesses"===log_type?(count=9,__p+="\n \n \n \n \n \n \n \n \n \n "):(count=6,__p+="\n \n \n \n \n \n \n "),__p+='\n \n \n ',"errors"===log_type||"stream_errors"===log_type?__p+='\n \n \n \n \n \n ':"accesses"===log_type?__p+='\n \n \n \n \n \n \n \n \n \n ':__p+='\n \n \n \n \n \n \n ',__p+='\n \n \n \n \n \n \n \n \n \n \n \n \n
DateTimeSeverityNumberMessageTimeRemote IPUsernameStatusSizeRefererUser AgentForwarded ForRequest LineTimeRemote IPStatusBytes SentBytes ReceivedSession Time
\n \n \n \n \n \n \n Page 1/0\n \n \n \n \n \n Found lines: 0/0
\n'}return __p}},function(module,exports,__webpack_require__){var _={escape:__webpack_require__(0)};module.exports=function(obj){obj||(obj={});var __t,__p="";with(obj)__p+='
\n No data available...\n
\n';return __p}},,,,function(e,t,n){"use strict";n.r(t);var i=Backbone.Model.extend({});var l=Backbone.Collection.extend({model:i,url:function(){return`/api/nginx/logs/${this.logType}`},initialize:function(e){this.logType=e.logType}}),a=Backbone.Model.extend({});var o=Backbone.Collection.extend({model:a,url:function(){return`/api/nginx/logs/${this.logType}/${this.uuid}`},initialize:function(e){this.logType=e.logType,this.uuid=e.uuid}}),s=n(16),r=n.n(s);var _=Backbone.View.extend({tagName:"li",events:{"click .mainentry":"mainMenuClick","click .menuEntry":"menuEntryClick","click .dropdown-toggle":"menuDropdownClick"},initialize:function(e){this.listenTo(this.collection,"update",this.render),this.logType=e.logType,this.logview=e.logview,this.render()},render:function(){this.$el.html(""),this.renderCollection()},renderCollection:function(){this.$el.addClass("dropdown"),"global"==this.model.get("id")&&(this.$el.addClass("active"),this.logview.get_log("errors","global",-1)),this.$el.html(""),this.$el.append(r()({model:this.collection,id:this.model.get("id"),name:this.model.has("server_name")?this.model.get("server_name"):"Port "+this.model.get("port")}))},mainMenuClick:function(){this.collection.models[0]&&(this.handleElementClick(this.model.get("id"),-1),$(`#tab_${this.model.get("id")} li`).removeClass("active"),$(`#subtab_item_${this.model.get("id")}_${this.collection.models[0].get("number")}`).parent().addClass("active"))},menuDropdownClick:function(e){this.collection.fetch()},menuEntryClick:function(e){this.handleElementClick(e.target.dataset.modelUuid,e.target.dataset.modelFileno)},handleElementClick:function(e,t){this.logview.get_log(this.logType,e,t)}}),c=n(17),u=n.n(c);Backbone.View.extend({tagName:"li",initialize:function(e){this.logview=e.logview,this.log_name=e.log_name,this.visible_name=e.visible_name,this.log_type=e.log_type},events:{"click .mainentry":"handleElementClick"},log_name:null,log_type:null,visible_name:null,render:function(){this.$el.html(u()({name:this.visible_name}))},handleElementClick:function(){this.logview.get_log(this.log_type,this.log_name)}});var p=Backbone.View.extend({tagName:"ul",className:"nav nav-tabs",initialize:function(e){this.listenTo(this.collection,"update",this.render),this.logview=e.logview,this.logType=e.logType},render:function(){this.$el.attr("role","tablist"),this.$el.html(""),"global"==this.logType?this.render_global_error_tab():this.collection.forEach(e=>this.render_one_server(e))},render_one_server:function(e){const t=new o({uuid:e.get("id"),logType:this.logType}),n=new _({collection:t,model:e,logType:this.logType,logview:this.logview});this.$el.append(n.$el)},render_global_error_tab:function(){const e=new o({uuid:"global",logType:"errors"}),t=new _({collection:e,model:new Backbone.Model({server_name:"Global Error Log",id:"global"}),logType:"errors",logview:this.logview});this.$el.append(t.$el),e.fetch()}}),d=n(18),h=n.n(d),m=n(19),g=n.n(m),b=n(20),f=n.n(b),v=n(21),y=n.n(v);var w=Backbone.Model.extend({});var x=Backbone.Collection.extend({model:w,url:function(){return`/api/nginx/logs/${this.logType}/${this.uuid}/${this.fileNo}/${this.page}/${this.pageSize}/${this.create_filter()}`},initialize:function(){this.logType="none",this.uuid="none",this.fileNo=-1,this.page=0,this.pageSize=0,this.filter_model=new Backbone.Model},parse:function(e){return"error"in e?[]:(this.page_count=e.pages,this.total_entries=e.total,this.displayed_entries=e.found,e.lines)},create_filter:function(){return encodeURIComponent(JSON.stringify(this.filter_model))}}),k=n(22),j=n.n(k);const T=Backbone.View.extend({tagName:"tr",initialize:function(e){this.type=e.type},render:function(){this.$el.html(this.get_template()({model:this.model}))},get_template:function(){return"accesses"===this.type?h.a:"stream_accesses"===this.type?g.a:f.a}});const C=new(Backbone.View.extend({tagName:"div",className:"content-box tab-content",events:{"keyup .filter input":"update_filter","click #paging_first":"page_first","click #paging_back":"page_back","click #refresh":"update","click #paging_forward":"page_forward","click #paging_last":"page_last","change #entrycount":"change_entry_count"},page_entry_count:100,filter_delay:-1,initialize:function(){this.collection=new x,this.listenTo(this.collection,"sync",this.render),this.listenTo(this.collection,"update",this.render),this.listenTo(this.collection.filter_model,"change",this.render),this.type=""},render:function(){let e=this.$("tbody");e.length<1?0!==this.collection.length?(this.$el.html(y()({log_type:this.type,model:this.collection.filter_model})),e=this.$("tbody")):this.$el.html(j.a):e.html(""),0!==this.collection.length&&null==this.current_filtered_collection&&this.collection.forEach(t=>this.render_one(e,t)),this.$("#entrycountdisplay").html(this.page_entry_count),this.$("#currentpage").html(this.current_page+1),this.$("#pagecount").html(this.collection.page_count),this.$("#totalcount").html(this.collection.total_entries),this.$("#resultcount").html(this.collection.displayed_entries),this.current_page>=this.collection.page_count-1?(this.$("#paging_last").addClass("disabled"),this.$("#paging_forward").addClass("disabled")):(this.$("#paging_last").removeClass("disabled"),this.$("#paging_forward").removeClass("disabled")),this.current_page<=0?(this.$("#paging_back").addClass("disabled"),this.$("#paging_first").addClass("disabled")):(this.$("#paging_back").removeClass("disabled"),this.$("#paging_first").removeClass("disabled"))},render_one:function(e,t){const n=new T({type:this.type,model:t});n.render(),e.append(n.$el)},get_log:function(e,t,n){this.collection.uuid=t,this.collection.logType=e,this.collection.fileNo=n,this.type=e,this.current_page=0,this.$el.html(""),this.collection.filter_model.clear(),this.update()},update:function(){this.collection.page=this.current_page,this.collection.pageSize=this.page_entry_count,this.collection.fetch()},update_filter:function(e){clearTimeout(this.filter_delay);const t=e.target;this.collection.filter_model.set(t.name,$(t).val()),this.current_page=0,this.filter_delay=setTimeout(function(e){e.update()},500,this)},page_first:function(){this.current_page=0,this.update()},page_back:function(){this.current_page>0&&(this.current_page--,this.update())},page_forward:function(){this.current_page"']/g,a=RegExp(o.source);e.exports=function(e){return(e=l(e))&&a.test(e)?e.replace(o,n):e}},function(e,t,i){var n=i(6).Symbol;e.exports=n},function(e,t,i){var n=i(3)({"&":"&","<":"<",">":">",'"':""","'":"'"});e.exports=n},function(e,t){e.exports=function(e){return function(t){return null==e?void 0:e[t]}}},function(e,t,i){var n=i(5);e.exports=function(e){return null==e?"":n(e)}},function(e,t,i){var n=i(1),l=i(9),o=i(10),a=i(11),s=1/0,r=n?n.prototype:void 0,c=r?r.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(o(t))return l(t,e)+"";if(a(t))return c?c.call(t):"";var i=t+"";return"0"==i&&1/t==-s?"-0":i}},function(e,t,i){var n=i(7),l="object"==typeof self&&self&&self.Object===Object&&self,o=n||l||Function("return this")();e.exports=o},function(e,t,i){(function(t){var i="object"==typeof t&&t&&t.Object===Object&&t;e.exports=i}).call(this,i(8))},function(e,t){var i;i=function(){return this}();try{i=i||new Function("return this")()}catch(e){"object"==typeof window&&(i=window)}e.exports=i},function(e,t){e.exports=function(e,t){for(var i=-1,n=null==e?0:e.length,l=Array(n);++i\n \n\n'+(null==(__t=_.escape(name))?"":__t)+'\n\n";return __p}},function(module,exports,__webpack_require__){var _={escape:__webpack_require__(0)};module.exports=function(obj){obj||(obj={});var __t,__p="",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,"")}with(obj)__p+='\n\n '+(null==(__t=_.escape(name))?"":__t)+"\n\n";return __p}},function(module,exports,__webpack_require__){var _={escape:__webpack_require__(0)};module.exports=function(obj){obj||(obj={});var __t,__p="",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,"")}with(obj)log_fields_visible.forEach(e=>{__p+='\n'+(null==(__t=model.escape(e.id))?"":__t)+"\n"}),__p+="\n";return __p}},function(module,exports,__webpack_require__){var _={escape:__webpack_require__(0)};module.exports=function(obj){obj||(obj={});var __t,__p="";with(obj)__p+='\n
\n \n \n
\n\n';return __p}},function(module,exports,__webpack_require__){var _={escape:__webpack_require__(0)};module.exports=function(obj){obj||(obj={});var __t,__p="",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,"")}with(obj)__p+='\n \n \n \n \n \n \n \n \n \n
\n
\n \n
\n \n \n \n \n \n Page 1/0\n
\n \n \n \n
\n Found lines: 0/0\n
\n';return __p}},function(module,exports,__webpack_require__){var _={escape:__webpack_require__(0)};module.exports=function(obj){obj||(obj={});var __t,__p="";with(obj)__p+='
\n No data available...\n
\n';return __p}},,,,function(e,t,i){"use strict";i.r(t);var n=Backbone.Model.extend({});var l=Backbone.Collection.extend({model:n,url:function(){return`/api/nginx/logs/${this.logType}`},initialize:function(e){this.logType=e.logType}}),o=Backbone.Model.extend({});var a=Backbone.Collection.extend({model:o,url:function(){return`/api/nginx/logs/${this.logType}/${this.uuid}`},initialize:function(e){this.logType=e.logType,this.uuid=e.uuid}}),s=i(16),r=i.n(s);var c=Backbone.View.extend({tagName:"li",events:{"click .mainentry":"mainMenuClick","click .menuEntry":"menuEntryClick","click .dropdown-toggle":"menuDropdownClick"},initialize:function(e){this.listenTo(this.collection,"update",this.render),this.logType=e.logType,this.logview=e.logview,this.render()},render:function(){this.$el.html(""),this.renderCollection()},renderCollection:function(){this.$el.addClass("dropdown"),"global"==this.model.get("id")&&(this.$el.addClass("active"),this.logview.get_log("errors","global",-1)),this.$el.html(""),this.$el.append(r()({model:this.collection,id:this.model.get("id"),name:this.model.has("server_name")?this.model.get("server_name"):"Port "+this.model.get("port")}))},mainMenuClick:function(){this.collection.models[0]&&(this.handleElementClick(this.model.get("id"),-1),$(`#tab_${this.model.get("id")} li`).removeClass("active"),$(`#subtab_item_${this.model.get("id")}_${this.collection.models[0].get("number")}`).parent().addClass("active"))},menuDropdownClick:function(e){this.collection.fetch()},menuEntryClick:function(e){this.handleElementClick(e.target.dataset.modelUuid,e.target.dataset.modelFileno)},handleElementClick:function(e,t){this.logview.get_log(this.logType,e,t)}}),d=i(17),u=i.n(d);Backbone.View.extend({tagName:"li",initialize:function(e){this.logview=e.logview,this.log_name=e.log_name,this.visible_name=e.visible_name,this.log_type=e.log_type},events:{"click .mainentry":"handleElementClick"},log_name:null,log_type:null,visible_name:null,render:function(){this.$el.html(u()({name:this.visible_name}))},handleElementClick:function(){this.logview.get_log(this.log_type,this.log_name)}});var p=Backbone.View.extend({tagName:"ul",className:"nav nav-tabs",initialize:function(e){this.listenTo(this.collection,"update",this.render),this.logview=e.logview,this.logType=e.logType},render:function(){this.$el.attr("role","tablist"),this.$el.html(""),"global"==this.logType?this.render_global_error_tab():this.collection.forEach(e=>this.render_one_server(e))},render_one_server:function(e){const t=new a({uuid:e.get("id"),logType:this.logType}),i=new c({collection:t,model:e,logType:this.logType,logview:this.logview});this.$el.append(i.$el)},render_global_error_tab:function(){const e=new a({uuid:"global",logType:"errors"}),t=new c({collection:e,model:new Backbone.Model({server_name:"Global Error Log",id:"global"}),logType:"errors",logview:this.logview});this.$el.append(t.$el),e.fetch()}}),h=i(18),g=i.n(h),b=i(19),f=i.n(b),m=i(20),v=i.n(m);var y=Backbone.Model.extend({});var w=Backbone.Collection.extend({model:y,url:function(){return`/api/nginx/logs/${this.logType}/${this.uuid}/${this.fileNo}/${this.page}/${this.pageSize}/${this.create_filter()}`},initialize:function(){this.logType="none",this.uuid="none",this.fileNo=-1,this.page=0,this.pageSize=0,this.filter_model=new Backbone.Model},parse:function(e){return"error"in e?[]:(this.page_count=e.pages,this.total_entries=e.total,this.displayed_entries=e.found,e.lines)},create_filter:function(){return encodeURIComponent(JSON.stringify(this.filter_model))}});Backbone.Model.extend({});var k=i(21),x=i.n(k);const j=Backbone.View.extend({tagName:"tr",initialize:function(e){this.type=e.type,this.log_fields_visible=e.log_fields_visible},render:function(){this.$el.html(g()({log_fields_visible:this.log_fields_visible,model:this.model}))}}),T=Backbone.View.extend({tagName:"tr",className:"filter",initialize:function(e){this.log_fields_visible=e.log_fields_visible},render:function(){this.log_fields_visible.forEach(e=>this.$el.append(f()({field:e,model:this.model})))}});const C=new(Backbone.View.extend({tagName:"div",className:"content-box tab-content",events:{"keyup .filter input":"update_filter","click #paging_first":"page_first","click #paging_back":"page_back","click #refresh":"update","click #paging_forward":"page_forward","click #paging_last":"page_last","change #entrycount":"change_entry_count","click .ngx-dropdown-item":"toggle_column"},page_entry_count:100,filter_delay:-1,initialize:function(){this.collection=new w,this.listenTo(this.collection,"sync",this.render),this.listenTo(this.collection,"update",this.render),this.listenTo(this.collection.filter_model,"change",this.render),this.type=""},render:function(){this.logFields=[];let e=this.collection.uuid,t=this.type;switch(t){case"accesses":this.logFields.push({id:"time",header:"Time"},{id:"remote_ip",header:"Remote IP"},{id:"username",header:"Username"},{id:"status",header:"Status"},{id:"size",header:"Size"},{id:"referer",header:"Referer"},{id:"user_agent",header:"User Agent"},{id:"forwarded_for",header:"Forwarded For"},{id:"request_line",header:"Request Line"});break;case"errors":case"stream_errors":this.logFields.push({id:"date",header:"Date"},{id:"time",header:"Time"},{id:"severity",header:"Severity"},{id:"number",header:"Number"},{id:"message",header:"Message"});break;default:this.logFields.push({id:"time",header:"Time"},{id:"remote_ip",header:"Remote IP"},{id:"status",header:"Status"},{id:"bytes_sent",header:"Bytes Sent"},{id:"bytes_received",header:"Bytes Rcvd"},{id:"session_time",header:"Session Time"})}this.logFields.forEach(i=>{i.visible="false"!==localStorage.getItem("visibleColumns["+t+"]["+e+"]["+i.id+"]")}),this.logFieldsVisible=_.filter(this.logFields,["visible",!0]);let i=this.$("thead");if(i.children().length<1){const e=new T({log_fields_visible:this.logFieldsVisible,model:this.collection.filter_model});e.render(),i.html(e.$el)}let n=this.$("tbody");n.length<1?0!==this.collection.length?(this.$el.html(v()({log_type:this.type,log_fields:this.logFields,log_fields_visible:this.logFieldsVisible,model:this.collection.filter_model})),n=this.$("tbody")):this.$el.html(x.a):n.html(""),0!==this.collection.length&&null==this.current_filtered_collection&&this.collection.forEach(e=>this.render_one(n,e)),this.$("#entrycountdisplay").html(this.page_entry_count),this.$("#currentpage").html(this.current_page+1),this.$("#pagecount").html(this.collection.page_count),this.$("#totalcount").html(this.collection.total_entries),this.$("#resultcount").html(this.collection.displayed_entries),this.current_page>=this.collection.page_count-1?(this.$("#paging_last").addClass("disabled"),this.$("#paging_forward").addClass("disabled")):(this.$("#paging_last").removeClass("disabled"),this.$("#paging_forward").removeClass("disabled")),this.current_page<=0?(this.$("#paging_back").addClass("disabled"),this.$("#paging_first").addClass("disabled")):(this.$("#paging_back").removeClass("disabled"),this.$("#paging_first").removeClass("disabled"))},render_one:function(e,t){const i=new j({type:this.type,log_fields_visible:this.logFieldsVisible,model:t});i.render(),e.append(i.$el)},get_log:function(e,t,i){this.collection.uuid=t,this.collection.logType=e,this.collection.fileNo=i,this.type=e,this.current_page=0,this.$el.html(""),this.collection.filter_model.clear(),this.update()},update:function(){this.collection.page=this.current_page,this.collection.pageSize=this.page_entry_count,this.collection.fetch()},update_filter:function(e){clearTimeout(this.filter_delay);const t=e.target;this.collection.filter_model.set(t.name,$(t).val()),this.current_page=0,this.filter_delay=setTimeout(function(e){e.update()},500,this)},page_first:function(){this.current_page=0,this.update()},page_back:function(){this.current_page>0&&(this.current_page--,this.update())},page_forward:function(){this.current_page this.$el.append(LogColumn({field: field, model: this.model}))); + } }); const LogView = Backbone.View.extend({ @@ -39,6 +41,7 @@ const LogView = Backbone.View.extend({ "click #paging_forward": "page_forward", "click #paging_last": "page_last", "change #entrycount": "change_entry_count", + "click .ngx-dropdown-item": "toggle_column", }, page_entry_count: 100, filter_delay: -1, @@ -52,10 +55,60 @@ const LogView = Backbone.View.extend({ }, render: function() { + // set logline fields + // all the fields are visible by default + // users choice is stored in browser localStorage + this.logFields = []; + let uid = this.collection.uuid; + let type = this.type; + switch (type) { + case 'accesses': + this.logFields.push({id: "time", header: "Time"}, + {id: "remote_ip", header: "Remote IP"}, + {id: "username", header: "Username"}, + {id: "status", header: "Status"}, + {id: "size", header: "Size"}, + {id: "referer", header: "Referer"}, + {id: "user_agent", header: "User Agent"}, + {id: "forwarded_for", header: "Forwarded For"}, + {id: "request_line", header: "Request Line"}); + break; + case 'errors': + case 'stream_errors': + this.logFields.push({id: "date", header: "Date"}, + {id: "time", header: "Time"}, + {id: "severity", header: "Severity"}, + {id: "number", header: "Number"}, + {id: "message", header: "Message"}); + break; + default: + // stream access + this.logFields.push({id: "time", header: "Time"}, + {id: "remote_ip", header: "Remote IP"}, + {id: "status", header: "Status"}, + {id: "bytes_sent", header: "Bytes Sent"}, + {id: "bytes_received", header: "Bytes Rcvd"}, + {id: "session_time", header: "Session Time"}); + } + this.logFields.forEach( (field) => { + field.visible = localStorage.getItem('visibleColumns[' + type + '][' + uid + '][' + field.id + ']') !== 'false'; + }); + + this.logFieldsVisible = _.filter(this.logFields, ['visible', true]); + // fields are ready + + // create/update column headers + let thead = this.$('thead'); + if (thead.children().length < 1) { + const logColumns = new LogViewColumns({log_fields_visible: this.logFieldsVisible, model: this.collection.filter_model}); + logColumns.render(); + thead.html(logColumns.$el); + } + let tbody = this.$('tbody'); if (tbody.length < 1) { if (this.collection.length !== 0) { - this.$el.html(logViewer({log_type: this.type, model: this.collection.filter_model})); + this.$el.html(logViewer({log_type: this.type, log_fields: this.logFields, log_fields_visible: this.logFieldsVisible, model: this.collection.filter_model})); tbody = this.$('tbody'); } else { this.$el.html(noDataAvailable); @@ -99,7 +152,7 @@ const LogView = Backbone.View.extend({ }, render_one: function(parent_element, model) { - const logline = new LogViewLine({type: this.type, model: model}); + const logline = new LogViewLine({type: this.type, log_fields_visible: this.logFieldsVisible, model: model}); logline.render(); parent_element.append(logline.$el); }, @@ -161,6 +214,20 @@ const LogView = Backbone.View.extend({ this.page_entry_count = event.target.value; this.current_page = 0; this.update(); + }, + + toggle_column: function (event) { + event.stopPropagation(); + let uid = this.collection.uuid; + let type = this.type; + let field = $(event.currentTarget).find('input').prop('value'); + // toggle visibility + localStorage.setItem('visibleColumns[' + type + '][' + uid + '][' + field + ']', !_.find(this.logFields, { 'id': field }).visible); + // unset filter for this column (if any) so as not to confuse the user + this.collection.filter_model.unset(field, {silent: true}); + // reset table header and update data + this.$('thead').html(''); + this.update(); } }); diff --git a/www/nginx/src/opnsense/www/js/nginx/src/models/LogColumn.js b/www/nginx/src/opnsense/www/js/nginx/src/models/LogColumn.js new file mode 100644 index 000000000..40e01a155 --- /dev/null +++ b/www/nginx/src/opnsense/www/js/nginx/src/models/LogColumn.js @@ -0,0 +1,5 @@ + +const LogColumnModel = Backbone.Model.extend({ +}); + +export default LogColumnModel; diff --git a/www/nginx/src/opnsense/www/js/nginx/src/templates/AccessLogLine.html b/www/nginx/src/opnsense/www/js/nginx/src/templates/AccessLogLine.html deleted file mode 100644 index adde3d4d7..000000000 --- a/www/nginx/src/opnsense/www/js/nginx/src/templates/AccessLogLine.html +++ /dev/null @@ -1,9 +0,0 @@ -<%= model.escape('time') %> -<%= model.escape('remote_ip') %> -<%= model.escape('username') %> -<%= model.escape('status') %> -<%= model.escape('size') %> -<%= model.escape('http_referer') %> -<%= model.escape('user_agent') %> -<%= model.escape('forwarded_for') %> -<%= model.escape('request_line') %> diff --git a/www/nginx/src/opnsense/www/js/nginx/src/templates/ErrorLogLine.html b/www/nginx/src/opnsense/www/js/nginx/src/templates/ErrorLogLine.html deleted file mode 100644 index ec99b4232..000000000 --- a/www/nginx/src/opnsense/www/js/nginx/src/templates/ErrorLogLine.html +++ /dev/null @@ -1,5 +0,0 @@ -<%= model.escape('date') %> -<%= model.escape('time') %> -<%= model.escape('severity') %> -<%= model.escape('number') %> -<%= model.escape('message') %> diff --git a/www/nginx/src/opnsense/www/js/nginx/src/templates/LogColumn.html b/www/nginx/src/opnsense/www/js/nginx/src/templates/LogColumn.html new file mode 100644 index 000000000..92f303ef2 --- /dev/null +++ b/www/nginx/src/opnsense/www/js/nginx/src/templates/LogColumn.html @@ -0,0 +1,6 @@ + +
+ + +
+ diff --git a/www/nginx/src/opnsense/www/js/nginx/src/templates/LogLine.html b/www/nginx/src/opnsense/www/js/nginx/src/templates/LogLine.html new file mode 100644 index 000000000..b7b7881f4 --- /dev/null +++ b/www/nginx/src/opnsense/www/js/nginx/src/templates/LogLine.html @@ -0,0 +1,3 @@ +<% log_fields_visible.forEach( (field) => { %> +<%= model.escape(field.id) %> +<% }) %> diff --git a/www/nginx/src/opnsense/www/js/nginx/src/templates/StreamAccessLogLine.html b/www/nginx/src/opnsense/www/js/nginx/src/templates/StreamAccessLogLine.html deleted file mode 100644 index 54cfd8789..000000000 --- a/www/nginx/src/opnsense/www/js/nginx/src/templates/StreamAccessLogLine.html +++ /dev/null @@ -1,6 +0,0 @@ -<%= model.escape('time') %> -<%= model.escape('remote_ip') %> -<%= model.escape('status') %> -<%= model.escape('bytes_sent') %> -<%= model.escape('bytes_received') %> -<%= model.escape('session_time') %> diff --git a/www/nginx/src/opnsense/www/js/nginx/src/templates/logviewer.html b/www/nginx/src/opnsense/www/js/nginx/src/templates/logviewer.html index a92d60c6e..a1b7e6432 100644 --- a/www/nginx/src/opnsense/www/js/nginx/src/templates/logviewer.html +++ b/www/nginx/src/opnsense/www/js/nginx/src/templates/logviewer.html @@ -1,93 +1,42 @@ -<% let count = 0; %> +
- - <% if (log_type === 'errors' || log_type === 'stream_errors') { - count = 5; %> - - - - - - <% } else if (log_type === 'accesses') { - count = 9; %> - - - - - - - - - - <% } else { - count = 6; %> - - - - - - - <% } %> - - - <% if (log_type === 'errors' || log_type === 'stream_errors') { %> - - - - - - <% } else if (log_type === 'accesses') { %> - - - - - - - - - - <% } else { %> - - - - - - - <% } %> - - - - -
DateTimeSeverityNumberMessageTimeRemote IPUsernameStatusSizeRefererUser AgentForwarded ForRequest LineTimeRemote IPStatusBytes SentBytes ReceivedSession Time
+ +
+ +
+ Page 1/0 +
+ + + +
+ Found lines: 0/0
- Page 1/0 - - - - - - Found lines: 0/0