From ecf3f696209d971f7dc78d3e292b8d173ee6957d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Membr=C3=A9?= Date: Sun, 15 Sep 2019 23:22:44 +0200 Subject: [PATCH] Work in progress --- .../rudder/repository/ReportsRepository.scala | 7 +++++- .../jdbc/ReportsJdbcRepository.scala | 11 ++++++++ .../bootstrap/liftweb/RudderConfig.scala | 1 + .../components/ShowNodeDetailsFromNode.scala | 2 +- .../rudder/web/services/LogDisplayer.scala | 18 +++++++------ .../rudder/web/services/ReportDisplayer.scala | 15 ++++++++++- .../dataTables-rowGroup-1.1.0.min.js | 25 +++++++++++++++++++ .../javascript/rudder/rudder-datatable.js | 8 ++++++ .../datatables/dataTables.bootstrap.min.css | 1 + .../rowGroup-bootstrap-1.1.0.min.css | 1 + .../templates-hidden/common-layout.html | 3 +++ .../templates-hidden/reports_server.html | 4 +++ 12 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 webapp/sources/rudder/rudder-web/src/main/webapp/javascript/jquery/datatables/dataTables-rowGroup-1.1.0.min.js create mode 100644 webapp/sources/rudder/rudder-web/src/main/webapp/style/datatables/dataTables.bootstrap.min.css create mode 100644 webapp/sources/rudder/rudder-web/src/main/webapp/style/datatables/rowGroup-bootstrap-1.1.0.min.css diff --git a/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/repository/ReportsRepository.scala b/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/repository/ReportsRepository.scala index bf77a544d59..79dcceac372 100644 --- a/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/repository/ReportsRepository.scala +++ b/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/repository/ReportsRepository.scala @@ -84,11 +84,16 @@ trait ReportsRepository { ) : Seq[Reports] def findReportsByNodeOnInterval( - nodeId: NodeId + nodeId: NodeId , start : DateTime , end : DateTime ) : Seq[Reports] + def findReportsByNodeByRun( + nodeId: NodeId + , runDate : DateTime + ) : Seq[Reports] + //databaseManager only def getReportsInterval() : Box[(Option[DateTime], Option[DateTime])] def getArchivedReportsInterval() : Box[(Option[DateTime], Option[DateTime])] diff --git a/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/repository/jdbc/ReportsJdbcRepository.scala b/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/repository/jdbc/ReportsJdbcRepository.scala index cb6f97f20f3..7b7bcea1f64 100644 --- a/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/repository/jdbc/ReportsJdbcRepository.scala +++ b/webapp/sources/rudder/rudder-core/src/main/scala/com/normation/rudder/repository/jdbc/ReportsJdbcRepository.scala @@ -100,6 +100,17 @@ class ReportsJdbcRepository(doobie: Doobie) extends ReportsRepository with Logga transactRun(xa => q.to[Vector].transact(xa)) } + + override def findReportsByNodeByRun( + nodeId: NodeId + , runDate : DateTime + ) : Vector[Reports] = { + val q = Query[(NodeId, DateTime), Reports](baseQuery + + " and nodeId = ? and executionTimeStamp = ? ORDER BY executionTimeStamp asc" + , None).toQuery0((nodeId, runDate)) + transactRun(xa => q.to[Vector].transact(xa)) + } + override def findReportsByNodeOnInterval( nodeId: NodeId , start : DateTime diff --git a/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/RudderConfig.scala b/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/RudderConfig.scala index b92eeb2909a..696f8628b0c 100644 --- a/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/RudderConfig.scala +++ b/webapp/sources/rudder/rudder-web/src/main/scala/bootstrap/liftweb/RudderConfig.scala @@ -1809,6 +1809,7 @@ object RudderConfig extends Loggable { , reportingServiceImpl , techniqueRepositoryImpl , configService + , logDisplayerImpl ) private[this] lazy val propertyRepository = new RudderPropertiesRepositoryImpl(doobie) private[this] lazy val autoReportLogger = new AutomaticReportLogger( diff --git a/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/components/ShowNodeDetailsFromNode.scala b/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/components/ShowNodeDetailsFromNode.scala index 0ea019bae2f..e8fb5d8abe0 100644 --- a/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/components/ShowNodeDetailsFromNode.scala +++ b/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/components/ShowNodeDetailsFromNode.scala @@ -279,7 +279,7 @@ class ShowNodeDetailsFromNode( "#nodeDetails" #> DisplayNode.showNodeDetails(inventory, Some((node, globalMode)), Some(node.creationDate), AcceptedInventory, isDisplayingInPopup = withinPopup) & "#nodeInventory *" #> DisplayNode.show(inventory, false) & "#reportsDetails *" #> reportDisplayer.asyncDisplay(node) & - "#logsDetails *" #> logDisplayer.asyncDisplay(node.id) & + "#logsDetails *" #> Script(OnLoad(logDisplayer.asyncDisplay(node.id,None))) & "#node_parameters -*" #> (if(node.id == Constants.ROOT_POLICY_SERVER_ID) NodeSeq.Empty else nodeStateEditForm(node).nodeStateConfiguration) & "#node_parameters -*" #> agentPolicyModeEditForm.cfagentPolicyModeConfiguration & "#node_parameters -*" #> agentScheduleEditForm(node).cfagentScheduleConfiguration & diff --git a/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/services/LogDisplayer.scala b/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/services/LogDisplayer.scala index 9d7507406cb..a422008adcd 100644 --- a/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/services/LogDisplayer.scala +++ b/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/services/LogDisplayer.scala @@ -41,7 +41,6 @@ import com.normation.rudder.domain.policies.RuleId import com.normation.rudder.web.model._ import com.normation.inventory.domain.NodeId import com.normation.rudder.domain.reports.Reports -import scala.xml._ import net.liftweb.common._ import net.liftweb.http._ import net.liftweb.http.js._ @@ -76,10 +75,12 @@ class LogDisplayer( private val gridName = "logsGrid" - def asyncDisplay(nodeId : NodeId) : NodeSeq = { + def asyncDisplay(nodeId : NodeId, runDate : Option[DateTime]) = { val id = JsNodeId(nodeId) - val ajaxRefresh = SHtml.ajaxInvoke( () => refreshData(nodeId, reportRepository.findReportsByNode(nodeId))) - + val ajaxRefresh = runDate match { + case Some(runDate) => SHtml.ajaxInvoke (() => refreshData (nodeId, reportRepository.findReportsByNodeByRun (nodeId, runDate).filter(_.severity.startsWith("log")) ) ) + case None => SHtml.ajaxInvoke (() => refreshData (nodeId, reportRepository.findReportsByNode (nodeId) ) ) + } def getEventsInterval(jsonInterval: String): JsCmd = { import net.liftweb.util.Helpers.tryo import net.liftweb.json.parse @@ -113,19 +114,17 @@ class LogDisplayer( } } - Script( - OnLoad( // set static content SetHtml("logsDetails",content) & // Create empty table JsRaw(s""" + console.log("${runDate}") var pickEventLogsInInterval = ${AnonFunc(SHtml.ajaxCall(JsRaw( """'{"start":"'+$(".pickStartInput").val()+'", "end":"'+$(".pickEndInput").val()+'"}'""" ), getEventsInterval)._2).toJsCmd} createTechnicalLogsTable("${gridName}",[], "${S.contextPath}",function() {${ajaxRefresh.toJsCmd}}, pickEventLogsInInterval);""") & // Load data asynchronously - JsRaw( s""" $$("#details_${id}").on( "tabsactivate", function(event, ui) { @@ -134,7 +133,7 @@ class LogDisplayer( } }); """ - ))) + ) } /** @@ -169,6 +168,7 @@ class LogDisplayer( ReportLine ( report.executionDate + , report.executionTimestamp , report.severity , ruleName , directiveName @@ -205,6 +205,7 @@ class LogDisplayer( */ case class ReportLine ( executionDate : DateTime + , runDate : DateTime , severity : String , ruleName : String , directiveName : String @@ -217,6 +218,7 @@ case class ReportLine ( JsObj( ( "executionDate", executionDate.toString("yyyy-MM-dd HH:mm:ss") ) + , ( "runDate", runDate.toString("yyyy-MM-dd HH:mm:ss") ) , ( "severity" , severity ) , ( "ruleName" , escapeHTML(ruleName) ) , ( "directiveName", escapeHTML(directiveName) ) diff --git a/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/services/ReportDisplayer.scala b/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/services/ReportDisplayer.scala index 19195e4255d..69b470d4440 100644 --- a/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/services/ReportDisplayer.scala +++ b/webapp/sources/rudder/rudder-web/src/main/scala/com/normation/rudder/web/services/ReportDisplayer.scala @@ -52,14 +52,15 @@ import net.liftweb.http.js.JsCmd import net.liftweb.http.js.JsCmds._ import net.liftweb.util.Helpers._ import org.joda.time.format.DateTimeFormat + import scala.xml.NodeSeq import scala.xml.NodeSeq.seqToNodeSeq import com.normation.appconfig.ReadConfigService import com.normation.rudder.domain.policies.PolicyMode import com.normation.rudder.web.ChooseTemplate import com.normation.rudder.domain.nodes.NodeState - import com.normation.box._ +import org.joda.time.DateTime /** * Display the last reports of a server @@ -71,6 +72,7 @@ class ReportDisplayer( , reportingService : ReportingService , techniqueRepository : TechniqueRepository , configService : ReadConfigService + , logDisplayer: LogDisplayer ) extends Loggable { private[this] val getAllNodeInfos = RudderConfig.nodeInfoService.getAll _ @@ -108,9 +110,20 @@ class ReportDisplayer( for { report <- reportingService.findNodeStatusReport(node.id) data <- getComplianceData(node.id, report) + runDate : Option[DateTime] = report.runInfo match { + case a : ComputeCompliance => Some(a.lastRunDateTime) + case a : LastRunAvailable => Some(a.lastRunDateTime) + case a : NoExpectedReport => Some(a.lastRunDateTime) + case a : NoReportInInterval => None + case a : Pending => a.optLastRun.map(_._1) + case a : ReportsDisabledInInterval => None + case NoRunNoExpectedReport => None + + } } yield { import net.liftweb.util.Helpers.encJs val intro = encJs(displayIntro(report).toString) + logDisplayer.asyncDisplay(node.id,runDate) & JsRaw(s"""refreshTable("reportsGrid",${data.json.toJsCmd}); $$("#node-compliance-intro").replaceWith(${intro})""") } } diff --git a/webapp/sources/rudder/rudder-web/src/main/webapp/javascript/jquery/datatables/dataTables-rowGroup-1.1.0.min.js b/webapp/sources/rudder/rudder-web/src/main/webapp/javascript/jquery/datatables/dataTables-rowGroup-1.1.0.min.js new file mode 100644 index 00000000000..ca1f5922c7f --- /dev/null +++ b/webapp/sources/rudder/rudder-web/src/main/webapp/javascript/jquery/datatables/dataTables-rowGroup-1.1.0.min.js @@ -0,0 +1,25 @@ +/*! + Copyright 2017-2018 SpryMedia Ltd. + + This source file is free software, available under the following license: + MIT license - http://datatables.net/license/mit + + This source file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. + + For details please refer to: http://www.datatables.net + RowGroup 1.1.0 + ©2017-2018 SpryMedia Ltd - datatables.net/license +*/ +var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.findInternal=function(a,d,c){a instanceof String&&(a=String(a));for(var e=a.length,f=0;f").append(a("").attr("colspan",this._colspan()).append(b))).addClass(this.c.className).addClass(g).addClass("dtrg-level-"+c)}});h.defaults={className:"dtrg-group",dataSrc:0,emptyDataGroup:"No group",enable:!0,endClassName:"dtrg-end",endRender:null,startClassName:"dtrg-start",startRender:function(a,c){return c}};h.version="1.1.0";a.fn.dataTable.RowGroup=h;a.fn.DataTable.RowGroup= +h;f.Api.register("rowGroup()",function(){return this});f.Api.register("rowGroup().disable()",function(){return this.iterator("table",function(a){a.rowGroup&&a.rowGroup.enable(!1)})});f.Api.register("rowGroup().enable()",function(a){return this.iterator("table",function(b){b.rowGroup&&b.rowGroup.enable(a===e?!0:a)})});f.Api.register("rowGroup().dataSrc()",function(a){return a===e?this.context[0].rowGroup.dataSrc():this.iterator("table",function(b){b.rowGroup&&b.rowGroup.dataSrc(a)})});a(c).on("preInit.dt.dtrg", +function(b,c,d){"dt"===b.namespace&&(b=c.oInit.rowGroup,d=f.defaults.rowGroup,b||d)&&(d=a.extend({},d,b),!1!==b&&new h(c,d))});return h}); diff --git a/webapp/sources/rudder/rudder-web/src/main/webapp/javascript/rudder/rudder-datatable.js b/webapp/sources/rudder/rudder-web/src/main/webapp/javascript/rudder/rudder-datatable.js index 4f701571f62..b7c1070353e 100644 --- a/webapp/sources/rudder/rudder-web/src/main/webapp/javascript/rudder/rudder-datatable.js +++ b/webapp/sources/rudder/rudder-web/src/main/webapp/javascript/rudder/rudder-datatable.js @@ -1235,12 +1235,20 @@ function createTechnicalLogsTable(gridId, data, contextPath, refresh, pickEventL "sWidth": "24%" , "mDataProp": "message" , "sTitle": "Message" + } , { + "mDataProp": "runDate" + , "sTitle": "Run date" + , "bVisible" : false } ]; + console.log("youhouh") var params = { "bFilter" : true , "bPaginate" : true , "bLengthChange": true + , "rowGroup": { + dataSrc: 'runDate' + } , "sPaginationType": "full_numbers" , "oLanguage": { "sSearch": "" diff --git a/webapp/sources/rudder/rudder-web/src/main/webapp/style/datatables/dataTables.bootstrap.min.css b/webapp/sources/rudder/rudder-web/src/main/webapp/style/datatables/dataTables.bootstrap.min.css new file mode 100644 index 00000000000..16ed63758d2 --- /dev/null +++ b/webapp/sources/rudder/rudder-web/src/main/webapp/style/datatables/dataTables.bootstrap.min.css @@ -0,0 +1 @@ +table.dataTable{clear:both;margin-top:6px !important;margin-bottom:6px !important;max-width:none !important;border-collapse:separate !important}table.dataTable td,table.dataTable th{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}table.dataTable td.dataTables_empty,table.dataTable th.dataTables_empty{text-align:center}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}div.dataTables_wrapper div.dataTables_length label{font-weight:normal;text-align:left;white-space:nowrap}div.dataTables_wrapper div.dataTables_length select{width:75px;display:inline-block}div.dataTables_wrapper div.dataTables_filter{text-align:right}div.dataTables_wrapper div.dataTables_filter label{font-weight:normal;white-space:nowrap;text-align:left}div.dataTables_wrapper div.dataTables_filter input{margin-left:0.5em;display:inline-block;width:auto}div.dataTables_wrapper div.dataTables_info{padding-top:8px;white-space:nowrap}div.dataTables_wrapper div.dataTables_paginate{margin:0;white-space:nowrap;text-align:right}div.dataTables_wrapper div.dataTables_paginate ul.pagination{margin:2px 0;white-space:nowrap}div.dataTables_wrapper div.dataTables_processing{position:absolute;top:50%;left:50%;width:200px;margin-left:-100px;margin-top:-26px;text-align:center;padding:1em 0}table.dataTable thead>tr>th.sorting_asc,table.dataTable thead>tr>th.sorting_desc,table.dataTable thead>tr>th.sorting,table.dataTable thead>tr>td.sorting_asc,table.dataTable thead>tr>td.sorting_desc,table.dataTable thead>tr>td.sorting{padding-right:30px}table.dataTable thead>tr>th:active,table.dataTable thead>tr>td:active{outline:none}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc_disabled{cursor:pointer;position:relative}table.dataTable thead .sorting:after,table.dataTable thead .sorting_asc:after,table.dataTable thead .sorting_desc:after,table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:after{position:absolute;bottom:8px;right:8px;display:block;font-family:'Glyphicons Halflings';opacity:0.5}table.dataTable thead .sorting:after{opacity:0.2;content:"\e150"}table.dataTable thead .sorting_asc:after{content:"\e155"}table.dataTable thead .sorting_desc:after{content:"\e156"}table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:after{color:#eee}div.dataTables_scrollHead table.dataTable{margin-bottom:0 !important}div.dataTables_scrollBody table{border-top:none;margin-top:0 !important;margin-bottom:0 !important}div.dataTables_scrollBody table thead .sorting:after,div.dataTables_scrollBody table thead .sorting_asc:after,div.dataTables_scrollBody table thead .sorting_desc:after{display:none}div.dataTables_scrollBody table tbody tr:first-child th,div.dataTables_scrollBody table tbody tr:first-child td{border-top:none}div.dataTables_scrollFoot table{margin-top:0 !important;border-top:none}@media screen and (max-width: 767px){div.dataTables_wrapper div.dataTables_length,div.dataTables_wrapper div.dataTables_filter,div.dataTables_wrapper div.dataTables_info,div.dataTables_wrapper div.dataTables_paginate{text-align:center}}table.dataTable.table-condensed>thead>tr>th{padding-right:20px}table.dataTable.table-condensed .sorting:after,table.dataTable.table-condensed .sorting_asc:after,table.dataTable.table-condensed .sorting_desc:after{top:6px;right:6px}table.table-bordered.dataTable th,table.table-bordered.dataTable td{border-left-width:0}table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable td:last-child,table.table-bordered.dataTable td:last-child{border-right-width:0}table.table-bordered.dataTable tbody th,table.table-bordered.dataTable tbody td{border-bottom-width:0}div.dataTables_scrollHead table.table-bordered{border-bottom-width:0}div.table-responsive>div.dataTables_wrapper>div.row{margin:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^="col-"]:first-child{padding-left:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^="col-"]:last-child{padding-right:0} diff --git a/webapp/sources/rudder/rudder-web/src/main/webapp/style/datatables/rowGroup-bootstrap-1.1.0.min.css b/webapp/sources/rudder/rudder-web/src/main/webapp/style/datatables/rowGroup-bootstrap-1.1.0.min.css new file mode 100644 index 00000000000..ed986cc66c7 --- /dev/null +++ b/webapp/sources/rudder/rudder-web/src/main/webapp/style/datatables/rowGroup-bootstrap-1.1.0.min.css @@ -0,0 +1 @@ +table.dataTable tr.dtrg-group td{background-color:#e0e0e0}table.dataTable tr.dtrg-group.dtrg-level-0 td{font-weight:bold}table.dataTable tr.dtrg-group.dtrg-level-1 td,table.dataTable tr.dtrg-group.dtrg-level-2 td{background-color:#f0f0f0;padding-top:0.25em;padding-bottom:0.25em;padding-left:2em;font-size:0.9em}table.dataTable tr.dtrg-group.dtrg-level-2 td{background-color:#f3f3f3} diff --git a/webapp/sources/rudder/rudder-web/src/main/webapp/templates-hidden/common-layout.html b/webapp/sources/rudder/rudder-web/src/main/webapp/templates-hidden/common-layout.html index ed00dbbf4ea..1a7d36125df 100644 --- a/webapp/sources/rudder/rudder-web/src/main/webapp/templates-hidden/common-layout.html +++ b/webapp/sources/rudder/rudder-web/src/main/webapp/templates-hidden/common-layout.html @@ -23,6 +23,8 @@ + + @@ -34,6 +36,7 @@ + diff --git a/webapp/sources/rudder/rudder-web/src/main/webapp/templates-hidden/reports_server.html b/webapp/sources/rudder/rudder-web/src/main/webapp/templates-hidden/reports_server.html index 82b97a065fa..7de53f3e3e7 100644 --- a/webapp/sources/rudder/rudder-web/src/main/webapp/templates-hidden/reports_server.html +++ b/webapp/sources/rudder/rudder-web/src/main/webapp/templates-hidden/reports_server.html @@ -3,7 +3,11 @@ + +
+ +