From cc5e4a540d7bbe387b5d07ad843ecb6cd3da44d0 Mon Sep 17 00:00:00 2001 From: Rok Garbas Date: Fri, 10 Jul 2020 09:49:43 +0200 Subject: [PATCH] Allow to show results alphabetically (#133) fixed #119 --- src/Main.elm | 9 +-- src/Page/Options.elm | 10 +-- src/Page/Packages.elm | 10 +-- src/Route.elm | 12 ++-- src/Search.elm | 158 ++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 178 insertions(+), 21 deletions(-) diff --git a/src/Main.elm b/src/Main.elm index 80540d5..c095d52 100644 --- a/src/Main.elm +++ b/src/Main.elm @@ -127,6 +127,7 @@ submitQuery old ( new, cmd ) = (Maybe.withDefault "" newModel.query) newModel.from newModel.size + newModel.sort |> Cmd.map msg ] ) @@ -183,7 +184,7 @@ changeRouteTo model url = -- on the home page ( newModel, Browser.Navigation.pushUrl newModel.navKey "/packages" ) - Just (Route.Packages channel query show from size) -> + Just (Route.Packages channel query show from size sort) -> let modelPage = case newModel.page of @@ -193,11 +194,11 @@ changeRouteTo model url = _ -> Nothing in - Page.Packages.init channel query show from size modelPage + Page.Packages.init channel query show from size sort modelPage |> updateWith Packages PackagesMsg newModel |> submitQuery newModel - Just (Route.Options channel query show from size) -> + Just (Route.Options channel query show from size sort) -> let modelPage = case newModel.page of @@ -207,7 +208,7 @@ changeRouteTo model url = _ -> Nothing in - Page.Options.init channel query show from size modelPage + Page.Options.init channel query show from size sort modelPage |> updateWith Options OptionsMsg newModel |> submitQuery newModel diff --git a/src/Page/Options.elm b/src/Page/Options.elm index f25f3b5..92fcab7 100644 --- a/src/Page/Options.elm +++ b/src/Page/Options.elm @@ -73,12 +73,13 @@ init : -> Maybe String -> Maybe Int -> Maybe Int + -> Maybe String -> Maybe Model -> ( Model, Cmd Msg ) -init channel query show from size model = +init channel query show from size sort model = let ( newModel, newCmd ) = - Search.init channel query show from size model + Search.init channel query show from size sort model in ( newModel , Cmd.map SearchMsg newCmd @@ -285,8 +286,9 @@ makeRequest : -> String -> Int -> Int + -> Search.Sort -> Cmd Msg -makeRequest options channel queryRaw from size = +makeRequest options channel queryRaw from size sort = let query = queryRaw @@ -402,7 +404,7 @@ makeRequest options channel queryRaw from size = |> List.append (should_match 10) in Search.makeRequest - (Search.makeRequestBody query from size "option" "option_name_query" should_queries) + (Search.makeRequestBody query from size sort "option" "option_name" "option_name_query" should_queries) ("latest-" ++ String.fromInt options.mappingSchemaVersion ++ "-" ++ channel) decodeResultItemSource options diff --git a/src/Page/Packages.elm b/src/Page/Packages.elm index 8f1ad3d..bdc948d 100644 --- a/src/Page/Packages.elm +++ b/src/Page/Packages.elm @@ -108,12 +108,13 @@ init : -> Maybe String -> Maybe Int -> Maybe Int + -> Maybe String -> Maybe Model -> ( Model, Cmd Msg ) -init channel query show from size model = +init channel query show from size sort model = let ( newModel, newCmd ) = - Search.init channel query show from size model + Search.init channel query show from size sort model in ( newModel , Cmd.map SearchMsg newCmd @@ -381,8 +382,9 @@ makeRequest : -> String -> Int -> Int + -> Search.Sort -> Cmd Msg -makeRequest options channel queryRaw from size = +makeRequest options channel queryRaw from size sort = let query = queryRaw @@ -504,7 +506,7 @@ makeRequest options channel queryRaw from size = |> List.append (should_match 10) in Search.makeRequest - (Search.makeRequestBody query from size "package" "package_attr_name_query" should_queries) + (Search.makeRequestBody query from size sort "package" "package_attr_name" "package_attr_name_query" should_queries) ("latest-" ++ String.fromInt options.mappingSchemaVersion ++ "-" ++ channel) decodeResultItemSource options diff --git a/src/Route.elm b/src/Route.elm index b790d1a..29e19ec 100644 --- a/src/Route.elm +++ b/src/Route.elm @@ -15,8 +15,8 @@ import Url.Parser.Query type Route = NotFound | Home - | Packages (Maybe String) (Maybe String) (Maybe String) (Maybe Int) (Maybe Int) - | Options (Maybe String) (Maybe String) (Maybe String) (Maybe Int) (Maybe Int) + | 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) parser : Url.Parser.Parser (Route -> msg) msg @@ -36,6 +36,7 @@ parser = Url.Parser.Query.string "show" Url.Parser.Query.int "from" Url.Parser.Query.int "size" + Url.Parser.Query.string "sort" ) , Url.Parser.map Options @@ -45,6 +46,7 @@ parser = Url.Parser.Query.string "show" Url.Parser.Query.int "from" Url.Parser.Query.int "size" + Url.Parser.Query.string "sort" ) ] @@ -94,22 +96,24 @@ routeToPieces page = NotFound -> ( [ "not-found" ], [] ) - Packages channel query show from size -> + Packages channel query show from size sort -> ( [ "packages" ] , [ channel , query , show , Maybe.map String.fromInt from , Maybe.map String.fromInt size + , sort ] ) - Options channel query show from size -> + Options channel query show from size sort -> ( [ "options" ] , [ channel , query , show , Maybe.map String.fromInt from , Maybe.map String.fromInt size + , sort ] ) diff --git a/src/Search.elm b/src/Search.elm index fc01512..41ce53a 100644 --- a/src/Search.elm +++ b/src/Search.elm @@ -4,8 +4,10 @@ module Search exposing , Options , ResultItem , SearchResult + , Sort(..) , channelDetailsFromId , decodeResult + , fromSortId , init , makeRequest , makeRequestBody @@ -30,8 +32,11 @@ import Html , h1 , h4 , input + , label , li + , option , p + , select , strong , text , ul @@ -46,6 +51,7 @@ import Html.Attributes , href , id , placeholder + , selected , type_ , value ) @@ -76,6 +82,7 @@ type alias Model a = , show : Maybe String , from : Int , size : Int + , sort : Sort } @@ -114,22 +121,29 @@ type alias ResultHitsTotal = type alias ResultItem a = { index : String , id : String - , score : Float + , score : Maybe Float , source : a , text : Maybe String , matched_queries : Maybe (List String) } +type Sort + = Relevance + | AlphabeticallyAsc + | 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 model = +init channel query show from size sort model = let defaultChannel = model @@ -173,6 +187,11 @@ init channel query show from size model = , show = show , from = Maybe.withDefault defaultFrom from , size = Maybe.withDefault defaultSize size + , sort = + sort + |> Maybe.withDefault "" + |> fromSortId + |> Maybe.withDefault Relevance } , Browser.Dom.focus "search-query-input" |> Task.attempt (\_ -> NoOp) ) @@ -186,6 +205,7 @@ init channel query show from size model = type Msg a = NoOp + | SortChange String | ChannelChange String | QueryInputDebounce (Debouncer.Messages.Msg (Msg a)) | QueryInput String @@ -221,6 +241,23 @@ update path navKey result_type options decodeResultItemSource msg model = , Cmd.none ) + SortChange sortId -> + let + sort = + fromSortId sortId |> Maybe.withDefault Relevance + in + ( { model | sort = sort } + , createUrl + path + model.channel + model.query + model.show + 0 + model.size + sort + |> Browser.Navigation.pushUrl navKey + ) + ChannelChange channel -> ( { model | channel = channel @@ -242,6 +279,7 @@ update path navKey result_type options decodeResultItemSource msg model = model.show 0 model.size + model.sort |> Browser.Navigation.pushUrl navKey ) @@ -349,6 +387,7 @@ update path navKey result_type options decodeResultItemSource msg model = model.show 0 model.size + model.sort |> Browser.Navigation.pushUrl navKey ) @@ -371,6 +410,7 @@ update path navKey result_type options decodeResultItemSource msg model = ) model.from model.size + model.sort |> Browser.Navigation.pushUrl navKey ) @@ -531,10 +571,12 @@ createUrl : -> Maybe String -> Int -> Int + -> Sort -> String -createUrl path channel query show from size = +createUrl path channel query show from size sort = [ Url.Builder.int "from" from , Url.Builder.int "size" size + , Url.Builder.string "sort" <| toSortId sort , Url.Builder.string "channel" channel ] |> List.append @@ -618,6 +660,82 @@ channels = ] +sortBy : List Sort +sortBy = + [ Relevance + , AlphabeticallyAsc + , AlphabeticallyDesc + ] + + +toSortQuery : + Sort + -> String + -> ( String, Json.Encode.Value ) +toSortQuery sort field = + ( "sort" + , case sort of + AlphabeticallyAsc -> + Json.Encode.list Json.Encode.object + [ [ ( field, Json.Encode.string "asc" ) + ] + ] + + AlphabeticallyDesc -> + Json.Encode.list Json.Encode.object + [ [ ( field, Json.Encode.string "desc" ) + ] + ] + + Relevance -> + Json.Encode.list Json.Encode.string + [ "_score" + ] + ) + + +toSortTitle : Sort -> String +toSortTitle sort = + case sort of + AlphabeticallyAsc -> + "Alphabetically Ascending" + + AlphabeticallyDesc -> + "Alphabetically Descending" + + Relevance -> + "Relevance" + + +toSortId : Sort -> String +toSortId sort = + case sort of + AlphabeticallyAsc -> + "alpha_asc" + + AlphabeticallyDesc -> + "alpha_desc" + + Relevance -> + "relevance" + + +fromSortId : String -> Maybe Sort +fromSortId id = + case id of + "alpha_asc" -> + Just AlphabeticallyAsc + + "alpha_desc" -> + Just AlphabeticallyDesc + + "relevance" -> + Just Relevance + + _ -> + Nothing + + getSuggestions : Maybe String -> RemoteData.WebData (SearchResult a) @@ -840,6 +958,29 @@ view path title model viewSuccess outMsg = ) ] ] + , form [ class "form-horizontal pull-right" ] + [ div + [ class "control-group" + ] + [ label [ class "control-label" ] [ text "Sort by:" ] + , div + [ class "controls" ] + [ select + [ onInput (\x -> outMsg (SortChange x)) + ] + (List.map + (\sort -> + option + [ selected (model.sort == sort) + , value (toSortId sort) + ] + [ text <| toSortTitle sort ] + ) + sortBy + ) + ] + ] + ] , viewPager outMsg model result path , viewSuccess model.channel model.show result , viewPager outMsg model result path @@ -897,6 +1038,7 @@ viewPager _ model result path = model.show 0 model.size + model.sort ] [ text "First" ] ] @@ -918,6 +1060,7 @@ viewPager _ model result path = model.show (model.from - model.size) model.size + model.sort ] [ text "Previous" ] ] @@ -939,6 +1082,7 @@ viewPager _ model result path = model.show (model.from + model.size) model.size + model.sort ] [ text "Next" ] ] @@ -968,6 +1112,7 @@ viewPager _ model result path = model.show (((result.hits.total.value // model.size) - remainder) * model.size) model.size + model.sort ] [ text "Last" ] ] @@ -1074,11 +1219,13 @@ makeRequestBody : String -> Int -> Int + -> Sort + -> String -> String -> String -> List (List ( String, Json.Encode.Value )) -> Http.Body -makeRequestBody query from sizeRaw type_ query_field should_queries = +makeRequestBody query from sizeRaw sort type_ sort_field query_field should_queries = let -- you can not request more then 10000 results otherwise it will return 404 size = @@ -1096,6 +1243,7 @@ makeRequestBody query from sizeRaw type_ query_field should_queries = , ( "size" , Json.Encode.int size ) + , toSortQuery sort sort_field , ( "query" , Json.Encode.object [ ( "bool" @@ -1191,7 +1339,7 @@ decodeResultItem decodeResultItemSource = Json.Decode.map6 ResultItem (Json.Decode.field "_index" Json.Decode.string) (Json.Decode.field "_id" Json.Decode.string) - (Json.Decode.field "_score" Json.Decode.float) + (Json.Decode.field "_score" (Json.Decode.nullable Json.Decode.float)) (Json.Decode.field "_source" decodeResultItemSource) (Json.Decode.maybe (Json.Decode.field "text" Json.Decode.string)) (Json.Decode.maybe (Json.Decode.field "matched_queries" (Json.Decode.list Json.Decode.string)))