Permalink
Find file Copy path
d98f351 Dec 8, 2018
2 contributors

Users who have contributed to this file

@dillonkearns @xtian
181 lines (137 sloc) 4.9 KB
module GithubPagination exposing (main)
import Browser
import Github.Enum.SearchType
import Github.Object
import Github.Object.PageInfo
import Github.Object.Repository as Repository
import Github.Object.SearchResultItemConnection
import Github.Object.StargazerConnection
import Github.Query as Query
import Github.Scalar
import Github.Union
import Github.Union.SearchResultItem
import Graphql.Document as Document
import Graphql.Http
import Graphql.Operation exposing (RootQuery)
import Graphql.OptionalArgument as OptionalArgument exposing (OptionalArgument(..))
import Graphql.SelectionSet as SelectionSet exposing (SelectionSet, with)
import Html exposing (button, div, h1, p, pre, text)
import Html.Events exposing (onClick)
import PrintAny
import RemoteData exposing (RemoteData)
type alias Response =
Paginator (List (Maybe (Maybe Repo))) String
type alias Paginator dataType cursorType =
{ data : dataType
, paginationData : PaginationData cursorType
}
query : Maybe String -> SelectionSet Response RootQuery
query cursor =
Query.search
(\optionals ->
{ optionals
| first = Present 1
, after = OptionalArgument.fromMaybe cursor
}
)
{ query = "language:Elm"
, type_ = Github.Enum.SearchType.Repository
}
searchSelection
searchSelection : SelectionSet Response Github.Object.SearchResultItemConnection
searchSelection =
SelectionSet.succeed Paginator
|> with searchResultField
|> with (Github.Object.SearchResultItemConnection.pageInfo searchPageInfoSelection)
type alias PaginationData cursorType =
{ cursor : Maybe cursorType
, hasNextPage : Bool
}
searchPageInfoSelection : SelectionSet (PaginationData String) Github.Object.PageInfo
searchPageInfoSelection =
SelectionSet.succeed PaginationData
|> with Github.Object.PageInfo.endCursor
|> with Github.Object.PageInfo.hasNextPage
searchResultField : SelectionSet (List (Maybe (Maybe Repo))) Github.Object.SearchResultItemConnection
searchResultField =
Github.Object.SearchResultItemConnection.nodes searchResultSelection |> SelectionSet.nonNullOrFail
searchResultSelection : SelectionSet (Maybe Repo) Github.Union.SearchResultItem
searchResultSelection =
let
defaults =
Github.Union.SearchResultItem.maybeFragments
in
Github.Union.SearchResultItem.fragments
{ defaults | onRepository = repositorySelection |> SelectionSet.map Just }
type alias Repo =
{ name : String
, description : Maybe String
, createdAt : Github.Scalar.DateTime
, updatedAt : Github.Scalar.DateTime
, stargazers : Int
}
repositorySelection : SelectionSet Repo Github.Object.Repository
repositorySelection =
SelectionSet.succeed Repo
|> with Repository.nameWithOwner
|> with Repository.description
|> with Repository.createdAt
|> with Repository.updatedAt
|> with (Repository.stargazers identity Github.Object.StargazerConnection.totalCount)
makeRequest : Maybe String -> Cmd Msg
makeRequest cursor =
query cursor
|> Graphql.Http.queryRequest "https://api.github.com/graphql"
|> Graphql.Http.withHeader "authorization" "Bearer dbd4c239b0bbaa40ab0ea291fa811775da8f5b59"
|> Graphql.Http.send (RemoteData.fromResult >> GotResponse)
type Msg
= GotResponse RemoteDataResponse
| GetNextPage
type alias Model =
List RemoteDataResponse
type alias RemoteDataResponse =
RemoteData (Graphql.Http.Error Response) Response
init : Flags -> ( Model, Cmd Msg )
init flags =
( [ RemoteData.Loading ], makeRequest Nothing )
view : Model -> Html.Html Msg
view model =
div []
[ div []
[ h1 [] [ text "Generated Query" ]
, pre [] [ text (Document.serializeQuery (query Nothing)) ]
]
, div [] [ button [ onClick GetNextPage ] [ text "Load next page..." ] ]
, div []
[ h1 [] [ text "Response" ]
, PrintAny.view model
]
]
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
GetNextPage ->
case model of
(RemoteData.Success successResponse) :: rest ->
if successResponse.paginationData.hasNextPage then
( RemoteData.Loading :: model, makeRequest successResponse.paginationData.cursor )
else
( model, Cmd.none )
_ ->
( model, Cmd.none )
GotResponse response ->
case model of
head :: rest ->
( response :: rest, Cmd.none )
_ ->
( model, Cmd.none )
type alias Flags =
()
main : Program Flags Model Msg
main =
Browser.element
{ init = init
, update = update
, subscriptions = \_ -> Sub.none
, view = view
}