construct table structure for html
import Html as H
import Html.Attributes as A
config =
{ attr =
{ table = \data ->
[ [ "div-auto-size: none"
, "rows: " ++ (data.thead |> String.fromInt)
]
|> String.join "; "
|> A.attribute "_fixedhead"
]
, summary = [ "border-top-single" |> A.class ]
, border = \(left,right) ->
[ case left of
Table.None -> []
Table.Single -> ["border-left"]
Table.Double -> ["border-left-double"]
, case right of
Table.None -> []
Table.Single -> ["border-right"]
Table.Double -> ["border-right-double"]
]
|> List.concat |> List.map A.class
}
, emptyContent = Table.td []
[ H.p [ "alert" |> A.class ]
[ "empty!" |> H.text ]
]
}
data =
{ sum = 18
, roleLength = 2
, genders =
[ { value = "male"
, sum = 2
}
, { value = "female"
, sum = 3
}
, { value = "other"
, sum = 1
}
]
}
rows =
[ { id = 2
, name = "John"
, gender = "male"
, roles = [ "admin" ]
, comments =
[ { user = "guest"
, text = "looks goot to me"
, likes =
[ { user = "master"
, text = "looks great to me!"
}
]
}
]
}
]
rows |> Table.render config
[ Table.column ( Table.none, Table.none )
{ header = Table.th [] [ "id" |> H.text ]
, summary = Table.empty
, content = \row -> Table.td [ "is-center" |> A.class ]
[ H.p [] [ row.id |> String.fromInt |> H.text ] ]
}
, Table.group ( Table.th [ "is-center" |> A.class ] [ "info" |> H.text ] )
[ Table.column ( Table.none, Table.none )
{ header = Table.th [] [ "name" |> H.text ]
, summary = Table.th [ "is-right" |> A.class ] [ "sum" |> H.text ]
, content = \row -> Table.td []
[ H.p [] [ row.name |> H.text ] ]
}
, Table.column ( Table.none, Table.single )
{ header = Table.th [] [ "gender" |> H.text ]
, summary = Table.td [] [ H.p [] [ data.sum |> String.fromInt |> H.text ] ]
, content = \row -> Table.td []
[ H.p [] [ row.gender |> H.text ] ]
}
, Table.union ( Table.none, Table.none )
{ header = Table.th [] [ "roles" |> H.text ]
, summary = Table.empty
, colspan = data.roleLength
, data = \row -> row.roles |> List.map (\role -> ( row, role ))
, content = \(row,role) -> Table.td []
[ H.p [] [ role |> H.text ] ]
}
, Table.parts data.genders
(\gender ->
[ Table.column ( Table.none, Table.none )
{ header = Table.th [] [ gender.value |> H.text ]
, summary = Table.td [ "is-center" |> A.class ]
[ H.p [] [ gender.sum |> String.fromInt |> H.text ] ]
, content = \row -> Table.td [ "is-center" |> A.class ]
[ H.p []
[ if row.gender == gender.value
then "v" |> H.text
else "" |> H.text
]
]
}
, Table.column ( Table.none, Table.none )
{ header = Table.th [] [ gender.value |> H.text ]
, summary = Table.td [ "is-center" |> A.class ]
[ H.p [] [ gender.sum |> String.fromInt |> H.text ] ]
, content = \row -> Table.td [ "is-center" |> A.class ]
[ H.p []
[ if row.gender /= gender.value
then "o" |> H.text
else "" |> H.text
]
]
}
]
)
, Table.rows ( \row -> row.roles |> List.map (\role -> ( row, role )) )
[ Table.column ( Table.none, Table.none )
{ header = Table.th [] [ "roles" |> H.text ]
, summary = Table.empty
, content = \(row,role) -> Table.td []
[ H.p [] [ role |> H.text ] ]
}
, Table.column ( Table.none, Table.none )
{ header = Table.th [] [ "roles" |> H.text ]
, summary = Table.empty
, content = \(row,role) -> Table.td []
[ H.p [] [ role |> H.text ] ]
}
]
, Table.group ( Table.th [ "is-center" |> A.class ] [ "comment" |> H.text ] )
[ Table.rows ( \row -> row.comments |> List.map (\comment -> ( row, comment )) )
[ Table.column ( Table.single, Table.none )
{ header = Table.th [] [ "user" |> H.text ]
, summary = Table.empty
, content = \(row,comment) -> Table.td []
[ H.p [] [ comment.user |> H.text ] ]
}
, Table.column ( Table.none, Table.none )
{ header = Table.th [] [ "text" |> H.text ]
, summary = Table.empty
, content = \(row,comment) -> Table.td []
[ H.p [] [ comment.text |> H.text ] ]
}
, Table.group ( Table.th [ "is-center" |> A.class ] [ "like" |> H.text ] )
[ Table.rows
( \(row,comment) -> comment.likes |> List.map (\like -> ( row, comment, like )) )
[ Table.column ( Table.single, Table.none )
{ header = Table.th [] [ "user" |> H.text ]
, summary = Table.empty
, content = \(row,comment,like) -> Table.td []
[ H.p [] [ like.user |> H.text ] ]
}
, Table.column ( Table.none, Table.none )
{ header = Table.th [] [ "text" |> H.text ]
, summary = Table.empty
, content = \(row,comment,like) -> Table.td []
[ H.p [] [ like.text |> H.text ] ]
}
]
]
]
]
]
]
{ attr : { table : { thead : Basics.Int } -> List (Html.Attribute msg)
, summary : List (Html.Attribute msg)
, border : BorderAttribute msg }
, emptyContent : Struct.Cell (Cell msg)
}
configuration for rendering
{ attr =
-- attribute of <table> tag
{ table = \data ->
[ [ "div-auto-size: none"
, "rows: " ++ (data.thead |> String.fromInt)
]
|> String.join "; "
|> A.attribute "_fixedhead"
]
-- attribute of summary <tr> tag
, summary = [ "border-top-single" |> A.class ]
-- border attribute of <td> or <th> tag
, border = \(left,right) ->
[ case left of
Table.None -> []
Table.Single -> ["border-left"]
Table.Double -> ["border-left-double"]
, case right of
Table.None -> []
Table.Single -> ["border-right"]
Table.Double -> ["border-right-double"]
]
|> List.concat |> List.map A.class
}
-- <td> content when empty rows
, emptyContent = Table.td []
[ H.p [ "alert" |> A.class ]
[ "empty!" |> H.text ]
]
}
Struct.Border
left border and right border
( BorderStyle, BorderStyle ) -- left, right
border style
Struct.Column row (Cell msg)
column definition
Struct.ColumnModel row (Cell msg)
config for column
{ header : Cell msg -- header cell
, summary : Cell msg -- summary cell
, content : row -> Cell msg -- content cell
}
Struct.UnionModel row data (Cell msg)
config for union
{ header : Cell msg -- header cell
, summary : Cell msg -- summary cell
, colspan : Int -- colspan
, data : row -> List data -- list of sub data
, content : data -> Cell msg -- content cell
}
render : Config msg -> List (Column row msg) -> List row -> Html msg
render html by Config, Columns, data
column : Border -> ColumnModel row msg -> Column row msg
define column
Table.column
( Table.none, Table.none ) -- border ( left, right )
{ header =
Table.th [] [ "id" |> H.text ] -- header cell
, summary = Table.empty -- summary cell
, content = -- content cell
\row ->
Table.td [ "is-center" |> A.class ]
[ H.p [] [ row.id |> String.fromInt |> H.text ] ]
}
group : Struct.Cell (Cell msg) -> List (Column row msg) -> Column row msg
define group
Table.group
( Table.th [ "is-center" |> A.class ] -- header cell
[ "info" |> H.text ]
)
[ Table.column -- group columns
( Table.none, Table.none )
{ header = Table.th [] [ "name" |> H.text ]
, summary = Table.th [ "is-right" |> A.class ] [ "sum" |> H.text ]
, content = \row -> Table.td []
[ H.p [] [ row.name |> H.text ] ]
}
]
union : Border -> UnionModel row data msg -> Column row msg
define union
Table.union
( Table.none, Table.none ) -- border ( left, right )
{ header =
Table.th [] [ "roles" |> H.text ] -- header cell
, summary = Table.empty -- summary cell
, colspan = data.roleLength -- colspan
, data = -- list of sub data
\row -> row.roles |> List.map (\role -> ( row, role ))
, content = -- content cell
\(row,role) ->
Table.td []
[ H.p [] [ role |> H.text ] ]
}
parts : List data -> (data -> List (Column row msg)) -> Column row msg
define parts
Table.parts
data.genders -- list of sub data
(\gender -> -- sub data columns
[ Table.column ( Table.none, Table.none )
{ header = Table.th [] [ gender.value |> H.text ]
, summary = Table.td [ "is-center" |> A.class ]
[ H.p [] [ gender.sum |> String.fromInt |> H.text ] ]
, content = \row -> Table.td [ "is-center" |> A.class ]
[ H.p []
[ if row.gender == gender.value
then "v" |> H.text
else "" |> H.text
]
]
}
]
)
rows : (row -> List data) -> List (Column data msg) -> Column row msg
define rows
Table.rows
( \row -> -- list of sub data
row.roles |> List.map (\role -> ( row, role ))
)
[ Table.column -- sub data columns
( Table.none, Table.none )
{ header = Table.th [] [ "roles" |> H.text ]
, summary = Table.empty
, content = \(row,role) -> Table.td []
[ H.p [] [ role |> H.text ] ]
}
]
none : Struct.BorderStyle
border style None
single : Struct.BorderStyle
border style Single
double : Struct.BorderStyle
border style Double
empty : Struct.Cell (Cell msg)
empty Cell
summary = Table.empty -- nothing for summary
th : List (Html.Attribute msg) -> List (Html msg) -> Struct.Cell (Cell msg)
th Cell
Table.th [] -- attributes
[ "id" |> H.text ] -- contents
td : List (Html.Attribute msg) -> List (Html msg) -> Struct.Cell (Cell msg)
td Cell
Table.td [] -- attributes
[ H.p [] -- content
[ "content" |> H.text ]
]
map : (msg -> super) -> Column row msg -> Column row super
map Column
type Msg
= Sub SubMsg
column : model -> Table.Column row SubMsg
model |> column |> Table.map Sub