Skip to content

Commit

Permalink
Fixes #10157: Add an option to not display rule status/recent changes…
Browse files Browse the repository at this point in the history
… in directives screen
  • Loading branch information
fanf committed Feb 9, 2017
1 parent 205d743 commit 31d92bb
Show file tree
Hide file tree
Showing 10 changed files with 203 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ trait ReadConfigService {
*/
def display_changes_graph(): Box[Boolean]

/**
* Should we hide compliance/recent changes column in directive screen for rule ?
*/
def rudder_ui_display_ruleComplianceColumns(): Box[Boolean]

/**
* Should we send backward compatible data from API
*/
Expand Down Expand Up @@ -247,6 +252,11 @@ trait UpdateConfigService {
*/
def set_display_changes_graph(displayGraph : Boolean): Box[Unit]

/**
* Should we hide compliance/recent changes column in directive screen for rule ?
*/
def set_rudder_ui_display_ruleComplianceColumns(Columns: Boolean): Box[Unit]

/**
* Should we send backward compatible data from API
*/
Expand Down Expand Up @@ -295,6 +305,7 @@ class LDAPBasedConfigService(configFile: Config, repos: ConfigRepository, workfl
rudder.compliance.heartbeatPeriod=1
rudder.syslog.protocol=UDP
display.changes.graph=true
rudder.ui.display.ruleComplianceColumns=true
api.compatibility.mode=false
rudder.featureSwitch.directiveScriptEngine=enabled
rudder.featureSwitch.quicksearchEverything=enabled
Expand Down Expand Up @@ -489,9 +500,14 @@ class LDAPBasedConfigService(configFile: Config, repos: ConfigRepository, workfl
* Should we display recent changes graphs ?
*/
def display_changes_graph(): Box[Boolean] = get("display_changes_graph")

def set_display_changes_graph(displayGraphs : Boolean): Box[Unit] = save("display_changes_graph", displayGraphs)

/**
* Should we always display compliance/recent change columns ?
*/
def rudder_ui_display_ruleComplianceColumns(): Box[Boolean] = get("rudder_ui_display_ruleComplianceColumns")
def set_rudder_ui_display_ruleComplianceColumns(displayColumns: Boolean): Box[Unit] = save("rudder_ui_display_ruleComplianceColumns", displayColumns)

/**
* Should we send backward compatible data from API
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,12 @@ class DirectiveEditForm(
case Full(pe) => pe
case Empty => {
val errMsg = "Can not initialize the parameter editor for Directive %s " +
"(template %s). No error returned"
"(template %s). No error returned"
throw new IllegalArgumentException(errMsg.format(directive.id, technique.id))
}
case Failure(m, _, _) => {
val errMsg = "Can not initialize the parameter editor for Directive %s " +
"(template %s). Error message: %s"
"(template %s). Error message: %s"
throw new IllegalArgumentException(errMsg.format(directive.id, technique.id, m))
}
}
Expand Down Expand Up @@ -193,6 +193,8 @@ class DirectiveEditForm(
, (_ :Rule,_ : String) => Noop
, (_ : Rule) => Noop
, (_ : Option[Rule]) => Noop
, DisplayColumn.FromConfig
, DisplayColumn.FromConfig
).display
}

Expand All @@ -214,7 +216,7 @@ class DirectiveEditForm(
val agentCompEmpty : NodeSeq =
<span>
Can be used on any agent.
</span>
</span>
technique.compatible match {
case None =>
(osCompEmpty,agentCompEmpty)
Expand All @@ -233,7 +235,7 @@ class DirectiveEditForm(
case agent =>
<span>
{agent.mkString(", ")}
</span>
</span>
}
(osComp,agentComp)
}
Expand Down Expand Up @@ -412,16 +414,16 @@ class DirectiveEditForm(
<div>
<b>Priority:</b>
<span class="tw-bs">
<span tooltipid="priorityId" class="ruddericon tooltipable glyphicon glyphicon-question-sign" title=""></span>
<span tooltipid="priorityId" class="ruddericon tooltipable glyphicon glyphicon-question-sign" title=""></span>
<div class="tooltipContent" id="priorityId">
<h4> Priority </h4>
Priority determines which <b> unique </b> Directive will be applied.
<br/>
Unique Directives can be applied only once (ie. Time Settings), so only the highest priority will be appllied.
<br/>
Highest Priority is 0
<h4> Priority </h4>
Priority determines which <b> unique </b> Directive will be applied.
<br/>
Unique Directives can be applied only once (ie. Time Settings), so only the highest priority will be appllied.
<br/>
Highest Priority is 0
</div>
</span>
</span>
</div>
override def className = "twoCol"
override def labelClassName = "threeCol directiveInfo"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ class RuleDisplayer (
, gridId : String
, detailsCallbackLink : (Rule, String) => JsCmd
, onCreateRule : (Rule) => JsCmd
, showRulePopup : (Option[Rule]) => JsCmd
, showRulePopup : (Option[Rule]) => JsCmd
, columnCompliance : DisplayColumn
, columnRecentChanges : DisplayColumn
) extends DispatchSnippet with Loggable {

private[this] val ruleRepository = RudderConfig.roRuleRepository
Expand Down Expand Up @@ -171,9 +173,10 @@ class RuleDisplayer (
new RuleGrid(
"rules_grid_zone"
, callbackLink
, configService.display_changes_graph
, directive.isDefined
, directive
, columnCompliance
, columnRecentChanges
)
}
def includeSubCategory = {
Expand All @@ -200,8 +203,8 @@ class RuleDisplayer (
</lift:authz>
<div style={s"margin:10px 0px 0px ${if (directive.isDefined) 0 else 50}px; float:left"}>{includeSubCategory} <span style="margin-left:10px;"> Display Rules from subcategories</span></div>
<hr class="spacer"/>
{ ruleGrid.rulesGridWithUpdatedInfo(None, !directive.isDefined, true) ++
Script(OnLoad(ruleGrid.asyncDisplayAllRules(None, true, configService.display_changes_graph().openOr(true)).applied))
{ ruleGrid.rulesGridWithUpdatedInfo(None, !directive.isDefined) ++
Script(OnLoad(ruleGrid.asyncDisplayAllRules(None).applied))
}

</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,27 @@ object RuleGrid {
</head>
}

/**
* An ADT to denote if a column should be display or not,
* or if is should be decided from config service.
*/
sealed trait DisplayColumn
final object DisplayColumn {
final case class Force(display: Boolean) extends DisplayColumn
final object FromConfig extends DisplayColumn
}

class RuleGrid(
htmlId_rulesGridZone: String
//JS callback to call when clicking on a line
, detailsCallbackLink : Option[(Rule,String) => JsCmd]
, getDisplayChanges : () => Box[Boolean]
, showCheckboxColumn :Boolean = true
, directiveApplication: Option[DirectiveApplicationManagement] = None
, showCheckboxColumn : Boolean
, directiveApplication: Option[DirectiveApplicationManagement]
, columnCompliance : DisplayColumn
, columnRecentChanges : DisplayColumn
) extends DispatchSnippet with Loggable {


private[this] sealed trait Line { val rule:Rule }

private[this] case class OKLine(
Expand All @@ -125,18 +137,19 @@ class RuleGrid(
private[this] val getFullNodeGroupLib = RudderConfig.roNodeGroupRepository.getFullGroupLibrary _
private[this] val getFullDirectiveLib = RudderConfig.roDirectiveRepository.getFullDirectiveLibrary _
private[this] val getRuleApplicationStatus = RudderConfig.ruleApplicationStatus.isApplied _
private[this] val getAllNodeInfos = RudderConfig.nodeInfoService.getAll _
private[this] val getRootRuleCategory = RudderConfig.roRuleCategoryRepository.getRootCategory _
private[this] val getAllNodeInfos = RudderConfig.nodeInfoService.getAll _
private[this] val getRootRuleCategory = RudderConfig.roRuleCategoryRepository.getRootCategory _

private[this] val recentChanges = RudderConfig.recentChangesService
private[this] val techniqueRepository = RudderConfig.techniqueRepository
private[this] val categoryService = RudderConfig.ruleCategoryService
private[this] val asyncComplianceService = RudderConfig.asyncComplianceService
private[this] val recentChanges = RudderConfig.recentChangesService
private[this] val techniqueRepository = RudderConfig.techniqueRepository
private[this] val categoryService = RudderConfig.ruleCategoryService
private[this] val asyncComplianceService = RudderConfig.asyncComplianceService
private[this] val configService = RudderConfig.configService

//used to error tempering
private[this] val roRuleRepository = RudderConfig.roRuleRepository
private[this] val woRuleRepository = RudderConfig.woRuleRepository
private[this] val uuidGen = RudderConfig.stringUuidGenerator
private[this] val roRuleRepository = RudderConfig.roRuleRepository
private[this] val woRuleRepository = RudderConfig.woRuleRepository
private[this] val uuidGen = RudderConfig.stringUuidGenerator

///// local variables /////
private[this] val htmlId_rulesGridId = "grid_" + htmlId_rulesGridZone
Expand All @@ -145,6 +158,36 @@ class RuleGrid(
private[this] val htmlId_rulesGridWrapper = htmlId_rulesGridId + "_wrapper"
private[this] val tableId_reportsPopup = "popupReportsGrid"

/*
* Compliance and recent changes columns (not forced):
* - we display compliance if rudder_ui_display_ruleComplianceColumns is true,
* - we display recent changes only if compliance is displayed AND diplay_recent_changes is true
*
* If the configService is not available, display
*
* The will is to have the following result: (C = compliance column, R = recent changes columns)
*
* Screen \ config | C=1 R=1 | C=1 R=0 | C=0 R=1 | C=0 R=0 |
* ---------------------------------------------------------
* Rules | C=1 R=1 | C=1 R=0 | C=1 R=1 | C=1 R=0 |
* ---------------------------------------------------------
* Directives | C=1 R=1 | C=1 R=0 | C=0 R=0 | C=0 R=0 |
* ---------------------------------------------------------
* Accept Node | |
* ----------------- C=0 R=0 |
* Validate Change | |
* ---------------------------------------------------------
*/
import DisplayColumn._
private[this] val showComplianceColumn = columnCompliance match {
case Force(display) => display
case FromConfig => configService.rudder_ui_display_ruleComplianceColumns.openOr(true)
}
private[this] val showRecentChanges = showComplianceColumn && (columnRecentChanges match {
case Force(display) => display
case FromConfig => configService.display_changes_graph.openOr(true)
})

def templatePath = List("templates-hidden", "reports_grid")
def template() = Templates(templatePath) match {
case Empty | Failure(_,_,_) =>
Expand All @@ -154,13 +197,13 @@ class RuleGrid(
def reportTemplate = chooseTemplate("reports", "report", template)

def dispatch = {
case "rulesGrid" => { _:NodeSeq => rulesGridWithUpdatedInfo(None, true, true)}
case "rulesGrid" => { _:NodeSeq => rulesGridWithUpdatedInfo(None, true)}
}

/**
* Display all the rules. All data are charged asynchronously.
*/
def asyncDisplayAllRules(onlyRules: Option[Set[RuleId]], showComplianceColumns: Boolean, showRecentChanges: Boolean) = {
def asyncDisplayAllRules(onlyRules: Option[Set[RuleId]]) = {
AnonFunc(SHtml.ajaxCall(JsNull, (s) => {

val start = System.currentTimeMillis
Expand All @@ -173,14 +216,14 @@ class RuleGrid(
afterRules = System.currentTimeMillis
_ = TimingDebugLogger.debug(s"Rule grid: fetching all Rules took ${afterRules - start}ms" )

futureChanges = if(showComplianceColumns) changesFuture(rules) else changesFuture(Seq())
futureChanges = if(showRecentChanges) ajaxChanges(changesFuture(rules)) else Noop

nodeInfo <- getAllNodeInfos()
afterNodeInfos = System.currentTimeMillis
_ = TimingDebugLogger.debug(s"Rule grid: fetching all Nodes informations took ${afterNodeInfos - afterRules}ms" )

// we have all the data we need to start our future
futureCompliance = if(showComplianceColumns) asyncComplianceService.complianceByRule(nodeInfo.keys.toSet, rules.map(_.id).toSet, htmlId_rulesGridId) else Noop
futureCompliance = if(showComplianceColumn) asyncComplianceService.complianceByRule(nodeInfo.keys.toSet, rules.map(_.id).toSet, htmlId_rulesGridId) else Noop

groupLib <- getFullNodeGroupLib()
afterGroups = System.currentTimeMillis
Expand All @@ -206,7 +249,7 @@ class RuleGrid(
recentGraphs = {};
refreshTable("${htmlId_rulesGridId}", ${newData.json.toJsCmd});
${futureCompliance.toJsCmd}
${ajaxChanges(showRecentChanges,futureChanges).toJsCmd}
${futureChanges.toJsCmd}
""")
}
) match {
Expand All @@ -223,7 +266,7 @@ class RuleGrid(
/**
* Display the selected set of rules.
*/
def rulesGridWithUpdatedInfo(rules: Option[Seq[Rule]], showActionsColumn: Boolean, showComplianceColumns: Boolean): NodeSeq = {
def rulesGridWithUpdatedInfo(rules: Option[Seq[Rule]], showActionsColumn: Boolean): NodeSeq = {

(for {
allNodeInfos <- getAllNodeInfos()
Expand All @@ -250,31 +293,23 @@ class RuleGrid(
case Full(tableData) =>

val allcheckboxCallback = AnonFunc("checked",SHtml.ajaxCall(JsVar("checked"), (in : String) => selectAllVisibleRules(in.toBoolean)))
val (showRecentChanges, errorProperty) = getDisplayChanges() match {
case Full(display) => (display, None)
case eb: EmptyBox =>
val fail = eb ?~! "Error while fetching 'display graph' property, displaying them by default"
logger.warn(fail.messageChain)
(true, Some(fail.msg))
}
val onLoad =
s"""createRuleTable (
"${htmlId_rulesGridId}"
"${htmlId_rulesGridId}"
, ${tableData.json.toJsCmd}
, ${showCheckboxColumn}
, ${showActionsColumn}
, ${showComplianceColumns}
, ${showComplianceColumn}
, ${showRecentChanges}
, ${allcheckboxCallback.toJsCmd}
, "${S.contextPath}"
, ${asyncDisplayAllRules(rules.map(_.map(_.id).toSet), showComplianceColumns, showRecentChanges).toJsCmd}
, ${asyncDisplayAllRules(rules.map(_.map(_.id).toSet)).toJsCmd}
);
createTooltip();
createTooltiptr();
$$('#${htmlId_rulesGridWrapper}').css("margin","10px 0px 0px 0px");
"""
<div id={htmlId_rulesGridZone}>
<span class="error" id="ruleTableError">{errorProperty.getOrElse("")}</span>
<div id={htmlId_modalReportsPopup} class="nodisplay">
<div id={htmlId_reportsPopup} ></div>
</div>
Expand Down Expand Up @@ -353,7 +388,7 @@ class RuleGrid(
}

// Ajax call back to get recent changes
private[this] def ajaxChanges(displayGraph: Boolean, future : Future[Box[Map[RuleId,Map[Interval, Int]]]]) : JsCmd = {
private[this] def ajaxChanges(future : Future[Box[Map[RuleId,Map[Interval, Int]]]]) : JsCmd = {
SHtml.ajaxInvoke( () => {
// Is my future completed ?
if( future.isCompleted ) {
Expand All @@ -365,7 +400,7 @@ class RuleGrid(
} yield {
val changeCount = change.values.sum
val data = NodeChanges.json(change, recentChanges.getCurrentValidIntervals(None))
s"""computeChangeGraph(${data.toJsCmd},"${ruleId.value}",currentPageIds, ${changeCount}, ${displayGraph})"""
s"""computeChangeGraph(${data.toJsCmd},"${ruleId.value}",currentPageIds, ${changeCount})"""
}

JsRaw(s"""
Expand All @@ -382,7 +417,7 @@ class RuleGrid(
Alert(error.messageChain)
}
} else {
After(500,ajaxChanges(displayGraph,future))
After(500,ajaxChanges(future))
}
} )

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import net.liftweb.util.ClearClearable
import net.liftweb.util.Helpers._
import scala.xml.NodeSeq
import scala.xml.Text
import com.normation.rudder.web.components.DisplayColumn

object ExpectedPolicyPopup {

Expand Down Expand Up @@ -84,7 +85,8 @@ class ExpectedPolicyPopup(
//find the list of dyn groups on which that server would be and from that, the Rules
val rulesGrid : NodeSeq = getDependantRulesForNode match {
case Full(seq) =>
(new RuleGrid("dependentRulesGrid", None, () => Full(false), false )).rulesGridWithUpdatedInfo(Some(seq), false, false)
val noDisplay = DisplayColumn.Force(false)
(new RuleGrid("dependentRulesGrid", None, false, None, noDisplay, noDisplay)).rulesGridWithUpdatedInfo(Some(seq), false)
case e:EmptyBox =>
val msg = "Error when trying to find dependencies for that group"
logger.error(msg, e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ import com.normation.rudder.domain.nodes.AddNodeGroupDiff
import com.normation.rudder.domain.nodes.DeleteNodeGroupDiff
import com.normation.rudder.domain.nodes.ModifyToNodeGroupDiff
import com.normation.utils.Control.boxSequence
import com.normation.rudder.web.components.DisplayColumn

/**
* Validation pop-up for modification on group and directive.
Expand Down Expand Up @@ -371,8 +372,9 @@ class ModificationValidationPopup(
case CreateSolo => NodeSeq.Empty
case x if(rules.size <= 0) => NodeSeq.Empty
case x =>
val cmp = new RuleGrid("remove_popup_grid", None, () => Full(false), false)
cmp.rulesGridWithUpdatedInfo(Some(rules.toSeq), false, false)
val noDisplay = DisplayColumn.Force(false)
val cmp = new RuleGrid("remove_popup_grid", None, false, None, noDisplay, noDisplay)
cmp.rulesGridWithUpdatedInfo(Some(rules.toSeq), false)
}
}

Expand Down
Loading

0 comments on commit 31d92bb

Please sign in to comment.