From 44cbea8547fcd1735e0afa10d3ce0c03d7b751e2 Mon Sep 17 00:00:00 2001 From: Rok Garbas Date: Fri, 24 Jul 2020 23:01:16 +0200 Subject: [PATCH] remove suggestions feature (#141) --- VERSION | 2 +- elm-srcs.nix | 20 - elm.json | 74 ++-- flake.lock | 26 +- import-scripts/import_scripts/channel.py | 37 -- import-scripts/tests/Example.elm | 52 --- import-scripts/tests/test_channel.py | 36 -- src/Main.elm | 4 +- src/Page/Home.elm | 6 +- src/Page/Options.elm | 22 +- src/Page/Packages.elm | 13 +- src/Search.elm | 453 +---------------------- src/index.scss | 48 --- versions.dat | Bin 0 -> 127368 bytes 14 files changed, 78 insertions(+), 715 deletions(-) delete mode 100644 import-scripts/tests/Example.elm diff --git a/VERSION b/VERSION index ec63514..f599e28 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9 +10 diff --git a/elm-srcs.nix b/elm-srcs.nix index 2cb6b94..30a6fc4 100644 --- a/elm-srcs.nix +++ b/elm-srcs.nix @@ -10,11 +10,6 @@ version = "1.1.3"; }; - "ohanhi/keyboard" = { - sha256 = "10sbq8v2kydnc3lkydl367g36q2b0xizxl031xyakrgl4zlh07ic"; - version = "2.0.1"; - }; - "truqu/elm-base64" = { sha256 = "12w68b4idbs2vn0gm0lj354pm745jb7n0fj69408mpvh5r1z4m1b"; version = "2.0.4"; @@ -35,16 +30,6 @@ version = "1.0.2"; }; - "Gizra/elm-debouncer" = { - sha256 = "009yw0rb418ar2a458ilr25m8gxrxsv5nvs3ld3l6sy12v12n0yn"; - version = "2.0.0"; - }; - - "Skinney/keyboard-events" = { - sha256 = "10qjlpa4byk78sra071w4ghc7b9p2brnppx7aqyy9cmbrmp5nf86"; - version = "2.0.1"; - }; - "elm/core" = { sha256 = "0gyk7lx3b6vx2jlfbxdsb4xffn0wdvg5yxldq50jr2kk5dzc2prj"; version = "1.0.4"; @@ -90,11 +75,6 @@ version = "1.1.0"; }; - "elm-community/list-extra" = { - sha256 = "1rvr1c8cfb3dwf3li17l9ziax6d1fshkliasspnw6rviva38lw34"; - version = "8.2.4"; - }; - "elm/time" = { sha256 = "0vch7i86vn0x8b850w1p69vplll1bnbkp8s383z7pinyg94cm2z1"; version = "1.0.0"; diff --git a/elm.json b/elm.json index abdd889..4963cd0 100644 --- a/elm.json +++ b/elm.json @@ -1,43 +1,39 @@ { - "type": "application", - "source-directories": [ - "src" - ], - "elm-version": "0.19.1", - "dependencies": { - "direct": { - "Gizra/elm-debouncer": "2.0.0", - "NoRedInk/elm-json-decode-pipeline": "1.0.0", - "Skinney/keyboard-events": "2.0.1", - "elm/browser": "1.0.2", - "elm/core": "1.0.4", - "elm/html": "1.0.0", - "elm/http": "2.0.0", - "elm/json": "1.1.3", - "elm/regex": "1.0.0", - "elm/url": "1.0.0", - "hecrj/html-parser": "2.3.4", - "krisajenkins/remotedata": "6.0.1", - "ohanhi/keyboard": "2.0.1", - "truqu/elm-base64": "2.0.4" - }, - "indirect": { - "elm/bytes": "1.0.8", - "elm/file": "1.0.5", - "elm/parser": "1.1.0", - "elm/time": "1.0.0", - "elm/virtual-dom": "1.0.2", - "elm-community/list-extra": "8.2.4", - "rtfeldman/elm-hex": "1.0.0" - } + "type": "application", + "source-directories": [ + "src" + ], + "elm-version": "0.19.1", + "dependencies": { + "direct": { + "NoRedInk/elm-json-decode-pipeline": "1.0.0", + "elm/browser": "1.0.2", + "elm/core": "1.0.4", + "elm/html": "1.0.0", + "elm/http": "2.0.0", + "elm/json": "1.1.3", + "elm/regex": "1.0.0", + "elm/url": "1.0.0", + "hecrj/html-parser": "2.3.4", + "krisajenkins/remotedata": "6.0.1", + "truqu/elm-base64": "2.0.4" }, - "test-dependencies": { - "direct": { - "elm-explorations/test": "1.2.2" - }, - "indirect": { - "elm/random": "1.0.0", - "elm/svg": "1.0.1" - } + "indirect": { + "elm/bytes": "1.0.8", + "elm/file": "1.0.5", + "elm/parser": "1.1.0", + "elm/time": "1.0.0", + "elm/virtual-dom": "1.0.2", + "rtfeldman/elm-hex": "1.0.0" } + }, + "test-dependencies": { + "direct": { + "elm-explorations/test": "1.2.2" + }, + "indirect": { + "elm/random": "1.0.0", + "elm/svg": "1.0.1" + } + } } diff --git a/flake.lock b/flake.lock index 802ad5a..4fd260e 100644 --- a/flake.lock +++ b/flake.lock @@ -1,14 +1,12 @@ { "nodes": { "nixpkgs": { - "info": { - "lastModified": 1592376843, - "narHash": "sha256-vKchUGsNMQC9vCmTnpssHMV/+cKXA5QhbEoFm0zua1U=" - }, "locked": { + "lastModified": 1595175601, + "narHash": "sha256-NMxaD3mdKyp+6nidFkZe7XOzVXtWMpOH1v4KYZxo/Z0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "14fcd947a0150b78d7a37bef56c87fcd57808247", + "rev": "5717d9d2f7ca0662291910c52f1d7b95b568fec2", "type": "github" }, "original": { @@ -18,14 +16,12 @@ } }, "nixpkgs_2": { - "info": { - "lastModified": 1592514044, - "narHash": "sha256-jGQJmq14vh9ASt9d5Z9yBPsrbUgroiNVNhsoBabsw0k=" - }, "locked": { + "lastModified": 1595619256, + "narHash": "sha256-TOSvHwfQevzE/uTFBWYAt1I/F9F3YRkOV8gUrqUQfkk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e051dab9ff8a58455f6b8375856ac2802c6cd261", + "rev": "fd0febffda9af90d6d369ecb4cb9aaf347116bce", "type": "github" }, "original": { @@ -34,17 +30,15 @@ } }, "poetry2nix": { - "info": { - "lastModified": 1592121810, - "narHash": "sha256-9cGTKtL7JpllwABxa4iRVU4Qw/YwniLni4RATyONz+s=" - }, "inputs": { "nixpkgs": "nixpkgs_2" }, "locked": { + "lastModified": 1595517229, + "narHash": "sha256-5eMk3+Twb2fDyFX5sm33JYSRaPAvKe9vHV5w/HjbiHs=", "owner": "nix-community", "repo": "poetry2nix", - "rev": "e7c69a288c10e4d97816fdabda5ae3f38e21914e", + "rev": "270a0b26b773e566ad59927c51d40a5e9b8ff08d", "type": "github" }, "original": { @@ -61,5 +55,5 @@ } }, "root": "root", - "version": 5 + "version": 7 } diff --git a/import-scripts/import_scripts/channel.py b/import-scripts/import_scripts/channel.py index 827cb8c..01cc8e2 100644 --- a/import-scripts/import_scripts/channel.py +++ b/import-scripts/import_scripts/channel.py @@ -16,7 +16,6 @@ import shlex import subprocess import sys import tqdm # type: ignore -import typing import xml.etree.ElementTree logger = logging.getLogger("import-channel") @@ -47,12 +46,6 @@ MAPPING = { "properties": { "type": {"type": "keyword"}, # Package fields - "package_suggestions": { - "type": "completion", - "analyzer": "lowercase", - "search_analyzer": "lowercase", - "preserve_position_increments": False, - }, "package_hydra_build": { "type": "nested", "properties": { @@ -96,12 +89,6 @@ MAPPING = { "package_homepage": {"type": "keyword"}, "package_system": {"type": "keyword"}, # Options fields - "option_suggestions": { - "type": "completion", - "analyzer": "lowercase", - "search_analyzer": "lowercase", - "preserve_position_increments": False, - }, "option_name": {"type": "keyword", "normalizer": "lowercase"}, "option_name_query": {"type": "keyword", "normalizer": "lowercase"}, "option_description": {"type": "text"}, @@ -113,28 +100,6 @@ MAPPING = { } -def parse_suggestions(text: str) -> typing.List[typing.Dict[str, object]]: - """Tokenize option_name - - Example: - - services.nginx.extraConfig - - services.nginx.extraConfig - - services.nginx. - - services. - """ - results: typing.List[typing.Dict[str, object]] = [ - {"input": text, "weight": 1000 - (((len(text.split(".")) - 1) * 10))}, - ] - for i in range(len(text.split(".")) - 1): - result = { - "input": ".".join(text.split(".")[: -(i + 1)]) + ".", - "weight": 1000 - ((len(text.split(".")) - 2 - i) * 10) + 1, - } - results.append(result) - return results - - def parse_query(text): """Tokenize package attr_name @@ -371,7 +336,6 @@ def get_packages(evaluation, evaluation_builds): yield dict( type="package", - package_suggestions=parse_suggestions(attr_name), package_hydra=hydra, package_attr_name=attr_name, package_attr_name_query=list(parse_query(attr_name)), @@ -438,7 +402,6 @@ def get_options(evaluation): yield dict( type="option", - option_suggestions=parse_suggestions(name), option_name=name, option_name_query=parse_query(name), option_description=description, diff --git a/import-scripts/tests/Example.elm b/import-scripts/tests/Example.elm deleted file mode 100644 index 1bcd7b0..0000000 --- a/import-scripts/tests/Example.elm +++ /dev/null @@ -1,52 +0,0 @@ -module Example exposing (fuzzTest, unitTest, viewTest) - -import Expect exposing (Expectation) -import Fuzz exposing (Fuzzer, int, list, string) -import Main exposing (..) -import Test exposing (..) -import Test.Html.Query as Query -import Test.Html.Selector exposing (tag, text) - - -{-| See --} -unitTest : Test -unitTest = - describe "simple unit test" - [ test "Inc adds one" <| - \() -> - update Inc (Model 0 "") - |> Tuple.first - |> .counter - |> Expect.equal 1 - ] - - -{-| See --} -fuzzTest : Test -fuzzTest = - describe "simple fuzz test" - [ fuzz int "Inc ALWAYS adds one" <| - \ct -> - update Inc (Model ct "") - |> Tuple.first - |> .counter - |> Expect.equal (ct + 1) - ] - - -{-| see --} -viewTest : Test -viewTest = - describe "Testing view function" - [ test "Button has the expected text" <| - \() -> - Model 0 "" - |> view - |> Query.fromHtml - |> Query.findAll [ tag "button" ] - |> Query.first - |> Query.has [ text "+ 1" ] - ] diff --git a/import-scripts/tests/test_channel.py b/import-scripts/tests/test_channel.py index cab755e..6cf4568 100644 --- a/import-scripts/tests/test_channel.py +++ b/import-scripts/tests/test_channel.py @@ -1,42 +1,6 @@ import pytest # type: ignore -@pytest.mark.parametrize( - "text,expected", - [ - ( - "services.grafana.analytics.reporting.enable", - [ - {"input": "services.grafana.analytics.reporting.enable", "weight": 960}, - {"input": "services.grafana.analytics.reporting.", "weight": 971}, - {"input": "services.grafana.analytics.", "weight": 981}, - {"input": "services.grafana.", "weight": 991}, - {"input": "services.", "weight": 1001}, - ], - ), - ( - "services.nginx.extraConfig", - [ - {"input": "services.nginx.extraConfig", "weight": 980}, - {"input": "services.nginx.", "weight": 991}, - {"input": "services.", "weight": 1001}, - ], - ), - ( - "python37Packages.test1_name-test2", - [ - {"input": "python37Packages.test1_name-test2", "weight": 990}, - {"input": "python37Packages.", "weight": 1001}, - ], - ), - ], -) -def test_parse_suggestions(text, expected): - import import_scripts.channel - - assert import_scripts.channel.parse_suggestions(text) == expected - - @pytest.mark.parametrize( "text,expected", [ diff --git a/src/Main.elm b/src/Main.elm index c095d52..14ef30a 100644 --- a/src/Main.elm +++ b/src/Main.elm @@ -240,11 +240,11 @@ update msg model = |> updateWith Home HomeMsg model ( PackagesMsg subMsg, Packages subModel ) -> - Page.Packages.update model.navKey model.elasticsearch subMsg subModel + Page.Packages.update model.navKey subMsg subModel |> updateWith Packages PackagesMsg model ( OptionsMsg subMsg, Options subModel ) -> - Page.Options.update model.navKey model.elasticsearch subMsg subModel + Page.Options.update model.navKey subMsg subModel |> updateWith Options OptionsMsg model ( _, _ ) -> diff --git a/src/Page/Home.elm b/src/Page/Home.elm index 4b83df7..757fd10 100644 --- a/src/Page/Home.elm +++ b/src/Page/Home.elm @@ -26,7 +26,9 @@ type Msg update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = - ( model, Cmd.none ) + case msg of + NoOp -> + ( model, Cmd.none ) @@ -34,5 +36,5 @@ update msg model = view : Model -> Html Msg -view model = +view _ = div [] [ text "Home" ] diff --git a/src/Page/Options.elm b/src/Page/Options.elm index 92fcab7..5e8926b 100644 --- a/src/Page/Options.elm +++ b/src/Page/Options.elm @@ -17,8 +17,6 @@ import Html , div , dl , dt - , li - , p , pre , span , table @@ -28,7 +26,6 @@ import Html , th , thead , tr - , ul ) import Html.Attributes exposing @@ -42,7 +39,6 @@ import Html.Events ) import Html.Parser import Html.Parser.Util -import Http import Json.Decode import Json.Encode import Regex @@ -94,8 +90,12 @@ type Msg = SearchMsg (Search.Msg ResultItemSource) -update : Browser.Navigation.Key -> Search.Options -> Msg -> Model -> ( Model, Cmd Msg ) -update navKey options msg model = +update : + Browser.Navigation.Key + -> Msg + -> Model + -> ( Model, Cmd Msg ) +update navKey msg model = case msg of SearchMsg subMsg -> let @@ -103,9 +103,6 @@ update navKey options msg model = Search.update "options" navKey - "option" - options - decodeResultItemSource subMsg model in @@ -211,9 +208,6 @@ viewResultItemDetails channel item = asCode value = pre [] [ text value ] - asLink value = - a [ href value ] [ text value ] - githubUrlPrefix branch = "https://github.com/NixOS/nixpkgs-channels/blob/" ++ branch ++ "/" @@ -305,7 +299,7 @@ makeRequest options channel queryRaw from size sort = [ ( field , Json.Encode.object [ ( "query", Json.Encode.string query ) - , ( "boost", Json.Encode.float boost ) + , ( "boost", Json.Encode.float <| boost_base * boost ) , ( "analyzer", Json.Encode.string "whitespace" ) , ( "fuzziness", Json.Encode.string "1" ) , ( "_name" @@ -332,7 +326,7 @@ makeRequest options channel queryRaw from size sort = [ ( field , Json.Encode.object [ ( "query", Json.Encode.string query ) - , ( "boost", Json.Encode.float boost ) + , ( "boost", Json.Encode.float <| boost_base * boost ) , ( "analyzer", Json.Encode.string "whitespace" ) , ( "fuzziness", Json.Encode.string "1" ) , ( "_name" diff --git a/src/Page/Packages.elm b/src/Page/Packages.elm index bdc948d..966ab9a 100644 --- a/src/Page/Packages.elm +++ b/src/Page/Packages.elm @@ -19,7 +19,6 @@ import Html , dl , dt , li - , p , table , tbody , td @@ -39,7 +38,6 @@ import Html.Events exposing ( onClick ) -import Http import Json.Decode import Json.Decode.Pipeline import Json.Encode @@ -129,8 +127,12 @@ type Msg = SearchMsg (Search.Msg ResultItemSource) -update : Browser.Navigation.Key -> Search.Options -> Msg -> Model -> ( Model, Cmd Msg ) -update navKey options msg model = +update : + Browser.Navigation.Key + -> Msg + -> Model + -> ( Model, Cmd Msg ) +update navKey msg model = case msg of SearchMsg subMsg -> let @@ -138,9 +140,6 @@ update navKey options msg model = Search.update "packages" navKey - "package" - options - decodeResultItemSource subMsg model in diff --git a/src/Search.elm b/src/Search.elm index 41ce53a..12e552a 100644 --- a/src/Search.elm +++ b/src/Search.elm @@ -15,12 +15,9 @@ module Search exposing , view ) -import Array import Base64 import Browser.Dom import Browser.Navigation -import Debouncer.Messages -import Dict import Html exposing ( Html @@ -44,7 +41,6 @@ import Html import Html.Attributes exposing ( attribute - , autocomplete , autofocus , class , classList @@ -57,16 +53,13 @@ import Html.Attributes ) import Html.Events exposing - ( custom - , onClick + ( onClick , onInput , onSubmit ) import Http import Json.Decode import Json.Encode -import Keyboard -import Keyboard.Events import RemoteData import Task import Url.Builder @@ -75,9 +68,6 @@ import Url.Builder type alias Model a = { channel : String , query : Maybe String - , queryDebounce : Debouncer.Messages.Debouncer (Msg a) - , querySuggest : RemoteData.WebData (SearchResult a) - , querySelectedSuggestion : Maybe String , result : RemoteData.WebData (SearchResult a) , show : Maybe String , from : Int @@ -88,20 +78,6 @@ type alias Model a = type alias SearchResult a = { hits : ResultHits a - , suggest : Maybe (SearchSuggest a) - } - - -type alias SearchSuggest a = - { query : Maybe (List (SearchSuggestQuery a)) - } - - -type alias SearchSuggestQuery a = - { text : String - , offset : Int - , length : Int - , options : List (ResultItem a) } @@ -161,25 +137,7 @@ init channel query show from size sort model = |> Maybe.withDefault 15 in ( { channel = Maybe.withDefault defaultChannel channel - , queryDebounce = - Debouncer.Messages.manual - |> Debouncer.Messages.settleWhenQuietFor (Just <| Debouncer.Messages.fromSeconds 0.4) - |> Debouncer.Messages.toDebouncer , query = query - , querySuggest = - query - |> Maybe.map - (\selected -> - if String.endsWith "." selected then - model - |> Maybe.map .querySuggest - |> Maybe.withDefault RemoteData.NotAsked - - else - RemoteData.NotAsked - ) - |> Maybe.withDefault RemoteData.NotAsked - , querySelectedSuggestion = Nothing , result = model |> Maybe.map (\x -> x.result) @@ -207,34 +165,19 @@ type Msg a = NoOp | SortChange String | ChannelChange String - | QueryInputDebounce (Debouncer.Messages.Msg (Msg a)) | QueryInput String - | QueryInputSuggestionsSubmit - | QueryInputSuggestionsResponse (RemoteData.WebData (SearchResult a)) | QueryInputSubmit | QueryResponse (RemoteData.WebData (SearchResult a)) | ShowDetails String - | SuggestionsMoveDown - | SuggestionsMoveUp - | SuggestionsSelect - | SuggestionsClickSelect String - | SuggestionsClose update : String -> Browser.Navigation.Key - -> String - -> Options - -> Json.Decode.Decoder a -> Msg a -> Model a -> ( Model a, Cmd (Msg a) ) -update path navKey result_type options decodeResultItemSource msg model = - let - requestQuerySuggestionsTracker = - "query-" ++ result_type ++ "-suggestions" - in +update path navKey msg model = case msg of NoOp -> ( model @@ -283,94 +226,8 @@ update path navKey result_type options decodeResultItemSource msg model = |> Browser.Navigation.pushUrl navKey ) - QueryInputDebounce subMsg -> - Debouncer.Messages.update - (update path navKey result_type options decodeResultItemSource) - { mapMsg = QueryInputDebounce - , getDebouncer = .queryDebounce - , setDebouncer = \debouncer m -> { m | queryDebounce = debouncer } - } - subMsg - model - QueryInput query -> - update path - navKey - result_type - options - decodeResultItemSource - (QueryInputDebounce (Debouncer.Messages.provideInput QueryInputSuggestionsSubmit)) - { model - | query = Just query - , querySuggest = RemoteData.Loading - , querySelectedSuggestion = Nothing - } - |> Tuple.mapSecond - (\cmd -> - if RemoteData.isLoading model.querySuggest then - Cmd.batch - [ cmd - , Http.cancel requestQuerySuggestionsTracker - ] - - else - cmd - ) - - QueryInputSuggestionsSubmit -> - let - body = - Http.jsonBody - (Json.Encode.object - [ ( "from", Json.Encode.int 0 ) - , ( "size", Json.Encode.int 0 ) - , ( "suggest" - , Json.Encode.object - [ ( "query" - , Json.Encode.object - [ ( "text", Json.Encode.string (Maybe.withDefault "" model.query) ) - , ( "completion" - , Json.Encode.object - [ ( "field", Json.Encode.string (result_type ++ "_suggestions") ) - , ( "skip_duplicates", Json.Encode.bool True ) - , ( "size", Json.Encode.int 1000 ) - ] - ) - ] - ) - ] - ) - ] - ) - in - ( { model - | querySuggest = - model.query - |> Maybe.map - (\selected -> - if String.endsWith "." selected then - model.querySuggest - - else - RemoteData.NotAsked - ) - |> Maybe.withDefault RemoteData.NotAsked - , querySelectedSuggestion = Nothing - } - , makeRequest - body - ("latest-" ++ String.fromInt options.mappingSchemaVersion ++ "-" ++ model.channel) - decodeResultItemSource - options - QueryInputSuggestionsResponse - (Just requestQuerySuggestionsTracker) - ) - - QueryInputSuggestionsResponse querySuggest -> - ( { model - | querySuggest = querySuggest - , querySelectedSuggestion = Nothing - } + ( { model | query = Just query } , Cmd.none ) @@ -414,155 +271,6 @@ update path navKey result_type options decodeResultItemSource msg model = |> Browser.Navigation.pushUrl navKey ) - SuggestionsMoveDown -> - ( { model - | querySelectedSuggestion = - getMovedSuggestion - model.query - model.querySuggest - model.querySelectedSuggestion - (\x -> x + 1) - } - , scrollToSelected "dropdown-menu" - ) - - SuggestionsMoveUp -> - ( { model - | querySelectedSuggestion = - getMovedSuggestion - model.query - model.querySuggest - model.querySelectedSuggestion - (\x -> x - 1) - } - , scrollToSelected "dropdown-menu" - ) - - SuggestionsSelect -> - case model.querySelectedSuggestion of - Just selected -> - update path - navKey - result_type - options - decodeResultItemSource - (SuggestionsClickSelect selected) - model - - Nothing -> - ( model - , Task.attempt (\_ -> QueryInputSubmit) (Task.succeed ()) - ) - - SuggestionsClickSelect selected -> - ( { model - | querySuggest = - if String.endsWith "." selected then - model.querySuggest - - else - RemoteData.NotAsked - , querySelectedSuggestion = Nothing - , query = Just selected - } - , Cmd.batch - [ Task.attempt (\_ -> QueryInputSuggestionsSubmit) (Task.succeed ()) - , Task.attempt (\_ -> QueryInputSubmit) (Task.succeed ()) - ] - ) - - SuggestionsClose -> - ( { model - | querySuggest = RemoteData.NotAsked - , querySelectedSuggestion = Nothing - } - , Cmd.none - ) - - -scrollToSelected : - String - -> Cmd (Msg a) -scrollToSelected id = - let - scroll y = - Browser.Dom.setViewportOf id 0 y - |> Task.onError (\_ -> Task.succeed ()) - in - Task.sequence - [ Browser.Dom.getElement (id ++ "-selected") - |> Task.map (\x -> ( x.element.y, x.element.height )) - , Browser.Dom.getElement id - |> Task.map (\x -> ( x.element.y, x.element.height )) - , Browser.Dom.getViewportOf id - |> Task.map (\x -> ( x.viewport.y, x.viewport.height )) - ] - |> Task.andThen - (\x -> - case x of - ( elementY, elementHeight ) :: ( viewportY, viewportHeight ) :: ( viewportScrollTop, _ ) :: [] -> - let - scrollTop = - scroll (viewportScrollTop + (elementY - viewportY)) - - scrollBottom = - scroll (viewportScrollTop + (elementY - viewportY) + (elementHeight - viewportHeight)) - in - if elementHeight > viewportHeight then - scrollTop - - else if elementY < viewportY then - scrollTop - - else if elementY + elementHeight > viewportY + viewportHeight then - scrollBottom - - else - Task.succeed () - - _ -> - Task.succeed () - ) - |> Task.attempt (\_ -> NoOp) - - -getMovedSuggestion : - Maybe String - -> RemoteData.WebData (SearchResult a) - -> Maybe String - -> (Int -> Int) - -> Maybe String -getMovedSuggestion query querySuggest querySelectedSuggestion moveIndex = - let - suggestions = - getSuggestions query querySuggest - |> List.filterMap .text - - getIndex key = - suggestions - |> List.indexedMap (\i a -> ( a, i )) - |> Dict.fromList - |> Dict.get key - |> Maybe.map moveIndex - |> Maybe.map - (\x -> - if x < 0 then - x + List.length suggestions - - else - x - ) - - getKey index = - suggestions - |> Array.fromList - |> Array.get index - in - querySelectedSuggestion - |> Maybe.andThen getIndex - |> Maybe.withDefault 0 - |> getKey - createUrl : String @@ -736,48 +444,6 @@ fromSortId id = Nothing -getSuggestions : - Maybe String - -> RemoteData.WebData (SearchResult a) - -> List (ResultItem a) -getSuggestions query querySuggest = - let - maybeList f x = - x - |> Maybe.map f - |> Maybe.withDefault [] - in - case querySuggest of - RemoteData.Success result -> - let - suggestions = - result.suggest - |> maybeList (\x -> x.query |> maybeList (List.map .options)) - |> List.concat - |> List.filter - (\x -> - if String.endsWith "." (Maybe.withDefault "" query) then - x.text /= query - - else - True - ) - - firstItemText items = - items - |> List.head - |> Maybe.andThen .text - in - if List.length suggestions == 1 && firstItemText suggestions == query then - [] - - else - suggestions - - _ -> - [] - - view : String -> String @@ -786,48 +452,10 @@ view : -> (Msg a -> b) -> Html b view path title model viewSuccess outMsg = - let - suggestions = - getSuggestions model.query model.querySuggest - - viewSuggestion x = - li - [] - [ a - ([ href "#" ] - |> List.append - (x.text - |> Maybe.map (\text -> [ onClick <| outMsg (SuggestionsClickSelect text) ]) - |> Maybe.withDefault [] - ) - |> List.append - (if x.text == model.querySelectedSuggestion then - [ id "dropdown-menu-selected" ] - - else - [] - ) - ) - [ text <| Maybe.withDefault "" x.text ] - ] - in div - [ classList - [ ( "search-page", True ) - , ( "with-suggestions", RemoteData.isSuccess model.querySuggest && List.length suggestions > 0 ) - , ( "with-suggestions-loading" - , (model.query /= Nothing) - && (model.query /= Just "") - && not (RemoteData.isSuccess model.querySuggest || RemoteData.isNotAsked model.querySuggest) - ) - ] + [ class "search-page" ] [ h1 [ class "page-header" ] [ text title ] - , div - [ class "search-backdrop" - , onClick <| outMsg SuggestionsClose - ] - [] , div [ class "search-input" ] @@ -863,60 +491,19 @@ view path title model viewSuccess outMsg = [ class "input-append" ] [ input - ([ type_ "text" - , id "search-query-input" - , autocomplete False - , autofocus True - , placeholder <| "Search for " ++ path - , onInput (\x -> outMsg (QueryInput x)) - , value <| Maybe.withDefault "" model.query - ] - |> List.append - (if RemoteData.isSuccess model.querySuggest && List.length suggestions > 0 then - [ Keyboard.Events.custom Keyboard.Events.Keydown - { preventDefault = True - , stopPropagation = True - } - ([ ( Keyboard.ArrowDown, SuggestionsMoveDown ) - , ( Keyboard.ArrowUp, SuggestionsMoveUp ) - , ( Keyboard.Tab, SuggestionsMoveDown ) - , ( Keyboard.Enter, SuggestionsSelect ) - , ( Keyboard.Escape, SuggestionsClose ) - ] - |> List.map (\( k, m ) -> ( k, outMsg m )) - ) - ] - - else if RemoteData.isNotAsked model.querySuggest then - [ Keyboard.Events.custom Keyboard.Events.Keydown - { preventDefault = True - , stopPropagation = True - } - ([ ( Keyboard.ArrowDown, QueryInputSuggestionsSubmit ) - , ( Keyboard.ArrowUp, QueryInputSuggestionsSubmit ) - ] - |> List.map (\( k, m ) -> ( k, outMsg m )) - ) - ] - - else - [] - ) - ) + [ type_ "text" + , id "search-query-input" + , autofocus True + , placeholder <| "Search for " ++ path + , onInput (\x -> outMsg (QueryInput x)) + , value <| Maybe.withDefault "" model.query + ] [] , div [ class "loader" ] [] , div [ class "btn-group" ] [ button [ class "btn" ] [ text "Search" ] ] ] - , ul - [ id "dropdown-menu", class "dropdown-menu" ] - (if RemoteData.isSuccess model.querySuggest && List.length suggestions > 0 then - List.map viewSuggestion suggestions - - else - [] - ) ] ] , case model.result of @@ -1299,24 +886,8 @@ decodeResult : Json.Decode.Decoder a -> Json.Decode.Decoder (SearchResult a) decodeResult decodeResultItemSource = - Json.Decode.map2 SearchResult + Json.Decode.map SearchResult (Json.Decode.field "hits" (decodeResultHits decodeResultItemSource)) - (Json.Decode.maybe (Json.Decode.field "suggest" (decodeSuggest decodeResultItemSource))) - - -decodeSuggest : Json.Decode.Decoder a -> Json.Decode.Decoder (SearchSuggest a) -decodeSuggest decodeResultItemSource = - Json.Decode.map SearchSuggest - (Json.Decode.maybe (Json.Decode.field "query" (Json.Decode.list (decodeSuggestQuery decodeResultItemSource)))) - - -decodeSuggestQuery : Json.Decode.Decoder a -> Json.Decode.Decoder (SearchSuggestQuery a) -decodeSuggestQuery decodeResultItemSource = - Json.Decode.map4 SearchSuggestQuery - (Json.Decode.field "text" Json.Decode.string) - (Json.Decode.field "offset" Json.Decode.int) - (Json.Decode.field "length" Json.Decode.int) - (Json.Decode.field "options" (Json.Decode.list (decodeResultItem decodeResultItemSource))) decodeResultHits : Json.Decode.Decoder a -> Json.Decode.Decoder (ResultHits a) diff --git a/src/index.scss b/src/index.scss index 93e831e..d7deb29 100644 --- a/src/index.scss +++ b/src/index.scss @@ -29,56 +29,8 @@ header .navbar.navbar-static-top { } } -.search-page.with-suggestions-loading { - .input-append div.loader { - display: block; - } -} -.search-page.with-suggestions { - ul.dropdown-menu { - display: block; - } - .input-append input { - border-radius: 4px 0 0 0; - } - .search-backdrop { - position: absolute; - width: 100%; - height: 100%; - top: 0; - left: 0; - z-index: 999; - } -} .search-input { - position: relative; - ul.dropdown-menu { - font-size: 18px; - width: 25.6em; - height: auto; - max-height: 200px; - border-radius: 0; - margin-top: -10px; - border-top: 0; - overflow-y: scroll; - li > a { - font-size: 14px; - } - li > a#dropdown-menu-selected { - color: #fff; - text-decoration: none; - background-color: #0081c2; - background-image: -moz-linear-gradient(top,#08c,#0077b3); - background-image: -webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3)); - background-image: -webkit-linear-gradient(top,#08c,#0077b3); - background-image: -o-linear-gradient(top,#08c,#0077b3); - background-image: linear-gradient(to bottom,#08c,#0077b3); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0); - } - } .input-append { - position: relative; input { font-size: 18px; height: 40px; diff --git a/versions.dat b/versions.dat index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b911b15b687930bdc190cfffe3198df303ca5ea6 100644 GIT binary patch literal 127368 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
>~T6{iPYiAmS=EB!R_P? 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 literal 0 HcmV?d00001