Skip to content

Commit

Permalink
Merge branch 'branches/rudder/8.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
RaphaelGauthier committed Dec 9, 2024
2 parents 125b888 + f595149 commit d2e0244
Show file tree
Hide file tree
Showing 11 changed files with 455 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -243,15 +243,14 @@ displayNodePropertyRow model =
let
pTitle = case pr of
"inherited" -> "<h4 class='tags-tooltip-title'>Inherited</h4> <div class='tooltip-inner-content'>This property is inherited " ++ (Maybe.withDefault "" p.hierarchy) ++ "</div>."
"overridden" -> "<h4 class='tags-tooltip-title'>Overridden</h4> <div>This property is overridden on this object and was inherited " ++ (Maybe.withDefault "" p.hierarchy) ++ "</div>."
"overridden" -> "<h4 class='tags-tooltip-title'>Overridden</h4> <div class='tooltip-inner-content'>This property is overridden on this object and was inherited " ++ (Maybe.withDefault "" p.hierarchy) ++ "</div>."
_ -> "<h4 class='tags-tooltip-title'>" ++ pr ++ "</h4> <div class='tooltip-inner-content'>This property is managed by its provider ‘<b>" ++ pr ++ "</b>’ and can not be modified manually. Check Rudder’s settings to adjust this provider’s configuration.</div>"
in
(span
[ class "rudder-label label-provider label-sm bs-tooltip"
, attribute "data-bs-toggle" "tooltip"
, attribute "data-bs-placement" "right"
, attribute "data-bs-html" "true"
, attribute "data-bs-container" "body"
, attribute "data-bs-trigger" "click"
, title pTitle
] [ text pr ]
, pr == "overridden" || pr == "inherited"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ update msg model =
let
ui = model.ui
in
({model | ui = { ui | filtersOnProperty = tableFilters}}, Cmd.none)
({model | ui = { ui | filtersOnProperty = tableFilters}}, initTooltips "")

UpdateTableFiltersUsage tableFilters ->
let
Expand All @@ -317,7 +317,7 @@ update msg model =
ui = model.ui
showMore = if List.member id ui.showMore then List.Extra.remove id ui.showMore else id :: ui.showMore
in
({model | ui = { ui | showMore = showMore}}, Cmd.none)
({model | ui = { ui | showMore = showMore}}, initTooltips "")

ClosePopup callback ->
let
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module Nodes.ApiCalls exposing (..)

import Http exposing (..)
import Url.Builder exposing (QueryParameter)

import Nodes.DataTypes exposing (..)
import Nodes.JsonDecoder exposing (..)
import Nodes.JsonEncoder exposing (..)


getUrl: Model -> List String -> List QueryParameter -> String
getUrl m url p=
Url.Builder.relative (m.contextPath :: "secure" :: "api" :: url ) p

getNodes : Model -> Cmd Msg
getNodes model =
let
req =
request
{ method = "GET"
, headers = []
, url = getUrl model [ "nodes" , "details"] []
, body = emptyBody
, expect = expectJson GetNodes decodeGetNodes
, timeout = Nothing
, tracker = Nothing
}
in
req

getNodeDetails : Model -> Cmd Msg
getNodeDetails model =
let
changeAction = "Disable "
req =
request
{ method = "POST"
, headers = []
, url = getUrl model [ "nodes" , "details"] []
, body = encodeDetails model |> jsonBody
, expect = expectJson GetNodes decodeGetNodeDetails
, timeout = Nothing
, tracker = Nothing
}
in
req
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module Nodes.DataTypes exposing (..)

import Http exposing (Error)

import Ui.Datatable exposing (..)
--
-- All our data types
--

type alias NodeId = { value : String }

type alias Node =
{ id : NodeId
, hostname : String
}

type SortBy
= Id
| Hostname

type alias UI =
{ hasReadRights : Bool
, loading : Bool
, filters : TableFilters SortBy
, editColumns : Bool
, columns : List SortBy
}

type alias Model =
{ contextPath : String
, policyMode : String
, nodes : List Node
, ui : UI
}

type Msg
= Ignore
| Copy String
| CallApi (Model -> Cmd Msg)
| GetNodes (Result Error (List Node))
| UpdateUI UI
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module Nodes.Init exposing (..)

import Nodes.DataTypes exposing (..)
import Nodes.ApiCalls exposing (getNodeDetails)


init : { contextPath : String, hasReadRights : Bool, policyMode : String} -> ( Model, Cmd Msg )
init flags =
let
initUi = UI flags.hasReadRights True (TableFilters Hostname Asc "") False [] -- TODO : Get columns list from browser cache
initModel = Model flags.contextPath flags.policyMode [] initUi
in
( initModel
, getNodeDetails initModel
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module Nodes.JsonDecoder exposing (..)

import Json.Decode exposing (..)
import Json.Decode.Pipeline exposing (..)

import Nodes.DataTypes exposing (..)


-- GENERAL
decodeGetNodes =
at [ "data", "nodes" ] (list decodeNode)

decodeGetNodeDetails =
list decodeNode

decodeNode : Decoder Node
decodeNode =
succeed Node
|> required "id" (map NodeId string)
|> required "name" string

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module Nodes.JsonEncoder exposing (..)

import Json.Encode exposing (Value, object, string, list)
import Json.Encode.Extra exposing (maybe)

import Nodes.DataTypes exposing (..)

encodeDetails : Model -> Value
encodeDetails model =
let
data = object
[ ("properties" , list string [] )
, ("software" , list string [] )
]
in
data
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
module Nodes.View exposing (..)

import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick, onInput)

import Nodes.DataTypes exposing (..)
import Nodes.ViewUtils exposing (..)
import Nodes.ApiCalls exposing (getNodeDetails)

import Ui.Datatable exposing (generateLoadingTable)

view : Model -> Html Msg
view model =
if model.ui.hasReadRights then
let
nodes = model.nodes
ui = model.ui
filters = ui.filters

editColumnsBtn =
if ui.editColumns then
button [class "btn btn-success btn-sm btn-icon", style "min-width" "120px", onClick (UpdateUI {ui | editColumns = False})]
[ text "Confirm"
, i [class "fa fa-check"][]
]
else
button [class "btn btn-default btn-sm btn-icon", style "min-width" "120px", onClick (UpdateUI {ui | editColumns = True})]
[ text "Edit columns"
, i [class "fa fa-pencil"][]
]

displayColumnsEdit =
if ui.editColumns then
let
colOptions = allColumns
|> List.filter (\c -> not (List.member c ui.columns))
|> List.map (\c -> option[value (getColumnTitle c)][text (getColumnTitle c)])
in
div[class "more-filters edit-columns"]
[ select[](colOptions)
]
else
text ""
in
div [class "rudder-template"]
[ div [class "one-col"]
[ div [class "main-header"]
[ div [class "header-title"]
[ h1[][ span[][text "Nodes"] ]
]
]
, div [class "one-col-main"]
[ div [class "template-main"]
[ if model.ui.loading then
generateLoadingTable False 5
else
div [class "main-table tab-table-content col-sm-12"]
[ div [class "table-header extra-filters"]
[ div [class "main-filters"]
[ input [type_ "text", placeholder "Filter", class "input-sm form-control", onInput (\s -> UpdateUI {ui | filters = {filters | filter = s}})][]
, editColumnsBtn
, button [class "btn btn-default btn-sm btn-refresh", onClick (CallApi getNodeDetails)][i [class "fa fa-refresh"][]]
]
, displayColumnsEdit
]
, div [class "table-container"]
[ table [ class "no-footer dataTable"]
[ thead [] [nodesTableHeader model.ui]
, tbody [] (buildNodesTable model)
]
]
]
]
]
]
]
else
text "No rights"
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
module Nodes.ViewUtils exposing (..)

import Html exposing (..)
import Html.Attributes exposing (class, href, attribute, title, style, colspan, rowspan )
import Html.Events exposing (onClick, onInput)
import Json.Decode exposing (decodeValue)
import NaturalOrdering as N exposing (compare)

import Nodes.DataTypes exposing (..)
import Ui.Datatable exposing (..)


getSortFunction : Model -> Node -> Node -> Order
getSortFunction model n1 n2 =
let
order = case model.ui.filters.sortBy of
Id -> N.compare n1.id.value n2.id.value
Hostname -> N.compare n1.hostname n2.hostname
_ -> N.compare n1.hostname n2.hostname
-- TODO : Add all cases
in
if model.ui.filters.sortOrder == Asc then
order
else
case order of
LT -> GT
EQ -> EQ
GT -> LT

searchField : Node -> List String
searchField node =
[ node.id.value
, node.hostname
]

buildNodesTable : Model -> List (Html Msg)
buildNodesTable model =
let
nodes = model.nodes
sortedNodesList = nodes
|> List.filter (\n -> filterSearch model.ui.filters.filter (searchField n))
|> List.sortWith (getSortFunction model)

rowTable : Node -> Html Msg
rowTable n =
let
test = ""
in
tr[]
[ td[][ text n.hostname ]
, td[][ text n.id.value ]
]
in
if List.length sortedNodesList > 0 then
List.map rowTable sortedNodesList
else
[ tr[][td [class "empty", colspan 5][i [class "fa fa-exclamation-triangle"][], text "No nodes match your filters."]]]

nodesTableHeader : UI -> Html Msg
nodesTableHeader ui =
let
filters = ui.filters
in
tr [class "head"]
[ th [ class (thClass filters Hostname) , rowspan 1, colspan 1
, onClick (UpdateUI {ui | filters = (sortTable filters Hostname)})
] [ text "Hostname" ]
, th [ class (thClass filters Id) , rowspan 1, colspan 1
, onClick (UpdateUI {ui | filters = (sortTable filters Id)})
] [ text "Id" ]
]

allColumns : List SortBy
allColumns =
[ Hostname
, Id
, PolicyServer
, Ram
, AgentVersion
, Software ""
, NodeProperty "" False
, PolicyMode
, IpAddresses
, MachineType
, Kernel
, Os
, NodeCompliance
, LastRun
, InventoryDate
]

defaultColumns : List SortBy
defaultColumns =
[ Hostname
, PolicyMode
, Os
, NodeCompliance
]

getColumnTitle : SortBy -> String
getColumnTitle col =
case col of
Hostname -> "Hostname"
Id -> "Node ID"
PolicyServer -> "Policy server"
Ram -> "RAM"
AgentVersion -> "Agent version"
Software _ -> "Software"
NodeProperty _ _ -> "Property"
PolicyMode -> "Policy mode"
IpAddresses -> "IP addresses"
MachineType -> "Machine type"
Kernel -> "Kernel"
Os -> "OS"
NodeCompliance -> "Compliance"
LastRun -> "Last run"
InventoryDate -> "Inventory date"
Loading

0 comments on commit d2e0244

Please sign in to comment.