mirror of
https://github.com/dillonkearns/elm-pages-v3-beta.git
synced 2024-11-24 06:54:03 +03:00
Show search results in trails.
This commit is contained in:
parent
31265b4979
commit
b030de85ba
@ -1,8 +1,15 @@
|
|||||||
module Route.Search exposing (ActionData, Data, Model, Msg, route)
|
module Route.Search exposing (ActionData, Data, Model, Msg, route)
|
||||||
|
|
||||||
|
import Api.InputObject
|
||||||
|
import Api.Object
|
||||||
|
import Api.Object.Trails
|
||||||
|
import Api.Query
|
||||||
import DataSource exposing (DataSource)
|
import DataSource exposing (DataSource)
|
||||||
import Effect exposing (Effect)
|
import Effect exposing (Effect)
|
||||||
import ErrorPage exposing (ErrorPage)
|
import ErrorPage exposing (ErrorPage)
|
||||||
|
import Graphql.Operation exposing (RootQuery)
|
||||||
|
import Graphql.OptionalArgument exposing (OptionalArgument(..))
|
||||||
|
import Graphql.SelectionSet exposing (SelectionSet)
|
||||||
import Head
|
import Head
|
||||||
import Head.Seo as Seo
|
import Head.Seo as Seo
|
||||||
import Html exposing (Html)
|
import Html exposing (Html)
|
||||||
@ -11,6 +18,7 @@ import Pages.Msg
|
|||||||
import Pages.PageUrl exposing (PageUrl)
|
import Pages.PageUrl exposing (PageUrl)
|
||||||
import Pages.Url
|
import Pages.Url
|
||||||
import Path exposing (Path)
|
import Path exposing (Path)
|
||||||
|
import Request.Hasura
|
||||||
import RouteBuilder exposing (StatefulRoute, StatelessRoute, StaticPayload)
|
import RouteBuilder exposing (StatefulRoute, StatelessRoute, StaticPayload)
|
||||||
import Server.Request as Request
|
import Server.Request as Request
|
||||||
import Server.Response as Response exposing (Response)
|
import Server.Response as Response exposing (Response)
|
||||||
@ -95,15 +103,18 @@ data routeParams =
|
|||||||
field "q"
|
field "q"
|
||||||
|> Request.map
|
|> Request.map
|
||||||
(\query ->
|
(\query ->
|
||||||
DataSource.succeed
|
Request.Hasura.dataSource ""
|
||||||
(Response.render
|
(search query)
|
||||||
{ results =
|
|> DataSource.map
|
||||||
Just
|
(\results ->
|
||||||
{ query = query
|
Response.render
|
||||||
, results = [ "Hello" ]
|
{ results =
|
||||||
|
Just
|
||||||
|
{ query = query
|
||||||
|
, results = results
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
, Request.succeed (DataSource.succeed (Response.render { results = Nothing }))
|
, Request.succeed (DataSource.succeed (Response.render { results = Nothing }))
|
||||||
@ -121,7 +132,7 @@ head :
|
|||||||
head static =
|
head static =
|
||||||
Seo.summary
|
Seo.summary
|
||||||
{ canonicalUrlOverride = Nothing
|
{ canonicalUrlOverride = Nothing
|
||||||
, siteName = "elm-pages"
|
, siteName = "Trail Blazer"
|
||||||
, image =
|
, image =
|
||||||
{ url = Pages.Url.external "TODO"
|
{ url = Pages.Url.external "TODO"
|
||||||
, alt = "elm-pages logo"
|
, alt = "elm-pages logo"
|
||||||
@ -130,7 +141,16 @@ head static =
|
|||||||
}
|
}
|
||||||
, description = "TODO"
|
, description = "TODO"
|
||||||
, locale = Nothing
|
, locale = Nothing
|
||||||
, title = "TODO title" -- metadata.title -- TODO
|
, title =
|
||||||
|
case static.data.results of
|
||||||
|
Nothing ->
|
||||||
|
"Find your next trail"
|
||||||
|
|
||||||
|
Just { results, query } ->
|
||||||
|
query
|
||||||
|
++ " at TrailBlazer ("
|
||||||
|
++ String.fromInt (List.length results)
|
||||||
|
++ " results)"
|
||||||
}
|
}
|
||||||
|> Seo.website
|
|> Seo.website
|
||||||
|
|
||||||
@ -163,4 +183,36 @@ resultsView : SearchResults -> Html msg
|
|||||||
resultsView results =
|
resultsView results =
|
||||||
Html.div []
|
Html.div []
|
||||||
[ Html.h2 [] [ Html.text <| "Results matching " ++ results.query ]
|
[ Html.h2 [] [ Html.text <| "Results matching " ++ results.query ]
|
||||||
|
, results.results
|
||||||
|
|> List.map
|
||||||
|
(\result ->
|
||||||
|
Html.li []
|
||||||
|
[ Html.text result
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|> Html.ul []
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
search : String -> SelectionSet (List String) RootQuery
|
||||||
|
search query =
|
||||||
|
Api.Query.trails
|
||||||
|
(\optionals ->
|
||||||
|
{ optionals
|
||||||
|
| where_ =
|
||||||
|
Present
|
||||||
|
(Api.InputObject.buildTrails_bool_exp
|
||||||
|
(\whereOptionals ->
|
||||||
|
{ whereOptionals
|
||||||
|
| name =
|
||||||
|
Api.InputObject.buildString_comparison_exp
|
||||||
|
(\stringOptionals ->
|
||||||
|
{ stringOptionals | ilike_ = Present <| "%" ++ query ++ "%" }
|
||||||
|
)
|
||||||
|
|> Present
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Api.Object.Trails.name
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
module Request.Fauna exposing (dataSource, mutationDataSource)
|
|
||||||
|
|
||||||
import DataSource exposing (DataSource)
|
|
||||||
import DataSource.Http
|
|
||||||
import Graphql.Document
|
|
||||||
import Graphql.Operation exposing (RootMutation, RootQuery)
|
|
||||||
import Graphql.SelectionSet exposing (SelectionSet)
|
|
||||||
import Json.Encode as Encode
|
|
||||||
|
|
||||||
|
|
||||||
dataSource : String -> SelectionSet value RootQuery -> DataSource value
|
|
||||||
dataSource timeStamp selectionSet =
|
|
||||||
DataSource.Http.request
|
|
||||||
{ url =
|
|
||||||
faunaUrl
|
|
||||||
-- for now, this timestamp invalidates the dev server cache
|
|
||||||
-- it would be helpful to have a way to mark a DataSource as uncached. Maybe only allow
|
|
||||||
-- from server-rendered pages?
|
|
||||||
++ "?time="
|
|
||||||
++ timeStamp
|
|
||||||
, method = "POST"
|
|
||||||
, headers = [ ( "authorization", faunaAuthValue ) ]
|
|
||||||
, body =
|
|
||||||
DataSource.Http.jsonBody
|
|
||||||
(Encode.object
|
|
||||||
[ ( "query"
|
|
||||||
, selectionSet
|
|
||||||
|> Graphql.Document.serializeQuery
|
|
||||||
|> Encode.string
|
|
||||||
)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
(selectionSet
|
|
||||||
|> Graphql.Document.decoder
|
|
||||||
|> DataSource.Http.expectJson
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
mutationDataSource : String -> SelectionSet value RootMutation -> DataSource value
|
|
||||||
mutationDataSource timeStamp selectionSet =
|
|
||||||
DataSource.Http.request
|
|
||||||
{ url = faunaUrl ++ "?time=" ++ timeStamp
|
|
||||||
, method = "POST"
|
|
||||||
, headers = [ ( "authorization", faunaAuthValue ) ]
|
|
||||||
, body =
|
|
||||||
DataSource.Http.jsonBody
|
|
||||||
(Encode.object
|
|
||||||
[ ( "query"
|
|
||||||
, selectionSet
|
|
||||||
|> Graphql.Document.serializeMutation
|
|
||||||
|> Encode.string
|
|
||||||
)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
(selectionSet
|
|
||||||
|> Graphql.Document.decoder
|
|
||||||
|> DataSource.Http.expectJson
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
faunaUrl : String
|
|
||||||
faunaUrl =
|
|
||||||
"https://graphql.us.fauna.com/graphql"
|
|
||||||
|
|
||||||
|
|
||||||
faunaAuthValue : String
|
|
||||||
faunaAuthValue =
|
|
||||||
"Bearer fnAEdqJ_JdAAST7wRrjZj7NKSw-vCfE9_W8RyshZ"
|
|
74
examples/trails/src/Request/Hasura.elm
Normal file
74
examples/trails/src/Request/Hasura.elm
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
module Request.Hasura exposing (dataSource, mutationDataSource)
|
||||||
|
|
||||||
|
import DataSource exposing (DataSource)
|
||||||
|
import DataSource.Env
|
||||||
|
import DataSource.Http
|
||||||
|
import Graphql.Document
|
||||||
|
import Graphql.Operation exposing (RootMutation, RootQuery)
|
||||||
|
import Graphql.SelectionSet exposing (SelectionSet)
|
||||||
|
import Json.Encode as Encode
|
||||||
|
|
||||||
|
|
||||||
|
dataSource : String -> SelectionSet value RootQuery -> DataSource value
|
||||||
|
dataSource timeStamp selectionSet =
|
||||||
|
DataSource.Env.expect "TRAILS_HASURA_SECRET"
|
||||||
|
|> DataSource.andThen
|
||||||
|
(\hasuraSecret ->
|
||||||
|
DataSource.Http.request
|
||||||
|
{ url =
|
||||||
|
hasuraUrl
|
||||||
|
-- for now, this timestamp invalidates the dev server cache
|
||||||
|
-- it would be helpful to have a way to mark a DataSource as uncached. Maybe only allow
|
||||||
|
-- from server-rendered pages?
|
||||||
|
++ "?time="
|
||||||
|
++ timeStamp
|
||||||
|
, method = "POST"
|
||||||
|
, headers = [ ( "x-hasura-admin-secret", hasuraSecret ) ]
|
||||||
|
, body =
|
||||||
|
DataSource.Http.jsonBody
|
||||||
|
(Encode.object
|
||||||
|
[ ( "query"
|
||||||
|
, selectionSet
|
||||||
|
|> Graphql.Document.serializeQuery
|
||||||
|
|> Encode.string
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
(selectionSet
|
||||||
|
|> Graphql.Document.decoder
|
||||||
|
|> DataSource.Http.expectJson
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
mutationDataSource : String -> SelectionSet value RootMutation -> DataSource value
|
||||||
|
mutationDataSource timeStamp selectionSet =
|
||||||
|
DataSource.Env.expect "TRAILS_HASURA_SECRET"
|
||||||
|
|> DataSource.andThen
|
||||||
|
(\hasuraSecret ->
|
||||||
|
DataSource.Http.request
|
||||||
|
{ url = hasuraUrl ++ "?time=" ++ timeStamp
|
||||||
|
, method = "POST"
|
||||||
|
, headers = [ ( "x-hasura-admin-secret", hasuraSecret ) ]
|
||||||
|
, body =
|
||||||
|
DataSource.Http.jsonBody
|
||||||
|
(Encode.object
|
||||||
|
[ ( "query"
|
||||||
|
, selectionSet
|
||||||
|
|> Graphql.Document.serializeMutation
|
||||||
|
|> Encode.string
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
(selectionSet
|
||||||
|
|> Graphql.Document.decoder
|
||||||
|
|> DataSource.Http.expectJson
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
hasuraUrl : String
|
||||||
|
hasuraUrl =
|
||||||
|
"https://striking-mutt-82.hasura.app/v1/graphql"
|
@ -14,6 +14,7 @@ module Server.Request exposing
|
|||||||
, map3, map4, map5, map6, map7, map8, map9
|
, map3, map4, map5, map6, map7, map8, map9
|
||||||
, Method(..), methodToString
|
, Method(..), methodToString
|
||||||
, errorsToString, errorToString, getDecoder, ValidationError
|
, errorsToString, errorToString, getDecoder, ValidationError
|
||||||
|
, expectForm
|
||||||
)
|
)
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
@ -966,6 +967,68 @@ expectFormPost toForm =
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
{-| -}
|
||||||
|
expectForm :
|
||||||
|
({ field : String -> Parser String
|
||||||
|
, optionalField : String -> Parser (Maybe String)
|
||||||
|
}
|
||||||
|
-> Parser decodedForm
|
||||||
|
)
|
||||||
|
-> Parser decodedForm
|
||||||
|
expectForm toForm =
|
||||||
|
map2 Tuple.pair
|
||||||
|
queryParams
|
||||||
|
method
|
||||||
|
|> andThen
|
||||||
|
(\( queryParams_, validMethod ) ->
|
||||||
|
if validMethod == Get then
|
||||||
|
queryParams_
|
||||||
|
|> Dict.map
|
||||||
|
(\k v ->
|
||||||
|
v
|
||||||
|
|> List.NonEmpty.fromList
|
||||||
|
|> Maybe.withDefault ( "", [] )
|
||||||
|
)
|
||||||
|
|> succeed
|
||||||
|
|> andThen
|
||||||
|
(\parsedForm ->
|
||||||
|
let
|
||||||
|
thing : Json.Encode.Value
|
||||||
|
thing =
|
||||||
|
parsedForm
|
||||||
|
|> Dict.toList
|
||||||
|
|> List.map
|
||||||
|
(Tuple.mapSecond
|
||||||
|
(\( first, _ ) ->
|
||||||
|
Json.Encode.string first
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|> Json.Encode.object
|
||||||
|
|
||||||
|
innerDecoder : Json.Decode.Decoder ( Result ValidationError decodedForm, List ValidationError )
|
||||||
|
innerDecoder =
|
||||||
|
toForm { field = formField_, optionalField = optionalFormField_ }
|
||||||
|
|> (\(Internal.Request.Parser decoder) -> decoder)
|
||||||
|
in
|
||||||
|
Json.Decode.decodeValue innerDecoder thing
|
||||||
|
|> Result.mapError Json.Decode.errorToString
|
||||||
|
|> jsonFromResult
|
||||||
|
|> Internal.Request.Parser
|
||||||
|
)
|
||||||
|
|
||||||
|
else
|
||||||
|
Json.Decode.succeed
|
||||||
|
( Err
|
||||||
|
(ValidationError <|
|
||||||
|
"TODO validation error for not matching GET form submission"
|
||||||
|
--"expectFormPost did not match - expected method GET, but the method was " ++ methodToString validMethod
|
||||||
|
)
|
||||||
|
, []
|
||||||
|
)
|
||||||
|
|> Internal.Request.Parser
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
{-| -}
|
{-| -}
|
||||||
expectMultiPartFormPost :
|
expectMultiPartFormPost :
|
||||||
({ field : String -> Parser String
|
({ field : String -> Parser String
|
||||||
|
Loading…
Reference in New Issue
Block a user