Support search engine escaping of spaces (+) (#215)
This commit is contained in:
parent
adbb224490
commit
e412085ea8
|
@ -1,7 +1,5 @@
|
||||||
module Main exposing (main)
|
module Main exposing (main)
|
||||||
|
|
||||||
--exposing (UrlRequest(..))
|
|
||||||
|
|
||||||
import Browser
|
import Browser
|
||||||
import Browser.Navigation
|
import Browser.Navigation
|
||||||
import Html
|
import Html
|
||||||
|
|
|
@ -43,6 +43,7 @@ import Html.Parser.Util
|
||||||
import Json.Decode
|
import Json.Decode
|
||||||
import Json.Encode
|
import Json.Encode
|
||||||
import Regex
|
import Regex
|
||||||
|
import Route
|
||||||
import Search
|
import Search
|
||||||
|
|
||||||
|
|
||||||
|
@ -102,7 +103,7 @@ update navKey msg model =
|
||||||
let
|
let
|
||||||
( newModel, newCmd ) =
|
( newModel, newCmd ) =
|
||||||
Search.update
|
Search.update
|
||||||
"options"
|
Route.Options
|
||||||
navKey
|
navKey
|
||||||
subMsg
|
subMsg
|
||||||
model
|
model
|
||||||
|
@ -116,8 +117,7 @@ update navKey msg model =
|
||||||
|
|
||||||
view : Model -> Html Msg
|
view : Model -> Html Msg
|
||||||
view model =
|
view model =
|
||||||
Search.view
|
Search.view { toRoute = Route.Options, categoryName = "options" }
|
||||||
"options"
|
|
||||||
"Search NixOS options"
|
"Search NixOS options"
|
||||||
model
|
model
|
||||||
viewSuccess
|
viewSuccess
|
||||||
|
|
|
@ -43,6 +43,7 @@ import Json.Decode
|
||||||
import Json.Decode.Pipeline
|
import Json.Decode.Pipeline
|
||||||
import Json.Encode
|
import Json.Encode
|
||||||
import Regex
|
import Regex
|
||||||
|
import Route
|
||||||
import Search
|
import Search
|
||||||
|
|
||||||
|
|
||||||
|
@ -139,7 +140,7 @@ update navKey msg model =
|
||||||
let
|
let
|
||||||
( newModel, newCmd ) =
|
( newModel, newCmd ) =
|
||||||
Search.update
|
Search.update
|
||||||
"packages"
|
Route.Packages
|
||||||
navKey
|
navKey
|
||||||
subMsg
|
subMsg
|
||||||
model
|
model
|
||||||
|
@ -153,8 +154,7 @@ update navKey msg model =
|
||||||
|
|
||||||
view : Model -> Html Msg
|
view : Model -> Html Msg
|
||||||
view model =
|
view model =
|
||||||
Search.view
|
Search.view { toRoute = Route.Packages, categoryName = "packages" }
|
||||||
"packages"
|
|
||||||
"Search NixOS packages"
|
"Search NixOS packages"
|
||||||
model
|
model
|
||||||
viewSuccess
|
viewSuccess
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
module Route exposing (Route(..), fromUrl, href, replaceUrl)
|
module Route exposing (Route(..), fromUrl, href, replaceUrl, routeToString)
|
||||||
|
|
||||||
import Browser.Navigation
|
import Browser.Navigation
|
||||||
import Html
|
import Html
|
||||||
import Html.Attributes
|
import Html.Attributes
|
||||||
|
import Route.SearchQuery
|
||||||
import Url
|
import Url
|
||||||
|
import Url.Builder exposing (QueryParameter)
|
||||||
import Url.Parser exposing ((<?>))
|
import Url.Parser exposing ((<?>))
|
||||||
import Url.Parser.Query
|
import Url.Parser.Query
|
||||||
|
|
||||||
|
@ -19,30 +21,32 @@ type Route
|
||||||
| Options (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)
|
||||||
|
|
||||||
|
|
||||||
parser : Url.Parser.Parser (Route -> msg) msg
|
parser : Url.Url -> Url.Parser.Parser (Route -> msg) msg
|
||||||
parser =
|
parser 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
|
||||||
|
in
|
||||||
Url.Parser.oneOf
|
Url.Parser.oneOf
|
||||||
[ Url.Parser.map
|
[ Url.Parser.map Home Url.Parser.top
|
||||||
Home
|
, Url.Parser.map NotFound (Url.Parser.s "not-found")
|
||||||
Url.Parser.top
|
, Url.Parser.map (withSearchQuery Packages)
|
||||||
, Url.Parser.map
|
|
||||||
NotFound
|
|
||||||
(Url.Parser.s "not-found")
|
|
||||||
, Url.Parser.map
|
|
||||||
Packages
|
|
||||||
(Url.Parser.s "packages"
|
(Url.Parser.s "packages"
|
||||||
<?> Url.Parser.Query.string "channel"
|
<?> Url.Parser.Query.string "channel"
|
||||||
<?> Url.Parser.Query.string "query"
|
|
||||||
<?> Url.Parser.Query.string "show"
|
<?> Url.Parser.Query.string "show"
|
||||||
<?> Url.Parser.Query.int "from"
|
<?> Url.Parser.Query.int "from"
|
||||||
<?> Url.Parser.Query.int "size"
|
<?> Url.Parser.Query.int "size"
|
||||||
<?> Url.Parser.Query.string "sort"
|
<?> Url.Parser.Query.string "sort"
|
||||||
)
|
)
|
||||||
, Url.Parser.map
|
, Url.Parser.map (withSearchQuery Options)
|
||||||
Options
|
|
||||||
(Url.Parser.s "options"
|
(Url.Parser.s "options"
|
||||||
<?> Url.Parser.Query.string "channel"
|
<?> Url.Parser.Query.string "channel"
|
||||||
<?> Url.Parser.Query.string "query"
|
|
||||||
<?> Url.Parser.Query.string "show"
|
<?> Url.Parser.Query.string "show"
|
||||||
<?> Url.Parser.Query.int "from"
|
<?> Url.Parser.Query.int "from"
|
||||||
<?> Url.Parser.Query.int "size"
|
<?> Url.Parser.Query.int "size"
|
||||||
|
@ -71,7 +75,7 @@ fromUrl url =
|
||||||
-- This makes it *literally* the path, so we can proceed
|
-- This makes it *literally* the path, so we can proceed
|
||||||
-- with parsing as if it had been a normal path all along.
|
-- with parsing as if it had been a normal path all along.
|
||||||
--{ url | path = Maybe.withDefault "" url.fragment, fragment = Nothing }
|
--{ url | path = Maybe.withDefault "" url.fragment, fragment = Nothing }
|
||||||
Url.Parser.parse parser url
|
Url.Parser.parse (parser url) url
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,41 +83,63 @@ fromUrl url =
|
||||||
|
|
||||||
|
|
||||||
routeToString : Route -> String
|
routeToString : Route -> String
|
||||||
routeToString page =
|
routeToString =
|
||||||
let
|
let
|
||||||
( path, query ) =
|
buildString ( path, query, searchQuery ) =
|
||||||
routeToPieces page
|
Route.SearchQuery.absolute path query <|
|
||||||
|
Maybe.withDefault [] <|
|
||||||
|
Maybe.map List.singleton searchQuery
|
||||||
in
|
in
|
||||||
"/" ++ String.join "/" path ++ "?" ++ String.join "&" (List.filterMap Basics.identity query)
|
buildString << routeToPieces
|
||||||
|
|
||||||
|
|
||||||
routeToPieces : Route -> ( List String, List (Maybe String) )
|
routeToPieces : Route -> ( List String, List QueryParameter, Maybe ( String, Route.SearchQuery.SearchQuery ) )
|
||||||
routeToPieces page =
|
routeToPieces page =
|
||||||
|
let
|
||||||
|
channelQ =
|
||||||
|
Maybe.map (Url.Builder.string "channel")
|
||||||
|
|
||||||
|
queryQ =
|
||||||
|
Maybe.map (Route.SearchQuery.toSearchQuery "query")
|
||||||
|
|
||||||
|
showQ =
|
||||||
|
Maybe.map (Url.Builder.string "show")
|
||||||
|
|
||||||
|
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
|
case page of
|
||||||
Home ->
|
Home ->
|
||||||
( [], [] )
|
( [], [], Nothing )
|
||||||
|
|
||||||
NotFound ->
|
NotFound ->
|
||||||
( [ "not-found" ], [] )
|
( [ "not-found" ], [], Nothing )
|
||||||
|
|
||||||
Packages channel query show from size sort ->
|
Packages channel query show from size sort ->
|
||||||
( [ "packages" ]
|
( [ "packages" ]
|
||||||
, [ channel
|
, [ channelQ channel
|
||||||
, query
|
, showQ show
|
||||||
, show
|
, fromQ from
|
||||||
, Maybe.map String.fromInt from
|
, sizeQ size
|
||||||
, Maybe.map String.fromInt size
|
, sortQ sort
|
||||||
, sort
|
|
||||||
]
|
]
|
||||||
|
, queryQ query
|
||||||
)
|
)
|
||||||
|
|
||||||
Options channel query show from size sort ->
|
Options channel query show from size sort ->
|
||||||
( [ "options" ]
|
( [ "options" ]
|
||||||
, [ channel
|
, [ channelQ channel
|
||||||
, query
|
, showQ show
|
||||||
, show
|
, fromQ from
|
||||||
, Maybe.map String.fromInt from
|
, sizeQ size
|
||||||
, Maybe.map String.fromInt size
|
, sortQ sort
|
||||||
, sort
|
|
||||||
]
|
]
|
||||||
|
, queryQ query
|
||||||
)
|
)
|
||||||
|
|
87
src/Route/SearchQuery.elm
Normal file
87
src/Route/SearchQuery.elm
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
module Route.SearchQuery exposing
|
||||||
|
( RawQuery
|
||||||
|
, SearchQuery
|
||||||
|
, absolute
|
||||||
|
, searchQueryToString
|
||||||
|
, searchString
|
||||||
|
, toRawQuery
|
||||||
|
, toSearchQuery
|
||||||
|
)
|
||||||
|
|
||||||
|
import Dict exposing (Dict)
|
||||||
|
import Url
|
||||||
|
import Url.Builder
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- RawQuery
|
||||||
|
|
||||||
|
|
||||||
|
type RawQuery
|
||||||
|
= RawQuery (Dict String String)
|
||||||
|
|
||||||
|
|
||||||
|
chunk : String -> String -> Maybe ( String, String )
|
||||||
|
chunk sep str =
|
||||||
|
case String.split sep str of
|
||||||
|
[] ->
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
[ key ] ->
|
||||||
|
Just ( key, "" )
|
||||||
|
|
||||||
|
key :: xs ->
|
||||||
|
Just ( key, String.join sep xs )
|
||||||
|
|
||||||
|
|
||||||
|
toRawQuery : Url.Url -> Maybe RawQuery
|
||||||
|
toRawQuery =
|
||||||
|
Maybe.map (RawQuery << Dict.fromList << List.filterMap (chunk "=") << String.split "&")
|
||||||
|
<< .query
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- SearchQuery
|
||||||
|
|
||||||
|
|
||||||
|
{-| This is type safe wrapper for working with search queries in url
|
||||||
|
-}
|
||||||
|
type SearchQuery
|
||||||
|
= SearchQuery String
|
||||||
|
|
||||||
|
|
||||||
|
searchString : String -> RawQuery -> Maybe SearchQuery
|
||||||
|
searchString name (RawQuery dict) =
|
||||||
|
Maybe.map SearchQuery <| Dict.get name dict
|
||||||
|
|
||||||
|
|
||||||
|
searchQueryToString : SearchQuery -> Maybe String
|
||||||
|
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 )
|
||||||
|
|
||||||
|
|
||||||
|
{-| Build absolute URL with support for search query strings
|
||||||
|
-}
|
||||||
|
absolute : List String -> List Url.Builder.QueryParameter -> List ( String, SearchQuery ) -> String
|
||||||
|
absolute path query searchQuery =
|
||||||
|
let
|
||||||
|
searchStrings =
|
||||||
|
List.map (\( name, SearchQuery val ) -> name ++ "=" ++ val) searchQuery
|
||||||
|
|> String.join "&"
|
||||||
|
in
|
||||||
|
Url.Builder.absolute path query
|
||||||
|
|> (\str ->
|
||||||
|
str
|
||||||
|
++ (case query of
|
||||||
|
[] ->
|
||||||
|
"?" ++ searchStrings
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
"&" ++ searchStrings
|
||||||
|
)
|
||||||
|
)
|
|
@ -62,11 +62,23 @@ import Http
|
||||||
import Json.Decode
|
import Json.Decode
|
||||||
import Json.Encode
|
import Json.Encode
|
||||||
import RemoteData
|
import RemoteData
|
||||||
|
import Route exposing (Route)
|
||||||
import Set
|
import Set
|
||||||
import Task
|
import Task
|
||||||
|
import Url
|
||||||
import Url.Builder
|
import Url.Builder
|
||||||
|
|
||||||
|
|
||||||
|
type alias SearchRoute =
|
||||||
|
Maybe String
|
||||||
|
-> Maybe String
|
||||||
|
-> Maybe String
|
||||||
|
-> Maybe Int
|
||||||
|
-> Maybe Int
|
||||||
|
-> Maybe String
|
||||||
|
-> Route
|
||||||
|
|
||||||
|
|
||||||
type alias Model a =
|
type alias Model a =
|
||||||
{ channel : String
|
{ channel : String
|
||||||
, query : Maybe String
|
, query : Maybe String
|
||||||
|
@ -174,12 +186,12 @@ type Msg a
|
||||||
|
|
||||||
|
|
||||||
update :
|
update :
|
||||||
String
|
SearchRoute
|
||||||
-> Browser.Navigation.Key
|
-> Browser.Navigation.Key
|
||||||
-> Msg a
|
-> Msg a
|
||||||
-> Model a
|
-> Model a
|
||||||
-> ( Model a, Cmd (Msg a) )
|
-> ( Model a, Cmd (Msg a) )
|
||||||
update path navKey msg model =
|
update toRoute navKey msg model =
|
||||||
case msg of
|
case msg of
|
||||||
NoOp ->
|
NoOp ->
|
||||||
( model
|
( model
|
||||||
|
@ -193,7 +205,7 @@ update path navKey msg model =
|
||||||
in
|
in
|
||||||
( { model | sort = sort }
|
( { model | sort = sort }
|
||||||
, createUrl
|
, createUrl
|
||||||
path
|
toRoute
|
||||||
model.channel
|
model.channel
|
||||||
model.query
|
model.query
|
||||||
model.show
|
model.show
|
||||||
|
@ -218,7 +230,7 @@ update path navKey msg model =
|
||||||
|
|
||||||
else
|
else
|
||||||
createUrl
|
createUrl
|
||||||
path
|
toRoute
|
||||||
channel
|
channel
|
||||||
model.query
|
model.query
|
||||||
model.show
|
model.show
|
||||||
|
@ -240,7 +252,7 @@ update path navKey msg model =
|
||||||
else
|
else
|
||||||
( { model | result = RemoteData.Loading }
|
( { model | result = RemoteData.Loading }
|
||||||
, createUrl
|
, createUrl
|
||||||
path
|
toRoute
|
||||||
model.channel
|
model.channel
|
||||||
model.query
|
model.query
|
||||||
model.show
|
model.show
|
||||||
|
@ -258,7 +270,7 @@ update path navKey msg model =
|
||||||
ShowDetails selected ->
|
ShowDetails selected ->
|
||||||
( model
|
( model
|
||||||
, createUrl
|
, createUrl
|
||||||
path
|
toRoute
|
||||||
model.channel
|
model.channel
|
||||||
model.query
|
model.query
|
||||||
(if model.show == Just selected then
|
(if model.show == Just selected then
|
||||||
|
@ -275,8 +287,10 @@ update path navKey msg model =
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
{-| TODO: Sort should be part of Route type
|
||||||
|
-}
|
||||||
createUrl :
|
createUrl :
|
||||||
String
|
SearchRoute
|
||||||
-> String
|
-> String
|
||||||
-> Maybe String
|
-> Maybe String
|
||||||
-> Maybe String
|
-> Maybe String
|
||||||
|
@ -284,30 +298,9 @@ createUrl :
|
||||||
-> Int
|
-> Int
|
||||||
-> Sort
|
-> Sort
|
||||||
-> String
|
-> String
|
||||||
createUrl path channel query show from size sort =
|
createUrl toRoute channel query show from size sort =
|
||||||
[ Url.Builder.int "from" from
|
toRoute (Just channel) query show (Just from) (Just size) (Just <| toSortId sort)
|
||||||
, Url.Builder.int "size" size
|
|> Route.routeToString
|
||||||
, Url.Builder.string "sort" <| toSortId sort
|
|
||||||
, Url.Builder.string "channel" channel
|
|
||||||
]
|
|
||||||
|> List.append
|
|
||||||
(query
|
|
||||||
|> Maybe.map
|
|
||||||
(\x ->
|
|
||||||
[ Url.Builder.string "query" x ]
|
|
||||||
)
|
|
||||||
|> Maybe.withDefault []
|
|
||||||
)
|
|
||||||
|> List.append
|
|
||||||
(show
|
|
||||||
|> Maybe.map
|
|
||||||
(\x ->
|
|
||||||
[ Url.Builder.string "show" x
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|> Maybe.withDefault []
|
|
||||||
)
|
|
||||||
|> Url.Builder.absolute [ path ]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -320,6 +313,7 @@ type Channel
|
||||||
| Release_20_03
|
| Release_20_03
|
||||||
| Release_20_09
|
| Release_20_09
|
||||||
|
|
||||||
|
|
||||||
type alias ChannelDetails =
|
type alias ChannelDetails =
|
||||||
{ id : String
|
{ id : String
|
||||||
, title : String
|
, title : String
|
||||||
|
@ -455,13 +449,15 @@ fromSortId id =
|
||||||
|
|
||||||
|
|
||||||
view :
|
view :
|
||||||
String
|
{ toRoute : SearchRoute
|
||||||
|
, categoryName : String
|
||||||
|
}
|
||||||
-> String
|
-> String
|
||||||
-> Model a
|
-> Model a
|
||||||
-> (String -> Maybe String -> SearchResult a -> Html b)
|
-> (String -> Maybe String -> SearchResult a -> Html b)
|
||||||
-> (Msg a -> b)
|
-> (Msg a -> b)
|
||||||
-> Html b
|
-> Html b
|
||||||
view path title model viewSuccess outMsg =
|
view { toRoute, categoryName } title model viewSuccess outMsg =
|
||||||
div
|
div
|
||||||
[ class "search-page"
|
[ class "search-page"
|
||||||
]
|
]
|
||||||
|
@ -520,14 +516,15 @@ view path title model viewSuccess outMsg =
|
||||||
[ type_ "text"
|
[ type_ "text"
|
||||||
, id "search-query-input"
|
, id "search-query-input"
|
||||||
, autofocus True
|
, autofocus True
|
||||||
, placeholder <| "Search for " ++ path
|
, placeholder <| "Search for " ++ categoryName
|
||||||
, onInput (\x -> outMsg (QueryInput x))
|
, onInput (outMsg << QueryInput)
|
||||||
, value <| Maybe.withDefault "" model.query
|
, value <| Maybe.withDefault "" model.query
|
||||||
]
|
]
|
||||||
[]
|
[]
|
||||||
, div [ class "loader" ] []
|
, div [ class "loader" ] []
|
||||||
, div [ class "btn-group" ]
|
, div [ class "btn-group" ]
|
||||||
[ button [ class "btn" ] [ text "Search" ]
|
[ button [ class "btn", type_ "submit" ]
|
||||||
|
[ text "Search" ]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
@ -542,8 +539,7 @@ view path title model viewSuccess outMsg =
|
||||||
RemoteData.Success result ->
|
RemoteData.Success result ->
|
||||||
if result.hits.total.value == 0 then
|
if result.hits.total.value == 0 then
|
||||||
div []
|
div []
|
||||||
[ h4 [] [ text <| "No " ++ path ++ " found!" ]
|
[ h4 [] [ text <| "No " ++ categoryName ++ " found!" ] ]
|
||||||
]
|
|
||||||
|
|
||||||
else
|
else
|
||||||
div []
|
div []
|
||||||
|
@ -594,9 +590,9 @@ view path title model viewSuccess outMsg =
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
, viewPager outMsg model result path
|
, viewPager outMsg model result toRoute
|
||||||
, viewSuccess model.channel model.show result
|
, viewSuccess model.channel model.show result
|
||||||
, viewPager outMsg model result path
|
, viewPager outMsg model result toRoute
|
||||||
]
|
]
|
||||||
|
|
||||||
RemoteData.Failure error ->
|
RemoteData.Failure error ->
|
||||||
|
@ -629,9 +625,9 @@ viewPager :
|
||||||
(Msg a -> b)
|
(Msg a -> b)
|
||||||
-> Model a
|
-> Model a
|
||||||
-> SearchResult a
|
-> SearchResult a
|
||||||
-> String
|
-> SearchRoute
|
||||||
-> Html b
|
-> Html b
|
||||||
viewPager _ model result path =
|
viewPager _ model result toRoute =
|
||||||
ul [ class "pager" ]
|
ul [ class "pager" ]
|
||||||
[ li
|
[ li
|
||||||
[ classList
|
[ classList
|
||||||
|
@ -645,7 +641,7 @@ viewPager _ model result path =
|
||||||
else
|
else
|
||||||
href <|
|
href <|
|
||||||
createUrl
|
createUrl
|
||||||
path
|
toRoute
|
||||||
model.channel
|
model.channel
|
||||||
model.query
|
model.query
|
||||||
model.show
|
model.show
|
||||||
|
@ -667,7 +663,7 @@ viewPager _ model result path =
|
||||||
|
|
||||||
else
|
else
|
||||||
createUrl
|
createUrl
|
||||||
path
|
toRoute
|
||||||
model.channel
|
model.channel
|
||||||
model.query
|
model.query
|
||||||
model.show
|
model.show
|
||||||
|
@ -689,7 +685,7 @@ viewPager _ model result path =
|
||||||
|
|
||||||
else
|
else
|
||||||
createUrl
|
createUrl
|
||||||
path
|
toRoute
|
||||||
model.channel
|
model.channel
|
||||||
model.query
|
model.query
|
||||||
model.show
|
model.show
|
||||||
|
@ -719,7 +715,7 @@ viewPager _ model result path =
|
||||||
0
|
0
|
||||||
in
|
in
|
||||||
createUrl
|
createUrl
|
||||||
path
|
toRoute
|
||||||
model.channel
|
model.channel
|
||||||
model.query
|
model.query
|
||||||
model.show
|
model.show
|
||||||
|
|
Loading…
Reference in a new issue