mirror of
https://github.com/dillonkearns/elm-pages-v3-beta.git
synced 2024-11-27 21:29:55 +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)
|
||||
|
||||
import Api.InputObject
|
||||
import Api.Object
|
||||
import Api.Object.Trails
|
||||
import Api.Query
|
||||
import DataSource exposing (DataSource)
|
||||
import Effect exposing (Effect)
|
||||
import ErrorPage exposing (ErrorPage)
|
||||
import Graphql.Operation exposing (RootQuery)
|
||||
import Graphql.OptionalArgument exposing (OptionalArgument(..))
|
||||
import Graphql.SelectionSet exposing (SelectionSet)
|
||||
import Head
|
||||
import Head.Seo as Seo
|
||||
import Html exposing (Html)
|
||||
@ -11,6 +18,7 @@ import Pages.Msg
|
||||
import Pages.PageUrl exposing (PageUrl)
|
||||
import Pages.Url
|
||||
import Path exposing (Path)
|
||||
import Request.Hasura
|
||||
import RouteBuilder exposing (StatefulRoute, StatelessRoute, StaticPayload)
|
||||
import Server.Request as Request
|
||||
import Server.Response as Response exposing (Response)
|
||||
@ -95,12 +103,15 @@ data routeParams =
|
||||
field "q"
|
||||
|> Request.map
|
||||
(\query ->
|
||||
DataSource.succeed
|
||||
(Response.render
|
||||
Request.Hasura.dataSource ""
|
||||
(search query)
|
||||
|> DataSource.map
|
||||
(\results ->
|
||||
Response.render
|
||||
{ results =
|
||||
Just
|
||||
{ query = query
|
||||
, results = [ "Hello" ]
|
||||
, results = results
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -121,7 +132,7 @@ head :
|
||||
head static =
|
||||
Seo.summary
|
||||
{ canonicalUrlOverride = Nothing
|
||||
, siteName = "elm-pages"
|
||||
, siteName = "Trail Blazer"
|
||||
, image =
|
||||
{ url = Pages.Url.external "TODO"
|
||||
, alt = "elm-pages logo"
|
||||
@ -130,7 +141,16 @@ head static =
|
||||
}
|
||||
, description = "TODO"
|
||||
, 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
|
||||
|
||||
@ -163,4 +183,36 @@ resultsView : SearchResults -> Html msg
|
||||
resultsView results =
|
||||
Html.div []
|
||||
[ 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
|
||||
, Method(..), methodToString
|
||||
, 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 :
|
||||
({ field : String -> Parser String
|
||||
|
Loading…
Reference in New Issue
Block a user