Skip to content

Commit

Permalink
Fixes #14536: Add a button to show/hide Directives and Groups tree in…
Browse files Browse the repository at this point in the history
… Rule details
  • Loading branch information
fanf authored and RaphaelGauthier committed Mar 29, 2019
1 parent 6cfc181 commit c503ddc
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 78 deletions.
Expand Up @@ -78,6 +78,9 @@ class LinkUtil (
def groupLink(id:NodeGroupId) =
s"""${S.contextPath}${baseGroupLink(id)}"""

def targetLink(target: RuleTarget) =
s"""${S.contextPath}${baseTargetLink(target)}"""

def redirectToGroupLink(id:NodeGroupId) : JsCmd=
RedirectTo(baseGroupLink(id))

Expand Down
Expand Up @@ -47,8 +47,7 @@ import com.normation.rudder.domain.policies.FullRuleTargetInfo
import com.normation.rudder.domain.policies.Rule
import com.normation.rudder.domain.policies.RuleTarget
import com.normation.rudder.domain.workflows.ChangeRequestId
import com.normation.rudder.repository.FullActiveTechniqueCategory
import com.normation.rudder.repository.FullNodeGroupCategory
import com.normation.rudder.repository.{FullActiveTechnique, FullActiveTechniqueCategory, FullNodeGroupCategory}
import com.normation.rudder.web.components.popup.RuleModificationValidationPopup
import com.normation.rudder.web.model.CurrentUser
import com.normation.rudder.web.model.FormTracker
Expand Down Expand Up @@ -103,6 +102,11 @@ object RuleEditForm {
val htmlId_activeTechniquesTree = "directiveTree"
}


// these two case classes are needed to generate the JS for selected directive & target. They need to be top level else lift goes mad.
final case class JsGroup(target: String, link:String, name: String, desc: String)
final case class JsDirective(id: String, link:String, name: String, desc: String, techniqueName: String, techniqueVersion: String, mode: String)

/**
* The form that handles Rule edition
* (not creation)
Expand Down Expand Up @@ -243,17 +247,45 @@ class RuleEditForm(

//is't there an other way to do that? We already have the target/name
//in the tree, so there's just the existing id to find back
val maptarget = groupLib.allTargets.map{
case (gt,fg) => s" ${encJs(gt.target)} : ${encJs(fg.name)}"
}.toList.mkString("{",",","}")
val maptarget = {
// information given to the "selectedDirective" list
import net.liftweb.json._
import net.liftweb.json.Serialization.write
implicit val formats = Serialization.formats(NoTypeHints)
val map = (for {
(gt,fg) <- groupLib.allTargets
} yield {
(gt.target, JsGroup(
gt.target
, linkUtil.targetLink(gt)
, fg.name
, fg.description
))
}).toMap
write(map)
}

val selectedDirectives =
(for {
val selectedDirectives = {
// information given to the "selectedDirective" list
import net.liftweb.json._
import net.liftweb.json.Serialization.write
implicit val formats = Serialization.formats(NoTypeHints)
val map = (for {
id <- selectedDirectiveIds
(_,directive) <- directiveLib.allDirectives.get(id)
(t,d) <- directiveLib.allDirectives.get(id)
} yield {
s" ${encJs(id.value)} : ${encJs(directive.name)}"
}).mkString("{",",","}")
(id.value, JsDirective(
d.id.value
, linkUtil.directiveLink(d.id)
, d.name
, d.shortDescription
, t.techniqueName.value
, d.techniqueVersion.toString
, d.policyMode.map(_.name).getOrElse(globalMode.mode.name)
))
}).toMap
write(map)
}

val includedTarget = ruleTarget.includedTarget.targets
val excludedTarget = ruleTarget.excludedTarget.targets
Expand All @@ -278,7 +310,7 @@ class RuleEditForm(
, usedDirectiveIds = usedDirectiveIds
, onClickCategory = None
, onClickTechnique = None
, onClickDirective = Some((_,_,d) => directiveClick(d))
, onClickDirective = Some((_,t,d) => directiveClick(t, d, globalMode.mode.name))
, addEditLink = true
, included = selectedDirectiveIds
//filter techniques without directives, and categories without technique
Expand Down Expand Up @@ -406,8 +438,16 @@ class RuleEditForm(
JsRaw(s"""onClickTarget("${target}");""")
}

private[this] def directiveClick(directive: Directive) : JsCmd = {
JsRaw(s"""onClickDirective("${directive.id.value}", ${directive.name.encJs});""")
private[this] def directiveClick(t:FullActiveTechnique , d: Directive, gm:String) : JsCmd = {
val dirId = d.id.value
val dirLink = linkUtil.directiveLink(d.id).encJs
val dirName = d.name.encJs
val dirDescription = d.shortDescription.encJs
val dirTechName = t.techniqueName.toString.encJs
val dirTechVersion = d.techniqueVersion.toString.encJs
val dirMode = d.policyMode.map(_.name).getOrElse(gm).encJs

JsRaw(s"""onClickDirective("${dirId}", ${dirName}, ${dirLink}, ${dirDescription}, "${dirTechName}", ${dirTechVersion}, ${dirMode})""")
}

private[this] def includeRuleTarget(targetInfo: FullRuleTargetInfo) : JsCmd = {
Expand Down
Expand Up @@ -4,12 +4,12 @@
*************************************************************************************
*
* This file is part of Rudder.
*
*
* Rudder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* In accordance with the terms of section 7 (7. Additional Terms.) of
* the GNU General Public License version 3, the copyright holders add
* the following Additional permissions:
Expand All @@ -22,12 +22,12 @@
* documentation that, without modification of the Source Code, enables
* supplementary functions or services in addition to those offered by
* the Software.
*
*
* Rudder 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
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with Rudder. If not, see <http://www.gnu.org/licenses/>.
Expand All @@ -45,7 +45,7 @@ groupManagement.controller('GroupCtrl', ['$scope', function($scope) {
};

// Get name of a target (ie the group name) instead of using the target
$scope.getTargetName = function (target) {
$scope.getTarget = function (target) {
return $scope.mapTarget[target];
};

Expand Down Expand Up @@ -145,6 +145,12 @@ groupManagement.controller('GroupCtrl', ['$scope', function($scope) {
element.bsModal(show ? 'show' : 'hide');
};

$scope.getTooltipContent = function(group){
var title = "<h4>"+group.name+"</h4>";
var desc = group.desc != "" ? ("<div>"+group.desc+"</div>") : "<div><i class='empty'>This group has no description.</div></i>";
return title + desc;
}

} ] ) ;

// Add directive to create popup from angular, the directive should shared to future angular component
Expand Down Expand Up @@ -182,4 +188,4 @@ function onClickTarget(target) {
scope.$apply(function(){
scope.toggleTarget(target);
});
};
};
Expand Up @@ -4,12 +4,12 @@
*************************************************************************************
*
* This file is part of Rudder.
*
*
* Rudder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* In accordance with the terms of section 7 (7. Additional Terms.) of
* the GNU General Public License version 3, the copyright holders add
* the following Additional permissions:
Expand All @@ -22,12 +22,12 @@
* documentation that, without modification of the Source Code, enables
* supplementary functions or services in addition to those offered by
* the Software.
*
*
* Rudder 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
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with Rudder. If not, see <http://www.gnu.org/licenses/>.
Expand All @@ -37,35 +37,35 @@

var ruleDirectives = angular.module('ruleDirectives', []);

ruleDirectives.controller('DirectiveCtrl', ['$scope', function($scope) {
ruleDirectives.controller('DirectiveCtrl', ['$scope', '$timeout', function($scope, $timeout) {
$scope.directives = {};
//really, angular...
//a call to sortDirectives is needed.

//really, angular...
//a call to sortDirectives is needed.
//the array here is ONLY used as a cache so
//that angular can know when things don't change.
//else, we get infinite looping....
$scope.sortedDirectives = [];

//needed to correctly display directive by alphaNum
$scope.sortDirectives = function() {
var arr = [];
for (var o in $scope.directives) {
arr.push({"id":o, "name": $scope.directives[o] });
arr.push($scope.directives[o]);
}
var sorted = arr.sort(function(a, b) {
return a.name.localeCompare(b.name);
});

//test for equality... yeah..
//we need that because angularJS must know what is "stable",
//and by default, it uses the object id.
//we need that because angularJS must know what is "stable",
//and by default, it uses the object id.
//So we have to cache the data somewhere and return that cached data
//if nothing changed.
//if nothing changed.
if(sorted.length == $scope.sortedDirectives.length) {
for(var i=0; i<sorted.length; i++) {
if(sorted[i].id != $scope.sortedDirectives[i].id ||
sorted[i].name != $scope.sortedDirectives[i].name
sorted[i].name != $scope.sortedDirectives[i].name
) {
$scope.sortedDirectives = sorted;
return $scope.sortedDirectives;
Expand All @@ -76,14 +76,19 @@ ruleDirectives.controller('DirectiveCtrl', ['$scope', function($scope) {
}
return $scope.sortedDirectives;
}

// Init function so values can be set from outside the scope
// directiveIds is expected to be a json of {directiveId : directiveName }
$scope.init = function ( selectedDirectives ) {
$scope.directives = selectedDirectives;

//init tooltips
$('.icon-info').bsTooltip();
$timeout(function(){
$('.icon-info').bsTooltip();
$('#selectGroups, #selectDirectives').on('hidden.bs.modal', function (e) {
$('.icon-info').bsTooltip();
});
}, 200);
};

// Get name of a directive instead of using the directive ID
Expand All @@ -93,8 +98,8 @@ ruleDirectives.controller('DirectiveCtrl', ['$scope', function($scope) {

$scope.directivesIsEmpty = function() {
return $scope.sortDirectives($scope.directives).length === 0;
}
}

// Update the html field that stocks the directive
$scope.updateDirective = function() {
$('#selectedDirectives').val(JSON.stringify(Object.keys($scope.directives)));
Expand All @@ -108,22 +113,22 @@ ruleDirectives.controller('DirectiveCtrl', ['$scope', function($scope) {
};

// Add the new directive to include, remove it from included directives if it was
$scope.addInclude = function ( directiveId, directiveName ) {
$scope.directives[directiveId] = directiveName;
$("#jsTree-"+directiveId).addClass("included");
$scope.addInclude = function ( directive ) {
$scope.directives[directive.id] = directive;
$("#jsTree-"+directive.id).addClass("included");
$scope.updateDirective();
};

// Toggle a directive =>
// If it was not present => include that directive
// If either from included or excluded => Exclude it
$scope.toggleDirective = function ( directiveId, directiveName ) {
if ( $scope.directives[directiveId] !== undefined ) {
$scope.toggleDirective = function ( directive ) {
if ( $scope.directives[directive.id] !== undefined ) {
// In included directives => remove from included
$scope.removeInclude(directiveId);
$scope.removeInclude(directive.id);
} else {
// Not in directives => include
$scope.addInclude(directiveId, directiveName);
$scope.addInclude(directive);
}
};

Expand All @@ -132,7 +137,12 @@ ruleDirectives.controller('DirectiveCtrl', ['$scope', function($scope) {
element.bsModal(show ? 'show' : 'hide');
};


$scope.getTooltipContent = function(directive){
var title = "<h4>"+directive.name+"</h4>";
var tech = "<div><label>Technique: </label><span>"+directive.techniqueName+"</span><span class='small'>"+directive.techniqueVersion+"</span></div>"
var desc = directive.desc != "" ? "<div>"+directive.desc+"</div>" : "<div><i class='empty'>This directive has no description.</i><div>";
return title + tech + desc;
}
} ] ) ;

// Add directive to create popup from angular, the directive should shared to future angular component
Expand All @@ -148,17 +158,18 @@ ruleDirectives.directive('tooltip', function () {


// Helper function to access from outside angular scope

function includeDirective(directiveId, directiveName) {
var scope = angular.element($("#DirectiveCtrl")).scope();
scope.$apply(function(){
scope.addInclude(directiveId, directiveName);
});
};

function onClickDirective(directiveId, directiveName) {
function onClickDirective(dId, dName, dLink, dDescription, dTechName, dTechVersion, dMode) {
var selectedDir =
{ "id" : dId
, "link" : dLink
, "name" : dName
, "desc" : dDescription
, "techniqueName" : dTechName
, "techniqueVersion" : dTechVersion
, "mode" : dMode
}
var scope = angular.element($("#DirectiveCtrl")).scope();
scope.$apply(function(){
scope.toggleDirective(directiveId, directiveName);
scope.toggleDirective(selectedDir);
});
};
};

0 comments on commit c503ddc

Please sign in to comment.