Refactor route structure (#219)

This commit is contained in:
Marek Fajkus 2020-10-30 19:13:55 +01:00 committed by GitHub
parent 2de4ef3bda
commit fe04d9b14e
Failed to generate hash of commit
6 changed files with 167 additions and 252 deletions

View file

@ -162,15 +162,27 @@ changeRouteTo currentModel url =
let
attempteQuery (( newModel, cmd ) as pair) =
case ( currentModel.route, newModel.route ) of
( Route.Packages channel1 query1 _ from1 size1 sort1, Route.Packages channel2 query2 _ from2 size2 sort2 ) ->
if channel1 /= channel2 || query1 /= query2 || from1 /= from2 || size1 /= size2 || sort1 /= sort2 then
( Route.Packages arg1, Route.Packages arg2 ) ->
if
(arg1.channel /= arg2.channel)
|| (arg1.query /= arg2.query)
|| (arg1.from /= arg2.from)
|| (arg1.size /= arg2.size)
|| (arg1.sort /= arg2.sort)
then
submitQuery newModel ( newModel, cmd )
else
pair
( Route.Options channel1 query1 _ from1 size1 sort1, Route.Options channel2 query2 _ from2 size2 sort2 ) ->
if channel1 /= channel2 || query1 /= query2 || from1 /= from2 || size1 /= size2 || sort1 /= sort2 then
( Route.Options arg1, Route.Options arg2 ) ->
if
(arg1.channel /= arg2.channel)
|| (arg1.query /= arg2.query)
|| (arg1.from /= arg2.from)
|| (arg1.size /= arg2.size)
|| (arg1.sort /= arg2.sort)
then
submitQuery newModel ( newModel, cmd )
else
@ -203,7 +215,7 @@ changeRouteTo currentModel url =
-- on the home page
( model, Browser.Navigation.pushUrl model.navKey "/packages" )
Route.Packages channel query show from size sort ->
Route.Packages searchArgs ->
let
modelPage =
case model.page of
@ -213,11 +225,11 @@ changeRouteTo currentModel url =
_ ->
Nothing
in
Page.Packages.init channel query show from size sort modelPage
Page.Packages.init searchArgs modelPage
|> updateWith Packages PackagesMsg model
|> attempteQuery
Route.Options channel query show from size sort ->
Route.Options searchArgs ->
let
modelPage =
case model.page of
@ -227,7 +239,7 @@ changeRouteTo currentModel url =
_ ->
Nothing
in
Page.Options.init channel query show from size sort modelPage
Page.Options.init searchArgs modelPage
|> updateWith Options OptionsMsg model
|> attempteQuery
@ -349,14 +361,14 @@ viewNavigation route =
toRoute f =
case route of
-- Preserve arguments
Route.Packages channel query show from size sort ->
f channel query show from size sort
Route.Packages searchArgs ->
f searchArgs
Route.Options channel query show from size sort ->
f channel query show from size sort
Route.Options searchArgs ->
f searchArgs
_ ->
f Nothing Nothing Nothing Nothing Nothing Nothing
f <| Route.SearchArgs Nothing Nothing Nothing Nothing Nothing Nothing
in
li [] [ a [ href "https://nixos.org" ] [ text "Back to nixos.org" ] ]
:: List.map

View file

@ -65,19 +65,11 @@ type alias ResultItemSource =
}
init :
Maybe String
-> Maybe String
-> Maybe String
-> Maybe Int
-> Maybe Int
-> Maybe String
-> Maybe Model
-> ( Model, Cmd Msg )
init channel query show from size sort model =
init : Route.SearchArgs -> Maybe Model -> ( Model, Cmd Msg )
init searchArgs model =
let
( newModel, newCmd ) =
Search.init channel query show from size sort model
Search.init searchArgs model
in
( newModel
, Cmd.map SearchMsg newCmd

View file

@ -102,19 +102,11 @@ type alias ResultPackageHydraPath =
}
init :
Maybe String
-> Maybe String
-> Maybe String
-> Maybe Int
-> Maybe Int
-> Maybe String
-> Maybe Model
-> ( Model, Cmd Msg )
init channel query show from size sort model =
init : Route.SearchArgs -> Maybe Model -> ( Model, Cmd Msg )
init searchArgs model =
let
( newModel, newCmd ) =
Search.init channel query show from size sort model
Search.init searchArgs model
in
( newModel
, Cmd.map SearchMsg newCmd

View file

@ -1,12 +1,20 @@
module Route exposing (Route(..), fromUrl, href, replaceUrl, routeToString)
module Route exposing
( Route(..)
, SearchArgs
, SearchRoute
, fromUrl
, href
, replaceUrl
, routeToString
)
import Browser.Navigation
import Html
import Html.Attributes
import Route.SearchQuery
import Route.SearchQuery exposing (SearchQuery)
import Url
import Url.Builder exposing (QueryParameter)
import Url.Parser exposing ((<?>))
import Url.Parser exposing ((</>), (<?>))
import Url.Parser.Query
@ -14,45 +22,66 @@ import Url.Parser.Query
-- ROUTING
type Route
= NotFound
| Home
-- route | channel | (search) query | show | from | size | sort
| Packages (Maybe String) (Maybe String) (Maybe String) (Maybe Int) (Maybe Int) (Maybe String)
| Options (Maybe String) (Maybe String) (Maybe String) (Maybe Int) (Maybe Int) (Maybe String)
type alias SearchArgs =
{ query : Maybe SearchQuery
, channel : Maybe String
, show : Maybe String
, from : Maybe Int
, size : Maybe Int
-- TODO: embed sort type
, sort : Maybe String
}
parser : Url.Url -> Url.Parser.Parser (Route -> msg) msg
parser url =
type alias SearchRoute =
SearchArgs -> Route
searchQueryParser : Url.Url -> Url.Parser.Parser (SearchArgs -> msg) msg
searchQueryParser url =
let
rawQuery =
Route.SearchQuery.toRawQuery url
withSearchQuery : (a -> Maybe String -> b) -> a -> b
withSearchQuery f channel =
f channel <|
Maybe.andThen Route.SearchQuery.searchQueryToString <|
Maybe.andThen (Route.SearchQuery.searchString "query") rawQuery
maybeQuery = Maybe.andThen (Route.SearchQuery.searchString "query") rawQuery
in
Url.Parser.map (SearchArgs maybeQuery) <|
Url.Parser.top
<?> Url.Parser.Query.string "channel"
<?> Url.Parser.Query.string "show"
<?> Url.Parser.Query.int "from"
<?> Url.Parser.Query.int "size"
<?> Url.Parser.Query.string "sort"
searchArgsToUrl : SearchArgs -> ( List QueryParameter, Maybe ( String, Route.SearchQuery.SearchQuery ) )
searchArgsToUrl args =
( List.filterMap identity
[ Maybe.map (Url.Builder.string "channel") args.channel
, Maybe.map (Url.Builder.string "show") args.show
, Maybe.map (Url.Builder.int "from") args.from
, Maybe.map (Url.Builder.int "size") args.size
, Maybe.map (Url.Builder.string "sort") args.sort
]
, Maybe.map (Tuple.pair "query") args.query
)
type Route
= NotFound
| Home
| Packages SearchArgs
| Options SearchArgs
parser : Url.Url -> Url.Parser.Parser (Route -> msg) msg
parser url =
Url.Parser.oneOf
[ Url.Parser.map Home Url.Parser.top
, Url.Parser.map NotFound (Url.Parser.s "not-found")
, Url.Parser.map (withSearchQuery Packages)
(Url.Parser.s "packages"
<?> Url.Parser.Query.string "channel"
<?> Url.Parser.Query.string "show"
<?> Url.Parser.Query.int "from"
<?> Url.Parser.Query.int "size"
<?> Url.Parser.Query.string "sort"
)
, Url.Parser.map (withSearchQuery Options)
(Url.Parser.s "options"
<?> Url.Parser.Query.string "channel"
<?> Url.Parser.Query.string "show"
<?> Url.Parser.Query.int "from"
<?> Url.Parser.Query.int "size"
<?> Url.Parser.Query.string "sort"
)
, Url.Parser.map NotFound <| Url.Parser.s "not-found"
, Url.Parser.map Packages <| Url.Parser.s "packages" </> searchQueryParser url
, Url.Parser.map Options <| Url.Parser.s "options" </> searchQueryParser url
]
@ -96,51 +125,17 @@ routeToString =
routeToPieces : Route -> ( List String, List QueryParameter, Maybe ( String, Route.SearchQuery.SearchQuery ) )
routeToPieces page =
let
channelQ =
Maybe.map (Url.Builder.string "channel")
case page of
Home ->
( [], [], Nothing )
queryQ =
Maybe.map (Route.SearchQuery.toSearchQuery "query")
NotFound ->
( [ "not-found" ], [], Nothing )
showQ =
Maybe.map (Url.Builder.string "show")
Packages searchArgs ->
searchArgsToUrl searchArgs
|> (\( query, raw ) -> ( [ "packages" ], query, raw ))
fromQ =
Maybe.map (Url.Builder.int "from")
sizeQ =
Maybe.map (Url.Builder.int "size")
sortQ =
Maybe.map (Url.Builder.string "sort")
in
(\( path, urlQ, searchQuery ) -> ( path, List.filterMap identity urlQ, searchQuery )) <|
case page of
Home ->
( [], [], Nothing )
NotFound ->
( [ "not-found" ], [], Nothing )
Packages channel query show from size sort ->
( [ "packages" ]
, [ channelQ channel
, showQ show
, fromQ from
, sizeQ size
, sortQ sort
]
, queryQ query
)
Options channel query show from size sort ->
( [ "options" ]
, [ channelQ channel
, showQ show
, fromQ from
, sizeQ size
, sortQ sort
]
, queryQ query
)
Options searchArgs ->
searchArgsToUrl searchArgs
|> (\( query, raw ) -> ( [ "options" ], query, raw ))

View file

@ -60,9 +60,9 @@ searchQueryToString (SearchQuery str) =
Url.percentDecode <| String.replace "+" "%20" str
toSearchQuery : String -> String -> ( String, SearchQuery )
toSearchQuery name query =
( name, SearchQuery <| String.replace "%20" "+" <| Url.percentEncode query )
toSearchQuery : String -> SearchQuery
toSearchQuery query =
SearchQuery <| String.replace "%20" "+" <| Url.percentEncode query
{-| Build absolute URL with support for search query strings

View file

@ -63,22 +63,13 @@ import Json.Decode
import Json.Encode
import RemoteData
import Route exposing (Route)
import Route.SearchQuery
import Set
import Task
import Url
import Url.Builder
type alias SearchRoute =
Maybe String
-> Maybe String
-> Maybe String
-> Maybe Int
-> Maybe Int
-> Maybe String
-> Route
type alias Model a =
{ channel : String
, query : Maybe String
@ -124,16 +115,8 @@ type Sort
| AlphabeticallyDesc
init :
Maybe String
-> Maybe String
-> Maybe String
-> Maybe Int
-> Maybe Int
-> Maybe String
-> Maybe (Model a)
-> ( Model a, Cmd (Msg a) )
init channel query show from size sort model =
init : Route.SearchArgs -> Maybe (Model a) -> ( Model a, Cmd (Msg a) )
init args model =
let
defaultChannel =
model
@ -150,17 +133,17 @@ init channel query show from size sort model =
|> Maybe.map (\x -> x.size)
|> Maybe.withDefault 30
in
( { channel = Maybe.withDefault defaultChannel channel
, query = query
( { channel = Maybe.withDefault defaultChannel args.channel
, query = Maybe.andThen Route.SearchQuery.searchQueryToString args.query
, result =
model
|> Maybe.map (\x -> x.result)
|> Maybe.withDefault RemoteData.NotAsked
, show = show
, from = Maybe.withDefault defaultFrom from
, size = Maybe.withDefault defaultSize size
, show = args.show
, from = Maybe.withDefault defaultFrom args.from
, size = Maybe.withDefault defaultSize args.size
, sort =
sort
args.sort
|> Maybe.withDefault ""
|> fromSortId
|> Maybe.withDefault Relevance
@ -186,7 +169,7 @@ type Msg a
update :
SearchRoute
Route.SearchRoute
-> Browser.Navigation.Key
-> Msg a
-> Model a
@ -199,24 +182,14 @@ update toRoute navKey msg model =
)
SortChange sortId ->
let
sort =
fromSortId sortId |> Maybe.withDefault Relevance
in
( { model | sort = sort }
, createUrl
toRoute
model.channel
model.query
model.show
0
model.size
sort
|> Browser.Navigation.pushUrl navKey
)
{ model
| sort = fromSortId sortId |> Maybe.withDefault Relevance
, from = 0
}
|> pushUrl toRoute navKey
ChannelChange channel ->
( { model
{ model
| channel = channel
, result =
if model.query == Nothing || model.query == Just "" then
@ -224,21 +197,9 @@ update toRoute navKey msg model =
else
RemoteData.Loading
}
, if model.query == Nothing || model.query == Just "" then
Cmd.none
else
createUrl
toRoute
channel
model.query
model.show
0
model.size
model.sort
|> Browser.Navigation.pushUrl navKey
)
, from = 0
}
|> pushUrl toRoute navKey
QueryInput query ->
( { model | query = Just query }
@ -246,21 +207,11 @@ update toRoute navKey msg model =
)
QueryInputSubmit ->
if model.query == Nothing || model.query == Just "" then
( model, Cmd.none )
else
( { model | result = RemoteData.Loading }
, createUrl
toRoute
model.channel
model.query
model.show
0
model.size
model.sort
|> Browser.Navigation.pushUrl navKey
)
{ model
| result = RemoteData.Loading
, from = 0
}
|> pushUrl toRoute navKey
QueryResponse result ->
( { model | result = result }
@ -268,38 +219,38 @@ update toRoute navKey msg model =
)
ShowDetails selected ->
( model
, createUrl
toRoute
model.channel
model.query
(if model.show == Just selected then
Nothing
{ model
| show =
if model.show == Just selected then
Nothing
else
Just selected
)
model.from
model.size
model.sort
|> Browser.Navigation.pushUrl navKey
)
else
Just selected
}
|> pushUrl toRoute navKey
{-| TODO: Sort should be part of Route type
-}
createUrl :
SearchRoute
-> String
-> Maybe String
-> Maybe String
-> Int
-> Int
-> Sort
-> String
createUrl toRoute channel query show from size sort =
toRoute (Just channel) query show (Just from) (Just size) (Just <| toSortId sort)
|> Route.routeToString
pushUrl : Route.SearchRoute -> Browser.Navigation.Key -> Model a -> ( Model a, Cmd msg )
pushUrl toRoute navKey model =
Tuple.pair model <|
if model.query == Nothing || model.query == Just "" then
Cmd.none
else
Browser.Navigation.pushUrl navKey <| createUrl toRoute model
createUrl : Route.SearchRoute -> Model a -> String
createUrl toRoute model =
Route.routeToString <|
toRoute
{ channel = Just model.channel
, query = Maybe.map Route.SearchQuery.toSearchQuery model.query
, show = model.show
, from = Just model.from
, size = Just model.size
, sort = Just <| toSortId model.sort
}
@ -448,7 +399,7 @@ fromSortId id =
view :
{ toRoute : SearchRoute
{ toRoute : Route.SearchRoute
, categoryName : String
}
-> String
@ -624,7 +575,7 @@ viewPager :
(Msg a -> b)
-> Model a
-> SearchResult a
-> SearchRoute
-> Route.SearchRoute
-> Html b
viewPager _ model result toRoute =
ul [ class "pager" ]
@ -639,14 +590,7 @@ viewPager _ model result toRoute =
""
else
createUrl
toRoute
model.channel
model.query
model.show
0
model.size
model.sort
createUrl toRoute { model | from = 0 }
]
[ text "First" ]
]
@ -661,14 +605,7 @@ viewPager _ model result toRoute =
""
else
createUrl
toRoute
model.channel
model.query
model.show
(model.from - model.size)
model.size
model.sort
createUrl toRoute { model | from = model.from - model.size }
]
[ text "Previous" ]
]
@ -683,14 +620,7 @@ viewPager _ model result toRoute =
""
else
createUrl
toRoute
model.channel
model.query
model.show
(model.from + model.size)
model.size
model.sort
createUrl toRoute { model | from = model.from + model.size }
]
[ text "Next" ]
]
@ -713,14 +643,8 @@ viewPager _ model result toRoute =
else
0
in
createUrl
toRoute
model.channel
model.query
model.show
(((result.hits.total.value // model.size) - remainder) * model.size)
model.size
model.sort
createUrl toRoute
{ model | from = ((result.hits.total.value // model.size) - remainder) * model.size }
]
[ text "Last" ]
]