10 changed files with 6621 additions and 5 deletions
@ -1,4 +1,5 @@
|
||||
ssg/dist-newstyle |
||||
src/_cache |
||||
src/_site |
||||
src/elm-stuff |
||||
result |
||||
|
@ -0,0 +1,99 @@
|
||||
|
||||
module ServicesTable exposing (main) |
||||
|
||||
import List |
||||
import Browser |
||||
import Html exposing (Html, div, span, text, table, thead, tbody, tr, th, td) |
||||
import Html.Attributes exposing (class) |
||||
import Http |
||||
import Dict exposing (Dict) |
||||
import Json.Decode exposing (Decoder, map, map3, field, list, string, dict, keyValuePairs) |
||||
|
||||
type alias ServiceInfo = |
||||
{ fields : List String |
||||
, tests : List String |
||||
, mod : String } |
||||
|
||||
type alias Info = List |
||||
{ name : String |
||||
, fields : List String |
||||
, tests : List String |
||||
, mod : String } |
||||
|
||||
type Model |
||||
= Failure |
||||
| Loading |
||||
| Success Info |
||||
|
||||
type Msg = GotInfo (Result Http.Error Info) |
||||
|
||||
main = Browser.element |
||||
{ init = init |
||||
, update = update |
||||
, subscriptions = subscriptions |
||||
, view = view } |
||||
|
||||
init : () -> (Model, Cmd Msg) |
||||
init _ = |
||||
( Loading |
||||
, Http.get |
||||
{ url = "https://share.recursor.wf/systemd-services-tests.json" |
||||
, expect = Http.expectJson GotInfo dataDecoder } ) |
||||
|
||||
dataDecoder : Decoder Info |
||||
dataDecoder = map (List.map (\(name, (fields, tests, mod)) -> { name = name, fields = fields, tests = tests, mod = mod })) |
||||
<| keyValuePairs (map3 (\x y z -> (x, y, z)) (field "fields" <| list string) (field "tests" <| list string) (field "module" string)) |
||||
|
||||
update : Msg -> Model -> (Model, Cmd Msg) |
||||
update msg model = |
||||
case msg of |
||||
GotInfo result -> |
||||
case result of |
||||
Ok info -> (Success info, Cmd.none) |
||||
Err _ -> (Failure, Cmd.none) |
||||
|
||||
subscriptions : Model -> Sub Msg |
||||
subscriptions model = Sub.none |
||||
|
||||
-- Render |
||||
|
||||
watchedFields = |
||||
[ "PrivateDevices" |
||||
, "PrivateMounts" |
||||
, "PrivateNetwork" |
||||
, "PrivateTmp" |
||||
, "PrivateUsers" |
||||
, "ProtectControlGroups" |
||||
, "ProtectKernelModules" |
||||
, "ProtectKernelTunables" |
||||
, "ProtectKernelLogs" |
||||
, "ProtectClock" |
||||
, "ProtectHostname" |
||||
, "LockPersonality" |
||||
, "MemoryDenyWriteExecute" |
||||
, "NoNewPrivileges" |
||||
, "RestrictRealtime" |
||||
, "RestrictSUIDSGID" ] |
||||
|
||||
view : Model -> Html Msg |
||||
view model = case model of |
||||
Failure -> text "Unable to load data." |
||||
Loading -> text "Loading..." |
||||
Success info -> renderTable info |
||||
|
||||
headers : Html Msg |
||||
headers = tr [] |
||||
<| [ th [] [ text "source" ], th [] [ text "module" ] ] |
||||
++ List.map (\name -> th [ class "rotate-45" ] [ div [] [ span [] [ text name ] ] ]) watchedFields |
||||
|
||||
renderTable : Info -> Html Msg |
||||
renderTable info = table [ class "services-table", class "table-header-rotated" ] |
||||
[ thead [ class "info-thead" ] [ headers ] |
||||
, tbody [] (List.map renderLine info) ] |
||||
|
||||
renderLine : { name : String, fields : List String, tests : List String, mod : String } -> Html Msg |
||||
renderLine {name, fields, tests, mod} = tr [] |
||||
<| [ th [] [ text mod ], th [] [ text name ] ] |
||||
++ (List.map (\b -> td [class (if b then "cell-good" else "cell-bad")] [text (if b then "✓" else "✗")]) |
||||
<| List.map (\field -> not <| List.member field fields) watchedFields) |
||||
|
@ -0,0 +1,27 @@
|
||||
{ |
||||
"type": "application", |
||||
"source-directories": [ |
||||
"./" |
||||
], |
||||
"elm-version": "0.19.1", |
||||
"dependencies": { |
||||
"direct": { |
||||
"elm/browser": "1.0.2", |
||||
"elm/core": "1.0.5", |
||||
"elm/html": "1.0.0", |
||||
"elm/http": "2.0.0", |
||||
"elm/json": "1.1.3" |
||||
}, |
||||
"indirect": { |
||||
"elm/bytes": "1.0.8", |
||||
"elm/file": "1.0.5", |
||||
"elm/time": "1.0.0", |
||||
"elm/url": "1.0.0", |
||||
"elm/virtual-dom": "1.0.3" |
||||
} |
||||
}, |
||||
"test-dependencies": { |
||||
"direct": {}, |
||||
"indirect": {} |
||||
} |
||||
} |
@ -0,0 +1,94 @@
|
||||
<!DOCTYPE html> |
||||
<html> |
||||
<head> |
||||
<meta charset="utf-8"> |
||||
<title>Packages info</title> |
||||
</head> |
||||
<body> |
||||
<div id="app"></div> |
||||
</body> |
||||
<style> |
||||
.info-thead { |
||||
position: sticky; |
||||
top: 0; |
||||
} |
||||
.cell-good { |
||||
color: green; |
||||
} |
||||
.cell-bad { |
||||
color: red; |
||||
} |
||||
.services-table { |
||||
white-space: nowrap; |
||||
} |
||||
.services-table thead { |
||||
background-color: white; |
||||
} |
||||
.services-table thead th { |
||||
vertical-align: bottom; |
||||
} |
||||
.services-table td { |
||||
text-align: center; |
||||
} |
||||
.services-table tbody th { |
||||
text-align: left; |
||||
} |
||||
|
||||
/* Rotated table headers, borrowed from http://jimmybonney.com/articles/column_header_rotation_css */ |
||||
/* Adapted by me, without a calculator */ |
||||
|
||||
.tab-content { |
||||
margin-right: 5em; |
||||
overflow: visible; |
||||
} |
||||
|
||||
td.centered { |
||||
text-align: center; |
||||
} |
||||
|
||||
.table-header-rotated th.rotate-45 { |
||||
height: 200px; |
||||
width: 40px; |
||||
min-width: 40px; |
||||
max-width: 40px; |
||||
position: relative; |
||||
vertical-align: bottom; |
||||
padding: 0; |
||||
font-size: 100%; |
||||
line-height: 0.9; |
||||
} |
||||
|
||||
.table-header-rotated th.rotate-45 > div { |
||||
position: relative; |
||||
top: 0px; |
||||
left: 100px; |
||||
height: 100%; |
||||
-ms-transform:skew(-45deg,0deg); |
||||
-moz-transform:skew(-45deg,0deg); |
||||
-webkit-transform:skew(-45deg,0deg); |
||||
-o-transform:skew(-45deg,0deg); |
||||
transform:skew(-45deg,0deg); |
||||
overflow: hidden; |
||||
border-left: 1px solid #dddddd; |
||||
z-index: 1; |
||||
} |
||||
|
||||
.table-header-rotated th.rotate-45 span { |
||||
-ms-transform:skew(45deg,0deg) rotate(315deg); |
||||
-moz-transform:skew(45deg,0deg) rotate(315deg); |
||||
-webkit-transform:skew(45deg,0deg) rotate(315deg); |
||||
-o-transform:skew(45deg,0deg) rotate(315deg); |
||||
transform:skew(45deg,0deg) rotate(315deg); |
||||
position: absolute; |
||||
bottom: 85px; left: -107px; display: inline-block; |
||||
width: 254px; text-align: left; |
||||
} |
||||
|
||||
</style> |
||||
<script src="/ServicesTable.js"></script> |
||||
<script> |
||||
Elm.ServicesTable.init({ |
||||
node: document.getElementById("app"), |
||||
}); |
||||
</script> |
||||
</html> |
@ -1,11 +1,11 @@
|
||||
{ mkDerivation, base, hakyll, lib, pandoc }: |
||||
{ mkDerivation, base, hakyll, hakyll-process, lib, pandoc }: |
||||
mkDerivation { |
||||
pname = "ssg"; |
||||
version = "0.1.0.0"; |
||||
src = ./.; |
||||
isLibrary = false; |
||||
isExecutable = true; |
||||
executableHaskellDepends = [ base hakyll pandoc ]; |
||||
executableHaskellDepends = [ base hakyll hakyll-process pandoc ]; |
||||
license = "unknown"; |
||||
hydraPlatforms = lib.platforms.none; |
||||
} |
||||
|
Loading…
Reference in new issue