remove suggestions feature (#141)
This commit is contained in:
parent
3bf4907596
commit
44cbea8547
20
elm-srcs.nix
20
elm-srcs.nix
|
@ -10,11 +10,6 @@
|
||||||
version = "1.1.3";
|
version = "1.1.3";
|
||||||
};
|
};
|
||||||
|
|
||||||
"ohanhi/keyboard" = {
|
|
||||||
sha256 = "10sbq8v2kydnc3lkydl367g36q2b0xizxl031xyakrgl4zlh07ic";
|
|
||||||
version = "2.0.1";
|
|
||||||
};
|
|
||||||
|
|
||||||
"truqu/elm-base64" = {
|
"truqu/elm-base64" = {
|
||||||
sha256 = "12w68b4idbs2vn0gm0lj354pm745jb7n0fj69408mpvh5r1z4m1b";
|
sha256 = "12w68b4idbs2vn0gm0lj354pm745jb7n0fj69408mpvh5r1z4m1b";
|
||||||
version = "2.0.4";
|
version = "2.0.4";
|
||||||
|
@ -35,16 +30,6 @@
|
||||||
version = "1.0.2";
|
version = "1.0.2";
|
||||||
};
|
};
|
||||||
|
|
||||||
"Gizra/elm-debouncer" = {
|
|
||||||
sha256 = "009yw0rb418ar2a458ilr25m8gxrxsv5nvs3ld3l6sy12v12n0yn";
|
|
||||||
version = "2.0.0";
|
|
||||||
};
|
|
||||||
|
|
||||||
"Skinney/keyboard-events" = {
|
|
||||||
sha256 = "10qjlpa4byk78sra071w4ghc7b9p2brnppx7aqyy9cmbrmp5nf86";
|
|
||||||
version = "2.0.1";
|
|
||||||
};
|
|
||||||
|
|
||||||
"elm/core" = {
|
"elm/core" = {
|
||||||
sha256 = "0gyk7lx3b6vx2jlfbxdsb4xffn0wdvg5yxldq50jr2kk5dzc2prj";
|
sha256 = "0gyk7lx3b6vx2jlfbxdsb4xffn0wdvg5yxldq50jr2kk5dzc2prj";
|
||||||
version = "1.0.4";
|
version = "1.0.4";
|
||||||
|
@ -90,11 +75,6 @@
|
||||||
version = "1.1.0";
|
version = "1.1.0";
|
||||||
};
|
};
|
||||||
|
|
||||||
"elm-community/list-extra" = {
|
|
||||||
sha256 = "1rvr1c8cfb3dwf3li17l9ziax6d1fshkliasspnw6rviva38lw34";
|
|
||||||
version = "8.2.4";
|
|
||||||
};
|
|
||||||
|
|
||||||
"elm/time" = {
|
"elm/time" = {
|
||||||
sha256 = "0vch7i86vn0x8b850w1p69vplll1bnbkp8s383z7pinyg94cm2z1";
|
sha256 = "0vch7i86vn0x8b850w1p69vplll1bnbkp8s383z7pinyg94cm2z1";
|
||||||
version = "1.0.0";
|
version = "1.0.0";
|
||||||
|
|
74
elm.json
74
elm.json
|
@ -1,43 +1,39 @@
|
||||||
{
|
{
|
||||||
"type": "application",
|
"type": "application",
|
||||||
"source-directories": [
|
"source-directories": [
|
||||||
"src"
|
"src"
|
||||||
],
|
],
|
||||||
"elm-version": "0.19.1",
|
"elm-version": "0.19.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"direct": {
|
"direct": {
|
||||||
"Gizra/elm-debouncer": "2.0.0",
|
"NoRedInk/elm-json-decode-pipeline": "1.0.0",
|
||||||
"NoRedInk/elm-json-decode-pipeline": "1.0.0",
|
"elm/browser": "1.0.2",
|
||||||
"Skinney/keyboard-events": "2.0.1",
|
"elm/core": "1.0.4",
|
||||||
"elm/browser": "1.0.2",
|
"elm/html": "1.0.0",
|
||||||
"elm/core": "1.0.4",
|
"elm/http": "2.0.0",
|
||||||
"elm/html": "1.0.0",
|
"elm/json": "1.1.3",
|
||||||
"elm/http": "2.0.0",
|
"elm/regex": "1.0.0",
|
||||||
"elm/json": "1.1.3",
|
"elm/url": "1.0.0",
|
||||||
"elm/regex": "1.0.0",
|
"hecrj/html-parser": "2.3.4",
|
||||||
"elm/url": "1.0.0",
|
"krisajenkins/remotedata": "6.0.1",
|
||||||
"hecrj/html-parser": "2.3.4",
|
"truqu/elm-base64": "2.0.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"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"test-dependencies": {
|
"indirect": {
|
||||||
"direct": {
|
"elm/bytes": "1.0.8",
|
||||||
"elm-explorations/test": "1.2.2"
|
"elm/file": "1.0.5",
|
||||||
},
|
"elm/parser": "1.1.0",
|
||||||
"indirect": {
|
"elm/time": "1.0.0",
|
||||||
"elm/random": "1.0.0",
|
"elm/virtual-dom": "1.0.2",
|
||||||
"elm/svg": "1.0.1"
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
26
flake.lock
26
flake.lock
|
@ -1,14 +1,12 @@
|
||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"info": {
|
|
||||||
"lastModified": 1592376843,
|
|
||||||
"narHash": "sha256-vKchUGsNMQC9vCmTnpssHMV/+cKXA5QhbEoFm0zua1U="
|
|
||||||
},
|
|
||||||
"locked": {
|
"locked": {
|
||||||
|
"lastModified": 1595175601,
|
||||||
|
"narHash": "sha256-NMxaD3mdKyp+6nidFkZe7XOzVXtWMpOH1v4KYZxo/Z0=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "14fcd947a0150b78d7a37bef56c87fcd57808247",
|
"rev": "5717d9d2f7ca0662291910c52f1d7b95b568fec2",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -18,14 +16,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"info": {
|
|
||||||
"lastModified": 1592514044,
|
|
||||||
"narHash": "sha256-jGQJmq14vh9ASt9d5Z9yBPsrbUgroiNVNhsoBabsw0k="
|
|
||||||
},
|
|
||||||
"locked": {
|
"locked": {
|
||||||
|
"lastModified": 1595619256,
|
||||||
|
"narHash": "sha256-TOSvHwfQevzE/uTFBWYAt1I/F9F3YRkOV8gUrqUQfkk=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "e051dab9ff8a58455f6b8375856ac2802c6cd261",
|
"rev": "fd0febffda9af90d6d369ecb4cb9aaf347116bce",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -34,17 +30,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"poetry2nix": {
|
"poetry2nix": {
|
||||||
"info": {
|
|
||||||
"lastModified": 1592121810,
|
|
||||||
"narHash": "sha256-9cGTKtL7JpllwABxa4iRVU4Qw/YwniLni4RATyONz+s="
|
|
||||||
},
|
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs_2"
|
"nixpkgs": "nixpkgs_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
|
"lastModified": 1595517229,
|
||||||
|
"narHash": "sha256-5eMk3+Twb2fDyFX5sm33JYSRaPAvKe9vHV5w/HjbiHs=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "poetry2nix",
|
"repo": "poetry2nix",
|
||||||
"rev": "e7c69a288c10e4d97816fdabda5ae3f38e21914e",
|
"rev": "270a0b26b773e566ad59927c51d40a5e9b8ff08d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -61,5 +55,5 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "root",
|
"root": "root",
|
||||||
"version": 5
|
"version": 7
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ import shlex
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tqdm # type: ignore
|
import tqdm # type: ignore
|
||||||
import typing
|
|
||||||
import xml.etree.ElementTree
|
import xml.etree.ElementTree
|
||||||
|
|
||||||
logger = logging.getLogger("import-channel")
|
logger = logging.getLogger("import-channel")
|
||||||
|
@ -47,12 +46,6 @@ MAPPING = {
|
||||||
"properties": {
|
"properties": {
|
||||||
"type": {"type": "keyword"},
|
"type": {"type": "keyword"},
|
||||||
# Package fields
|
# Package fields
|
||||||
"package_suggestions": {
|
|
||||||
"type": "completion",
|
|
||||||
"analyzer": "lowercase",
|
|
||||||
"search_analyzer": "lowercase",
|
|
||||||
"preserve_position_increments": False,
|
|
||||||
},
|
|
||||||
"package_hydra_build": {
|
"package_hydra_build": {
|
||||||
"type": "nested",
|
"type": "nested",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -96,12 +89,6 @@ MAPPING = {
|
||||||
"package_homepage": {"type": "keyword"},
|
"package_homepage": {"type": "keyword"},
|
||||||
"package_system": {"type": "keyword"},
|
"package_system": {"type": "keyword"},
|
||||||
# Options fields
|
# Options fields
|
||||||
"option_suggestions": {
|
|
||||||
"type": "completion",
|
|
||||||
"analyzer": "lowercase",
|
|
||||||
"search_analyzer": "lowercase",
|
|
||||||
"preserve_position_increments": False,
|
|
||||||
},
|
|
||||||
"option_name": {"type": "keyword", "normalizer": "lowercase"},
|
"option_name": {"type": "keyword", "normalizer": "lowercase"},
|
||||||
"option_name_query": {"type": "keyword", "normalizer": "lowercase"},
|
"option_name_query": {"type": "keyword", "normalizer": "lowercase"},
|
||||||
"option_description": {"type": "text"},
|
"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):
|
def parse_query(text):
|
||||||
"""Tokenize package attr_name
|
"""Tokenize package attr_name
|
||||||
|
|
||||||
|
@ -371,7 +336,6 @@ def get_packages(evaluation, evaluation_builds):
|
||||||
|
|
||||||
yield dict(
|
yield dict(
|
||||||
type="package",
|
type="package",
|
||||||
package_suggestions=parse_suggestions(attr_name),
|
|
||||||
package_hydra=hydra,
|
package_hydra=hydra,
|
||||||
package_attr_name=attr_name,
|
package_attr_name=attr_name,
|
||||||
package_attr_name_query=list(parse_query(attr_name)),
|
package_attr_name_query=list(parse_query(attr_name)),
|
||||||
|
@ -438,7 +402,6 @@ def get_options(evaluation):
|
||||||
|
|
||||||
yield dict(
|
yield dict(
|
||||||
type="option",
|
type="option",
|
||||||
option_suggestions=parse_suggestions(name),
|
|
||||||
option_name=name,
|
option_name=name,
|
||||||
option_name_query=parse_query(name),
|
option_name_query=parse_query(name),
|
||||||
option_description=description,
|
option_description=description,
|
||||||
|
|
|
@ -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 <https://github.com/elm-community/elm-test>
|
|
||||||
-}
|
|
||||||
unitTest : Test
|
|
||||||
unitTest =
|
|
||||||
describe "simple unit test"
|
|
||||||
[ test "Inc adds one" <|
|
|
||||||
\() ->
|
|
||||||
update Inc (Model 0 "")
|
|
||||||
|> Tuple.first
|
|
||||||
|> .counter
|
|
||||||
|> Expect.equal 1
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
{-| See <https://github.com/elm-community/elm-test>
|
|
||||||
-}
|
|
||||||
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 <https://github.com/eeue56/elm-html-test>
|
|
||||||
-}
|
|
||||||
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" ]
|
|
||||||
]
|
|
|
@ -1,42 +1,6 @@
|
||||||
import pytest # type: ignore
|
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(
|
@pytest.mark.parametrize(
|
||||||
"text,expected",
|
"text,expected",
|
||||||
[
|
[
|
||||||
|
|
|
@ -240,11 +240,11 @@ update msg model =
|
||||||
|> updateWith Home HomeMsg model
|
|> updateWith Home HomeMsg model
|
||||||
|
|
||||||
( PackagesMsg subMsg, Packages subModel ) ->
|
( PackagesMsg subMsg, Packages subModel ) ->
|
||||||
Page.Packages.update model.navKey model.elasticsearch subMsg subModel
|
Page.Packages.update model.navKey subMsg subModel
|
||||||
|> updateWith Packages PackagesMsg model
|
|> updateWith Packages PackagesMsg model
|
||||||
|
|
||||||
( OptionsMsg subMsg, Options subModel ) ->
|
( OptionsMsg subMsg, Options subModel ) ->
|
||||||
Page.Options.update model.navKey model.elasticsearch subMsg subModel
|
Page.Options.update model.navKey subMsg subModel
|
||||||
|> updateWith Options OptionsMsg model
|
|> updateWith Options OptionsMsg model
|
||||||
|
|
||||||
( _, _ ) ->
|
( _, _ ) ->
|
||||||
|
|
|
@ -26,7 +26,9 @@ type Msg
|
||||||
|
|
||||||
update : Msg -> Model -> ( Model, Cmd Msg )
|
update : Msg -> Model -> ( Model, Cmd Msg )
|
||||||
update msg model =
|
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 -> Html Msg
|
||||||
view model =
|
view _ =
|
||||||
div [] [ text "Home" ]
|
div [] [ text "Home" ]
|
||||||
|
|
|
@ -17,8 +17,6 @@ import Html
|
||||||
, div
|
, div
|
||||||
, dl
|
, dl
|
||||||
, dt
|
, dt
|
||||||
, li
|
|
||||||
, p
|
|
||||||
, pre
|
, pre
|
||||||
, span
|
, span
|
||||||
, table
|
, table
|
||||||
|
@ -28,7 +26,6 @@ import Html
|
||||||
, th
|
, th
|
||||||
, thead
|
, thead
|
||||||
, tr
|
, tr
|
||||||
, ul
|
|
||||||
)
|
)
|
||||||
import Html.Attributes
|
import Html.Attributes
|
||||||
exposing
|
exposing
|
||||||
|
@ -42,7 +39,6 @@ import Html.Events
|
||||||
)
|
)
|
||||||
import Html.Parser
|
import Html.Parser
|
||||||
import Html.Parser.Util
|
import Html.Parser.Util
|
||||||
import Http
|
|
||||||
import Json.Decode
|
import Json.Decode
|
||||||
import Json.Encode
|
import Json.Encode
|
||||||
import Regex
|
import Regex
|
||||||
|
@ -94,8 +90,12 @@ type Msg
|
||||||
= SearchMsg (Search.Msg ResultItemSource)
|
= SearchMsg (Search.Msg ResultItemSource)
|
||||||
|
|
||||||
|
|
||||||
update : Browser.Navigation.Key -> Search.Options -> Msg -> Model -> ( Model, Cmd Msg )
|
update :
|
||||||
update navKey options msg model =
|
Browser.Navigation.Key
|
||||||
|
-> Msg
|
||||||
|
-> Model
|
||||||
|
-> ( Model, Cmd Msg )
|
||||||
|
update navKey msg model =
|
||||||
case msg of
|
case msg of
|
||||||
SearchMsg subMsg ->
|
SearchMsg subMsg ->
|
||||||
let
|
let
|
||||||
|
@ -103,9 +103,6 @@ update navKey options msg model =
|
||||||
Search.update
|
Search.update
|
||||||
"options"
|
"options"
|
||||||
navKey
|
navKey
|
||||||
"option"
|
|
||||||
options
|
|
||||||
decodeResultItemSource
|
|
||||||
subMsg
|
subMsg
|
||||||
model
|
model
|
||||||
in
|
in
|
||||||
|
@ -211,9 +208,6 @@ viewResultItemDetails channel item =
|
||||||
asCode value =
|
asCode value =
|
||||||
pre [] [ text value ]
|
pre [] [ text value ]
|
||||||
|
|
||||||
asLink value =
|
|
||||||
a [ href value ] [ text value ]
|
|
||||||
|
|
||||||
githubUrlPrefix branch =
|
githubUrlPrefix branch =
|
||||||
"https://github.com/NixOS/nixpkgs-channels/blob/" ++ branch ++ "/"
|
"https://github.com/NixOS/nixpkgs-channels/blob/" ++ branch ++ "/"
|
||||||
|
|
||||||
|
@ -305,7 +299,7 @@ makeRequest options channel queryRaw from size sort =
|
||||||
[ ( field
|
[ ( field
|
||||||
, Json.Encode.object
|
, Json.Encode.object
|
||||||
[ ( "query", Json.Encode.string query )
|
[ ( "query", Json.Encode.string query )
|
||||||
, ( "boost", Json.Encode.float boost )
|
, ( "boost", Json.Encode.float <| boost_base * boost )
|
||||||
, ( "analyzer", Json.Encode.string "whitespace" )
|
, ( "analyzer", Json.Encode.string "whitespace" )
|
||||||
, ( "fuzziness", Json.Encode.string "1" )
|
, ( "fuzziness", Json.Encode.string "1" )
|
||||||
, ( "_name"
|
, ( "_name"
|
||||||
|
@ -332,7 +326,7 @@ makeRequest options channel queryRaw from size sort =
|
||||||
[ ( field
|
[ ( field
|
||||||
, Json.Encode.object
|
, Json.Encode.object
|
||||||
[ ( "query", Json.Encode.string query )
|
[ ( "query", Json.Encode.string query )
|
||||||
, ( "boost", Json.Encode.float boost )
|
, ( "boost", Json.Encode.float <| boost_base * boost )
|
||||||
, ( "analyzer", Json.Encode.string "whitespace" )
|
, ( "analyzer", Json.Encode.string "whitespace" )
|
||||||
, ( "fuzziness", Json.Encode.string "1" )
|
, ( "fuzziness", Json.Encode.string "1" )
|
||||||
, ( "_name"
|
, ( "_name"
|
||||||
|
|
|
@ -19,7 +19,6 @@ import Html
|
||||||
, dl
|
, dl
|
||||||
, dt
|
, dt
|
||||||
, li
|
, li
|
||||||
, p
|
|
||||||
, table
|
, table
|
||||||
, tbody
|
, tbody
|
||||||
, td
|
, td
|
||||||
|
@ -39,7 +38,6 @@ import Html.Events
|
||||||
exposing
|
exposing
|
||||||
( onClick
|
( onClick
|
||||||
)
|
)
|
||||||
import Http
|
|
||||||
import Json.Decode
|
import Json.Decode
|
||||||
import Json.Decode.Pipeline
|
import Json.Decode.Pipeline
|
||||||
import Json.Encode
|
import Json.Encode
|
||||||
|
@ -129,8 +127,12 @@ type Msg
|
||||||
= SearchMsg (Search.Msg ResultItemSource)
|
= SearchMsg (Search.Msg ResultItemSource)
|
||||||
|
|
||||||
|
|
||||||
update : Browser.Navigation.Key -> Search.Options -> Msg -> Model -> ( Model, Cmd Msg )
|
update :
|
||||||
update navKey options msg model =
|
Browser.Navigation.Key
|
||||||
|
-> Msg
|
||||||
|
-> Model
|
||||||
|
-> ( Model, Cmd Msg )
|
||||||
|
update navKey msg model =
|
||||||
case msg of
|
case msg of
|
||||||
SearchMsg subMsg ->
|
SearchMsg subMsg ->
|
||||||
let
|
let
|
||||||
|
@ -138,9 +140,6 @@ update navKey options msg model =
|
||||||
Search.update
|
Search.update
|
||||||
"packages"
|
"packages"
|
||||||
navKey
|
navKey
|
||||||
"package"
|
|
||||||
options
|
|
||||||
decodeResultItemSource
|
|
||||||
subMsg
|
subMsg
|
||||||
model
|
model
|
||||||
in
|
in
|
||||||
|
|
453
src/Search.elm
453
src/Search.elm
|
@ -15,12 +15,9 @@ module Search exposing
|
||||||
, view
|
, view
|
||||||
)
|
)
|
||||||
|
|
||||||
import Array
|
|
||||||
import Base64
|
import Base64
|
||||||
import Browser.Dom
|
import Browser.Dom
|
||||||
import Browser.Navigation
|
import Browser.Navigation
|
||||||
import Debouncer.Messages
|
|
||||||
import Dict
|
|
||||||
import Html
|
import Html
|
||||||
exposing
|
exposing
|
||||||
( Html
|
( Html
|
||||||
|
@ -44,7 +41,6 @@ import Html
|
||||||
import Html.Attributes
|
import Html.Attributes
|
||||||
exposing
|
exposing
|
||||||
( attribute
|
( attribute
|
||||||
, autocomplete
|
|
||||||
, autofocus
|
, autofocus
|
||||||
, class
|
, class
|
||||||
, classList
|
, classList
|
||||||
|
@ -57,16 +53,13 @@ import Html.Attributes
|
||||||
)
|
)
|
||||||
import Html.Events
|
import Html.Events
|
||||||
exposing
|
exposing
|
||||||
( custom
|
( onClick
|
||||||
, onClick
|
|
||||||
, onInput
|
, onInput
|
||||||
, onSubmit
|
, onSubmit
|
||||||
)
|
)
|
||||||
import Http
|
import Http
|
||||||
import Json.Decode
|
import Json.Decode
|
||||||
import Json.Encode
|
import Json.Encode
|
||||||
import Keyboard
|
|
||||||
import Keyboard.Events
|
|
||||||
import RemoteData
|
import RemoteData
|
||||||
import Task
|
import Task
|
||||||
import Url.Builder
|
import Url.Builder
|
||||||
|
@ -75,9 +68,6 @@ import Url.Builder
|
||||||
type alias Model a =
|
type alias Model a =
|
||||||
{ channel : String
|
{ channel : String
|
||||||
, query : Maybe String
|
, query : Maybe String
|
||||||
, queryDebounce : Debouncer.Messages.Debouncer (Msg a)
|
|
||||||
, querySuggest : RemoteData.WebData (SearchResult a)
|
|
||||||
, querySelectedSuggestion : Maybe String
|
|
||||||
, result : RemoteData.WebData (SearchResult a)
|
, result : RemoteData.WebData (SearchResult a)
|
||||||
, show : Maybe String
|
, show : Maybe String
|
||||||
, from : Int
|
, from : Int
|
||||||
|
@ -88,20 +78,6 @@ type alias Model a =
|
||||||
|
|
||||||
type alias SearchResult a =
|
type alias SearchResult a =
|
||||||
{ hits : ResultHits 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
|
|> Maybe.withDefault 15
|
||||||
in
|
in
|
||||||
( { channel = Maybe.withDefault defaultChannel channel
|
( { channel = Maybe.withDefault defaultChannel channel
|
||||||
, queryDebounce =
|
|
||||||
Debouncer.Messages.manual
|
|
||||||
|> Debouncer.Messages.settleWhenQuietFor (Just <| Debouncer.Messages.fromSeconds 0.4)
|
|
||||||
|> Debouncer.Messages.toDebouncer
|
|
||||||
, query = query
|
, 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 =
|
, result =
|
||||||
model
|
model
|
||||||
|> Maybe.map (\x -> x.result)
|
|> Maybe.map (\x -> x.result)
|
||||||
|
@ -207,34 +165,19 @@ type Msg a
|
||||||
= NoOp
|
= NoOp
|
||||||
| SortChange String
|
| SortChange String
|
||||||
| ChannelChange String
|
| ChannelChange String
|
||||||
| QueryInputDebounce (Debouncer.Messages.Msg (Msg a))
|
|
||||||
| QueryInput String
|
| QueryInput String
|
||||||
| QueryInputSuggestionsSubmit
|
|
||||||
| QueryInputSuggestionsResponse (RemoteData.WebData (SearchResult a))
|
|
||||||
| QueryInputSubmit
|
| QueryInputSubmit
|
||||||
| QueryResponse (RemoteData.WebData (SearchResult a))
|
| QueryResponse (RemoteData.WebData (SearchResult a))
|
||||||
| ShowDetails String
|
| ShowDetails String
|
||||||
| SuggestionsMoveDown
|
|
||||||
| SuggestionsMoveUp
|
|
||||||
| SuggestionsSelect
|
|
||||||
| SuggestionsClickSelect String
|
|
||||||
| SuggestionsClose
|
|
||||||
|
|
||||||
|
|
||||||
update :
|
update :
|
||||||
String
|
String
|
||||||
-> Browser.Navigation.Key
|
-> Browser.Navigation.Key
|
||||||
-> String
|
|
||||||
-> Options
|
|
||||||
-> Json.Decode.Decoder a
|
|
||||||
-> Msg a
|
-> Msg a
|
||||||
-> Model a
|
-> Model a
|
||||||
-> ( Model a, Cmd (Msg a) )
|
-> ( Model a, Cmd (Msg a) )
|
||||||
update path navKey result_type options decodeResultItemSource msg model =
|
update path navKey msg model =
|
||||||
let
|
|
||||||
requestQuerySuggestionsTracker =
|
|
||||||
"query-" ++ result_type ++ "-suggestions"
|
|
||||||
in
|
|
||||||
case msg of
|
case msg of
|
||||||
NoOp ->
|
NoOp ->
|
||||||
( model
|
( model
|
||||||
|
@ -283,94 +226,8 @@ update path navKey result_type options decodeResultItemSource msg model =
|
||||||
|> Browser.Navigation.pushUrl navKey
|
|> 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 ->
|
QueryInput query ->
|
||||||
update path
|
( { model | query = Just query }
|
||||||
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
|
|
||||||
}
|
|
||||||
, Cmd.none
|
, Cmd.none
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -414,155 +271,6 @@ update path navKey result_type options decodeResultItemSource msg model =
|
||||||
|> Browser.Navigation.pushUrl navKey
|
|> 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 :
|
createUrl :
|
||||||
String
|
String
|
||||||
|
@ -736,48 +444,6 @@ fromSortId id =
|
||||||
Nothing
|
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 :
|
view :
|
||||||
String
|
String
|
||||||
-> String
|
-> String
|
||||||
|
@ -786,48 +452,10 @@ view :
|
||||||
-> (Msg a -> b)
|
-> (Msg a -> b)
|
||||||
-> Html b
|
-> Html b
|
||||||
view path title model viewSuccess outMsg =
|
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
|
div
|
||||||
[ classList
|
[ class "search-page"
|
||||||
[ ( "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)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
]
|
]
|
||||||
[ h1 [ class "page-header" ] [ text title ]
|
[ h1 [ class "page-header" ] [ text title ]
|
||||||
, div
|
|
||||||
[ class "search-backdrop"
|
|
||||||
, onClick <| outMsg SuggestionsClose
|
|
||||||
]
|
|
||||||
[]
|
|
||||||
, div
|
, div
|
||||||
[ class "search-input"
|
[ class "search-input"
|
||||||
]
|
]
|
||||||
|
@ -863,60 +491,19 @@ view path title model viewSuccess outMsg =
|
||||||
[ class "input-append"
|
[ class "input-append"
|
||||||
]
|
]
|
||||||
[ input
|
[ input
|
||||||
([ type_ "text"
|
[ type_ "text"
|
||||||
, id "search-query-input"
|
, id "search-query-input"
|
||||||
, autocomplete False
|
, autofocus True
|
||||||
, autofocus True
|
, placeholder <| "Search for " ++ path
|
||||||
, placeholder <| "Search for " ++ path
|
, onInput (\x -> outMsg (QueryInput x))
|
||||||
, onInput (\x -> outMsg (QueryInput x))
|
, value <| Maybe.withDefault "" model.query
|
||||||
, 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
|
|
||||||
[]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
[]
|
[]
|
||||||
, div [ class "loader" ] []
|
, div [ class "loader" ] []
|
||||||
, div [ class "btn-group" ]
|
, div [ class "btn-group" ]
|
||||||
[ button [ class "btn" ] [ text "Search" ]
|
[ 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
|
, case model.result of
|
||||||
|
@ -1299,24 +886,8 @@ decodeResult :
|
||||||
Json.Decode.Decoder a
|
Json.Decode.Decoder a
|
||||||
-> Json.Decode.Decoder (SearchResult a)
|
-> Json.Decode.Decoder (SearchResult a)
|
||||||
decodeResult decodeResultItemSource =
|
decodeResult decodeResultItemSource =
|
||||||
Json.Decode.map2 SearchResult
|
Json.Decode.map SearchResult
|
||||||
(Json.Decode.field "hits" (decodeResultHits decodeResultItemSource))
|
(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)
|
decodeResultHits : Json.Decode.Decoder a -> Json.Decode.Decoder (ResultHits a)
|
||||||
|
|
|
@ -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 {
|
.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 {
|
.input-append {
|
||||||
position: relative;
|
|
||||||
input {
|
input {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
|
BIN
versions.dat
BIN
versions.dat
Binary file not shown.
Loading…
Reference in a new issue