tutor/www/src/Paginated.elm

85 lines
2.5 KiB
Elm
Raw Normal View History

2021-07-16 16:06:33 +00:00
module Paginated exposing (..)
import Dict
import Http
import Json.Decode
import Maybe.Extra
import Regex
import Url
type alias Page a =
{ prev : Maybe Url.Url
, next : Maybe Url.Url
, values : List a
}
empty : Page a
empty =
{ prev = Nothing
, next = Nothing
, values = []
}
expectJson : (Result Http.Error (Page value) -> msg) -> Json.Decode.Decoder value -> Http.Expect msg
expectJson toMsg decoder =
let
linkPattern : Regex.Regex
linkPattern =
Regex.fromString "<(.*?)>; rel=\"(.*?)\""
|> Maybe.withDefault Regex.never
links : String -> Dict.Dict String String
links s =
let
toTuples xs =
case xs of
[ Just a, Just b ] ->
Just ( b, a )
_ ->
Nothing
in
Regex.find linkPattern s
|> List.map .submatches
|> List.map toTuples
|> Maybe.Extra.values
|> Dict.fromList
in
Http.expectStringResponse toMsg <|
\response ->
case response of
Http.BadUrl_ url ->
Err (Http.BadUrl url)
Http.Timeout_ ->
Err Http.Timeout
Http.NetworkError_ ->
Err Http.NetworkError
Http.BadStatus_ metadata _ ->
Err (Http.BadStatus metadata.statusCode)
Http.GoodStatus_ metadata body ->
case Json.Decode.decodeString (Json.Decode.list decoder) body of
Ok values ->
Ok
{ prev =
Dict.get "link" (Debug.log "headers" metadata.headers)
|> Maybe.map links
|> Maybe.andThen (Dict.get "prev")
|> Maybe.andThen Url.fromString
, next =
Dict.get "link" metadata.headers
|> Maybe.map links
|> Maybe.andThen (Dict.get "next")
|> Maybe.andThen Url.fromString
, values = values
}
Err err ->
Err (Http.BadBody (Json.Decode.errorToString err))