Skip to content

Commit

Permalink
Fixes #24637: Improvements on score: F score, rework tooltip, improve…
Browse files Browse the repository at this point in the history
… messages
  • Loading branch information
VinceMacBuche authored and fanf committed Apr 2, 2024
1 parent 125c328 commit fd2422c
Show file tree
Hide file tree
Showing 13 changed files with 83 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ CREATE TABLE NodeFacts (
);


CREATE TYPE score AS enum ('A', 'B', 'C', 'D', 'E');
CREATE TYPE score AS enum ('A', 'B', 'C', 'D', 'E', 'F', 'X');

Create table GlobalScore (
nodeId text primary key
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import com.normation.rudder.score.ScoreValue.B
import com.normation.rudder.score.ScoreValue.C
import com.normation.rudder.score.ScoreValue.D
import com.normation.rudder.score.ScoreValue.E
import com.normation.rudder.score.ScoreValue.F
import zio.*
import zio.json.*
import zio.syntax.*
Expand All @@ -64,17 +65,19 @@ object ComplianceScoreEventHandler extends ScoreEventHandler {
p <- ComplianceSerializable.fromPercent(percent).toJsonAST
} yield {
import ComplianceScore.scoreId
val score = if (percent.compliance >= 100) {
Score(scoreId, A, "Node is compliant at 100%", p)
} else if (percent.compliance >= 75) {
Score(scoreId, B, "Node is compliant at least at 75%", p)
val score = if (percent.compliance >= 95) {
Score(scoreId, A, "Compliance is over 95%", p)
} else if (percent.compliance >= 80) {
Score(scoreId, B, "Compliance is between 80% and 95%", p)
} else if (percent.compliance >= 50) {
ComplianceSerializable.fromPercent(percent)
Score(scoreId, C, "Node is compliant at least at 50%", p)
Score(scoreId, C, "Compliance is between 50% and 80%", p)
} else if (percent.compliance >= 20) {
Score(scoreId, D, "Compliance is between 20% and 50%", p)
} else if (percent.compliance >= 25) {
Score(scoreId, D, "Node is compliant at least at 25%", p)
Score(scoreId, E, "Compliance is between 5% and 20%", p)
} else {
Score(scoreId, E, "Node is compliant at less than 25%", p)
Score(scoreId, F, "Compliance is lower then 5%", p)
}
((n, score :: Nil) :: Nil)
}) match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ object ScoreValue extends Enum[ScoreValue] {
case object C extends ScoreValue { val value = "C" }
case object D extends ScoreValue { val value = "D" }
case object E extends ScoreValue { val value = "E" }
case object F extends ScoreValue { val value = "F" }
case object NoScore extends ScoreValue { val value = "X" }

val values: IndexedSeq[ScoreValue] = findValues
Expand All @@ -80,14 +81,18 @@ object GlobalScoreService {
NoDetailsScore(newScore.scoreId, newScore.value, newScore.message) :: acc.filterNot(_.scoreId == newScore.scoreId)
}
import ScoreValue.*
val score = if (correctScores.exists(_.value == E)) { E }
val score = if (correctScores.exists(_.value == F)) { F }
else if (correctScores.exists(_.value == E)) { E }
else if (correctScores.exists(_.value == D)) { D }
else if (correctScores.exists(_.value == C)) {
C
} else if (correctScores.exists(_.value == B)) {
B
} else A
GlobalScore(score, s"There is at least a Score with ${score.value}", correctScores)
else if (correctScores.exists(_.value == C)) { C }
else if (correctScores.exists(_.value == B)) { B }
else A

if (correctScores.isEmpty) {
GlobalScore(NoScore, "No Score defined for this node", correctScores)
} else {
GlobalScore(score, s"Worst score for this node is ${score.value}", correctScores)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
*
* 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 @@ -50,6 +50,7 @@ import com.normation.rudder.score.ScoreValue.B
import com.normation.rudder.score.ScoreValue.C
import com.normation.rudder.score.ScoreValue.D
import com.normation.rudder.score.ScoreValue.E
import com.normation.rudder.score.ScoreValue.F
import zio.*
import zio.json.*
import zio.syntax.*
Expand Down Expand Up @@ -97,15 +98,29 @@ class SystemUpdateScoreHandler(nodeFactRepository: NodeFactRepository) extends S
} yield {
import SystemUpdateScore.scoreId
val score = if (security == 0 && sum < 50) {
Score(scoreId, A, "Node has no security updates and less than 50 updates available", stats)
} else if (security < 5) {
Score(scoreId, B, s"Node has ${security} security updates available (less than 5)", stats)
} else if (security < 20) {
Score(scoreId, C, s"Node has ${security} security updates available (less than 20)", stats)
} else if (security < 50) {
Score(scoreId, D, s"Node has ${security} security updates available (less than 50)", stats)
val securityMessage = "No security update."
val updateMessage = s"${sum} updates available (less than 50)."
Score(scoreId, A, s"${securityMessage}\n${updateMessage}", stats)
} else if (security < 5 && sum < 75) {
val securityMessage = if (security < 5) s"${security} security updates available (less than 5)." else ""
val updateMessage = if (sum < 75) s"${sum} updates available (between 50 and 75)." else ""
Score(scoreId, B, s"${securityMessage}\n${updateMessage}", stats)
} else if (security < 20 && sum < 125) {
val securityMessage = if (security < 20) s"${security} security updates available (between 5 and 20)." else ""
val updateMessage = if (sum < 125) s"${sum} updates available (between 75 and 125)." else ""
Score(scoreId, C, s"${securityMessage}\n${updateMessage}", stats)
} else if (security < 50 && sum < 175) {
val securityMessage = if (security < 50) s"${security} security updates available (between 20 and 50)." else ""
val updateMessage = if (sum < 175) s"${sum} updates available (between 125 and 175)." else ""
Score(scoreId, D, s"${securityMessage}\n${updateMessage}", stats)
} else if (security < 80 && sum < 250) {
val securityMessage = if (security < 80) s"${security} security updates available (between 50 and 80)." else ""
val updateMessage = if (sum < 250) s"${sum} updates available (between 175 and 250)." else ""
Score(scoreId, E, s"${securityMessage}\n${updateMessage}", stats)
} else {
Score(scoreId, E, s"Node has ${security} security updates available (more than 50)", stats)
val securityMessage = if (security >= 80) s"${security} security updates available (more than 80)." else ""
val updateMessage = if (sum >= 250) s"${sum} updates available (More than 250)." else ""
Score(scoreId, F, s"${securityMessage}\n${updateMessage}", stats)
}
((n, score :: Nil) :: Nil)
}) match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ object AuthorizationApiMapping {
NodeApi.ListAcceptedNodes.x :: NodeApi.ListPendingNodes.x :: NodeApi.NodeDetails.x ::
NodeApi.NodeInheritedProperties.x :: NodeApi.NodeDisplayInheritedProperties.x :: NodeApi.NodeDetailsTable.x ::
NodeApi.PendingNodeDetails.x :: NodeApi.NodeDetailsSoftware.x :: NodeApi.NodeDetailsProperty.x ::
NodeApi.GetNodesStatus.x :: InventoryApi.QueueInformation.x ::
NodeApi.NodeGlobalScore.x :: NodeApi.NodeScoreDetail.x :: NodeApi.NodeScoreDetails.x ::
NodeApi.GetNodesStatus.x ::
// score about node
NodeApi.NodeGlobalScore.x :: NodeApi.NodeScoreDetails.x :: NodeApi.NodeScoreDetail.x ::
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
*************************************************************************************
* Copyright 2017 Normation SAS
*************************************************************************************
*
* This file is part of Rudder.
*
* Rudder is free software: you can redistribute it and/or modify
Expand Down Expand Up @@ -30,7 +30,7 @@
*
* You should have received a copy of the GNU General Public License
* along with Rudder. If not, see <http://www.gnu.org/licenses/>.
*
*
*************************************************************************************
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ buildTooltipContent : String -> String -> String
buildTooltipContent title content =
let
headingTag = "<h4 class='tags-tooltip-title'>"
contentTag = "</h4><div class='tooltip-inner-content'>"
closeTag = "</div>"
contentTag = "</h4><div class='tooltip-inner-content'><pre>"
closeTag = "</pre></div>"
in
headingTag ++ title ++ contentTag ++ content ++ closeTag
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ update msg model =
)
Err err ->
processApiError "Getting global score" err model
ShowScoreMessage optScore ->
( {model | scoreToShow = optScore} , Cmd.none )
GetScoreInfo res ->
case res of
Ok scoreInfo ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ type alias Model =
, score : Maybe GlobalScore
, contextPath : String
, scoreInfo : List ScoreInfo
, scoreToShow : Maybe String
}

type Msg = GetScore (Result Error GlobalScore) | GetScoreInfo (Result Error (List ScoreInfo))
type Msg = GetScore (Result Error GlobalScore) | GetScoreInfo (Result Error (List ScoreInfo)) | ShowScoreMessage (Maybe String)
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ subscriptions _ = Sub.none
init : { id : String, contextPath : String } -> ( Model, Cmd Msg )
init flags =
let
initModel = Model (NodeId flags.id) Nothing flags.contextPath []
initModel = Model (NodeId flags.id) Nothing flags.contextPath [] Nothing

action = Cmd.batch [ getScore initModel, getScoreInfo initModel ]
in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,47 @@ module Score.View exposing (..)

import Html exposing (..)
import Html.Attributes exposing (..)
import List.Extra
import Markdown

import Score.DataTypes exposing (..)
import Score.ViewUtils exposing (..)
import String.Extra

view : Model -> Html Msg
view model =
div[ class "compliance-score d-flex flex-column mb-4" ]
[ div[class "global-score d-flex"]
( case model.score of
Just complianceScore ->
let

(message,name) = case model.scoreToShow of
Nothing -> (complianceScore.message, "Global")
Just scoreId ->
let
msg = complianceScore.details |> List.Extra.find (.scoreId >> (==) scoreId) |> Maybe.map .message |> Maybe.withDefault complianceScore.message
n = List.Extra.find (.id >> (==) scoreId) model.scoreInfo |> Maybe.map .name |> Maybe.withDefault (String.Extra.humanize scoreId)
in
(msg,n)
in
[ div[class "score-badge"]
[ getScoreBadge complianceScore.value [] False
[ getScoreBadge Nothing complianceScore.value False
]
, div[class "score-breakdown ps-5 flex-grow-1 flex-column"]
[ h3[][text "Score breakdown"]
, div[class "d-flex"](scoreBreakdownList complianceScore.details model.scoreInfo)
]
, div[class "score-explanation ps-3 flex-grow-1"]
( Markdown.toHtml Nothing complianceScore.message )
(( h3 [] [text name ] ) ::
( Markdown.toHtml Nothing message ))
]
Nothing ->
let
noComplianceMsg = "There is no score for this node"
in
[ div[class "score-badge sm "]
[ getScoreBadge X [] False
[ getScoreBadge Nothing X False
]
, div[class "no-compliance d-flex flex-grow-1 align-items-center ps-4"]
[ i[class "fa fa-warning"][]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module Score.ViewUtils exposing (..)

import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onMouseLeave, onMouseOver)
import List
import List.Extra
import String.Extra
Expand All @@ -20,20 +21,13 @@ scoreLabel score =
F -> "F"
X -> "X"

buildTooltipBadge : String -> String -> List (Attribute msg)
buildTooltipBadge name msg =
[ attribute "data-bs-toggle" "tooltip"
, attribute "data-bs-placement" "top"
, title (buildTooltipContent (String.Extra.humanize name) msg)
]

getScoreBadge : ScoreValue -> List (Attribute Msg) -> Bool -> Html Msg
getScoreBadge score tooltipAttributes smallSize =

getScoreBadge : Maybe String -> ScoreValue -> Bool -> Html Msg
getScoreBadge id score smallSize =
span
( List.append
[ class ("badge-compliance-score " ++ (scoreLabel score) ++ (if smallSize then " sm" else ""))]
tooltipAttributes
)[]
[ onMouseOver (ShowScoreMessage id), onMouseLeave (ShowScoreMessage Nothing), class ("badge-compliance-score " ++ (scoreLabel score) ++ (if smallSize then " sm" else ""))]
[]

scoreBreakdownList : List Score -> List ScoreInfo -> List (Html Msg)
scoreBreakdownList scoreDetails scoreInfo = scoreDetails
Expand All @@ -42,7 +36,7 @@ scoreBreakdownList scoreDetails scoreInfo = scoreDetails
name = List.Extra.find (.id >> (==) sD.scoreId) scoreInfo |> Maybe.map .name |> Maybe.withDefault (String.Extra.humanize sD.scoreId)
in
div[class "d-flex flex-column pe-5 align-items-center"]
[ getScoreBadge sD.value (buildTooltipBadge sD.scoreId sD.message) True
[ getScoreBadge (Just sD.scoreId) sD.value True
, label[class "text-center pt-2"][text name ]
]
)
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class CheckTableScore(
def createScoreTables: IOResult[Unit] = {

val checkType = sql"SELECT 1 FROM pg_type WHERE typname = 'score'"
val sqlType = sql"""CREATE TYPE score AS enum ('A', 'B', 'C', 'D', 'E')"""
val sqlType = sql"""CREATE TYPE score AS enum ('A', 'B', 'C', 'D', 'E', 'F', 'X')"""
val sql1 = sql"""CREATE TABLE IF NOT EXISTS GlobalScore (
nodeId text primary key
, score score NOT NULL
Expand Down

0 comments on commit fd2422c

Please sign in to comment.