make a request to elasticsearch, nothing fancy
This commit is contained in:
parent
7ba9487c30
commit
f19216fe5a
5
elm.json
5
elm.json
|
@ -6,17 +6,20 @@
|
|||
"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/url": "1.0.0",
|
||||
"krisajenkins/remotedata": "6.0.1"
|
||||
"krisajenkins/remotedata": "6.0.1",
|
||||
"truqu/elm-base64": "2.0.4"
|
||||
},
|
||||
"indirect": {
|
||||
"elm/bytes": "1.0.8",
|
||||
"elm/file": "1.0.5",
|
||||
"elm/regex": "1.0.0",
|
||||
"elm/time": "1.0.0",
|
||||
"elm/virtual-dom": "1.0.2"
|
||||
}
|
||||
|
|
|
@ -75,6 +75,8 @@ def get_packages(evaluation):
|
|||
)
|
||||
for license in licenses
|
||||
]
|
||||
else:
|
||||
licenses = []
|
||||
maintainers = [
|
||||
type(maintainer) == str
|
||||
and dict(name=maintainer, email=None, github=None)
|
||||
|
|
285
src/Main.elm
285
src/Main.elm
|
@ -1,5 +1,6 @@
|
|||
module Main exposing (main)
|
||||
|
||||
import Base64
|
||||
import Browser exposing (UrlRequest(..))
|
||||
import Browser.Navigation as Nav exposing (Key)
|
||||
import Html
|
||||
|
@ -11,6 +12,7 @@ import Html
|
|||
, header
|
||||
, input
|
||||
, li
|
||||
, pre
|
||||
, text
|
||||
, ul
|
||||
)
|
||||
|
@ -25,7 +27,11 @@ import Html.Events
|
|||
( onClick
|
||||
, onInput
|
||||
)
|
||||
import Http exposing (Error(..))
|
||||
import Http
|
||||
import Json.Decode as D
|
||||
import Json.Decode.Pipeline as DP
|
||||
import Json.Encode as E
|
||||
import RemoteData as R
|
||||
import Url exposing (Url)
|
||||
import Url.Parser as UrlParser
|
||||
exposing
|
||||
|
@ -41,36 +47,78 @@ import Url.Parser.Query as UrlParserQuery
|
|||
-- ---------------------------
|
||||
|
||||
|
||||
type alias Flags =
|
||||
{ elasticsearchUrl : String
|
||||
, elasticsearchUsername : String
|
||||
, elasticsearchPassword : String
|
||||
}
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ key : Key
|
||||
, elasticsearchUrl : String
|
||||
, elasticsearchUsername : String
|
||||
, elasticsearchPassword : String
|
||||
, page : Page
|
||||
}
|
||||
|
||||
|
||||
type alias SearchModel =
|
||||
{ query : String
|
||||
, results : List SearchResult
|
||||
, result : R.WebData SearchResult
|
||||
}
|
||||
|
||||
|
||||
type Page
|
||||
= Search SearchModel
|
||||
= SearchPage SearchModel
|
||||
|
||||
|
||||
type SearchResult
|
||||
|
||||
--| PackagePage SearchModel
|
||||
--| MaintainerPage SearchModel
|
||||
|
||||
|
||||
type alias SearchResult =
|
||||
{ hits : SearchResultHits
|
||||
}
|
||||
|
||||
|
||||
type alias SearchResultHits =
|
||||
{ total : SearchResultHitsTotal
|
||||
, max_score : Maybe Float
|
||||
, hits : List SearchResultItem
|
||||
}
|
||||
|
||||
|
||||
type alias SearchResultHitsTotal =
|
||||
{ value : Int
|
||||
, relation : String -- TODO: this should probably be Enum
|
||||
}
|
||||
|
||||
|
||||
type alias SearchResultItem =
|
||||
{ index : String
|
||||
, id : String
|
||||
, score : Float
|
||||
, source : SearchResultItemSource
|
||||
}
|
||||
|
||||
|
||||
type SearchResultItemSource
|
||||
= Package SearchResultPackage
|
||||
| Option SearchResultOption
|
||||
|
||||
|
||||
type alias SearchResultPackage =
|
||||
{ attribute_name : String
|
||||
{ attr_name : String
|
||||
, name : String
|
||||
, version : String
|
||||
, description : String
|
||||
, longDescription : String
|
||||
, license : List SearchResultPackageLicense
|
||||
, position : String
|
||||
, homepage : String
|
||||
, description : Maybe String
|
||||
, longDescription : Maybe String
|
||||
, licenses : List SearchResultPackageLicense
|
||||
, maintainers : List SearchResultPackageMaintainer
|
||||
, position : Maybe String
|
||||
, homepage : Maybe String
|
||||
}
|
||||
|
||||
|
||||
|
@ -86,7 +134,7 @@ type alias SearchResultOption =
|
|||
|
||||
type alias SearchResultPackageLicense =
|
||||
{ fullName : String
|
||||
, url : String
|
||||
, url : Maybe String
|
||||
}
|
||||
|
||||
|
||||
|
@ -99,12 +147,15 @@ type alias SearchResultPackageMaintainer =
|
|||
|
||||
emptySearch : Page
|
||||
emptySearch =
|
||||
Search { query = "", results = [] }
|
||||
SearchPage { query = "", result = R.NotAsked }
|
||||
|
||||
|
||||
init : Int -> Url -> Key -> ( Model, Cmd Msg )
|
||||
init _ url key =
|
||||
init : Flags -> Url -> Key -> ( Model, Cmd Msg )
|
||||
init flags url key =
|
||||
( { key = key
|
||||
, elasticsearchUrl = flags.elasticsearchUrl
|
||||
, elasticsearchUsername = flags.elasticsearchUsername
|
||||
, elasticsearchPassword = flags.elasticsearchPassword
|
||||
, page = UrlParser.parse urlParser url |> Maybe.withDefault emptySearch
|
||||
}
|
||||
, Cmd.none
|
||||
|
@ -132,9 +183,9 @@ urlParser =
|
|||
UrlParser.oneOf
|
||||
[ UrlParser.map
|
||||
(\q ->
|
||||
Search
|
||||
SearchPage
|
||||
{ query = q |> Maybe.withDefault ""
|
||||
, results = []
|
||||
, result = R.NotAsked
|
||||
}
|
||||
)
|
||||
(UrlParser.s "search" <?> UrlParserQuery.string "query")
|
||||
|
@ -152,13 +203,124 @@ type Msg
|
|||
| OnUrlChange Url
|
||||
| SearchPageInput String
|
||||
| SearchQuerySubmit
|
||||
| SearchQueryResponse (R.WebData SearchResult)
|
||||
|
||||
|
||||
initPage : Page -> Cmd Msg
|
||||
initPage page =
|
||||
case page of
|
||||
Search _ ->
|
||||
Cmd.none
|
||||
decodeResult : D.Decoder SearchResult
|
||||
decodeResult =
|
||||
D.map SearchResult
|
||||
(D.field "hits" decodeResultHits)
|
||||
|
||||
|
||||
decodeResultHits : D.Decoder SearchResultHits
|
||||
decodeResultHits =
|
||||
D.map3 SearchResultHits
|
||||
(D.field "total" decodeResultHitsTotal)
|
||||
(D.field "max_score" (D.nullable D.float))
|
||||
(D.field "hits" (D.list decodeResultItem))
|
||||
|
||||
|
||||
decodeResultHitsTotal : D.Decoder SearchResultHitsTotal
|
||||
decodeResultHitsTotal =
|
||||
D.map2 SearchResultHitsTotal
|
||||
(D.field "value" D.int)
|
||||
(D.field "relation" D.string)
|
||||
|
||||
|
||||
decodeResultItem : D.Decoder SearchResultItem
|
||||
decodeResultItem =
|
||||
D.map4 SearchResultItem
|
||||
(D.field "_index" D.string)
|
||||
(D.field "_id" D.string)
|
||||
(D.field "_score" D.float)
|
||||
(D.field "_source" decodeResultItemSource)
|
||||
|
||||
|
||||
decodeResultItemSource : D.Decoder SearchResultItemSource
|
||||
decodeResultItemSource =
|
||||
D.oneOf
|
||||
[ D.map Package decodeResultPackage
|
||||
|
||||
--, D.map Option decodeResultOption
|
||||
]
|
||||
|
||||
|
||||
decodeResultPackage : D.Decoder SearchResultPackage
|
||||
decodeResultPackage =
|
||||
D.succeed SearchResultPackage
|
||||
|> DP.required "attr_name" D.string
|
||||
|> DP.required "name" D.string
|
||||
|> DP.required "version" D.string
|
||||
|> DP.required "description" (D.nullable D.string)
|
||||
|> DP.required "longDescription" (D.nullable D.string)
|
||||
|> DP.required "license" (D.list decodeResultPackageLicense)
|
||||
|> DP.required "maintainers" (D.list decodeResultPackageMaintainer)
|
||||
|> DP.required "position" (D.nullable D.string)
|
||||
|> DP.required "homepage" (D.nullable D.string)
|
||||
|
||||
|
||||
decodeResultPackageLicense : D.Decoder SearchResultPackageLicense
|
||||
decodeResultPackageLicense =
|
||||
D.map2 SearchResultPackageLicense
|
||||
(D.field "fullName" D.string)
|
||||
(D.field "url" (D.nullable D.string))
|
||||
|
||||
|
||||
decodeResultPackageMaintainer : D.Decoder SearchResultPackageMaintainer
|
||||
decodeResultPackageMaintainer =
|
||||
D.map3 SearchResultPackageMaintainer
|
||||
(D.field "name" D.string)
|
||||
(D.field "email" D.string)
|
||||
(D.field "github" D.string)
|
||||
|
||||
|
||||
decodeResultOption : D.Decoder SearchResultOption
|
||||
decodeResultOption =
|
||||
D.map6 SearchResultOption
|
||||
(D.field "option_name" D.string)
|
||||
(D.field "description" D.string)
|
||||
(D.field "type" D.string)
|
||||
(D.field "default" D.string)
|
||||
(D.field "example" D.string)
|
||||
(D.field "source" D.string)
|
||||
|
||||
|
||||
initPage : Model -> Cmd Msg
|
||||
initPage model =
|
||||
case model.page of
|
||||
SearchPage searchModel ->
|
||||
if searchModel.query == "" then
|
||||
Cmd.none
|
||||
|
||||
else
|
||||
Http.riskyRequest
|
||||
{ method = "POST"
|
||||
, headers =
|
||||
[ Http.header "Authorization" ("Basic " ++ Base64.encode (model.elasticsearchUsername ++ ":" ++ model.elasticsearchPassword))
|
||||
]
|
||||
, url = model.elasticsearchUrl ++ "/nixos-unstable-packages/_search"
|
||||
, body =
|
||||
Http.jsonBody <|
|
||||
E.object
|
||||
[ ( "query"
|
||||
, E.object
|
||||
[ ( "match"
|
||||
, E.object
|
||||
[ ( "name"
|
||||
, E.object
|
||||
[ ( "query", E.string searchModel.query )
|
||||
, ( "fuzziness", E.int 1 )
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
, expect = Http.expectJson (R.fromResult >> SearchQueryResponse) decodeResult
|
||||
, timeout = Nothing
|
||||
, tracker = Nothing
|
||||
}
|
||||
|
||||
|
||||
update : Msg -> Model -> ( Model, Cmd Msg )
|
||||
|
@ -172,53 +334,54 @@ update message model =
|
|||
newModel =
|
||||
{ model | page = UrlParser.parse urlParser url |> Maybe.withDefault model.page }
|
||||
|
||||
packages =
|
||||
[ Package
|
||||
{ attribute_name = "firefox"
|
||||
, name = "firefox"
|
||||
, version = "74.0"
|
||||
, description = "A web browser built from Firefox source tree (with plugins: )"
|
||||
, longDescription = ""
|
||||
, license = [ { fullName = "Mozilla Public License 2.0", url = "http://spdx.org/licenses/MPL-2.0.html" } ]
|
||||
, position = ""
|
||||
, homepage = "http://www.mozilla.com/en-US/firefox/"
|
||||
}
|
||||
]
|
||||
|
||||
newPage =
|
||||
case newModel.page of
|
||||
Search searchModel ->
|
||||
Search
|
||||
SearchPage searchModel ->
|
||||
SearchPage
|
||||
{ searchModel
|
||||
| results =
|
||||
| result =
|
||||
if searchModel.query == "" then
|
||||
[]
|
||||
R.NotAsked
|
||||
|
||||
else
|
||||
packages
|
||||
R.Loading
|
||||
}
|
||||
|
||||
newNewModel =
|
||||
{ newModel | page = newPage }
|
||||
in
|
||||
( { newModel | page = newPage }
|
||||
, initPage newPage
|
||||
( newNewModel
|
||||
, initPage newNewModel
|
||||
)
|
||||
|
||||
SearchPageInput query ->
|
||||
( { model
|
||||
| page =
|
||||
case model.page of
|
||||
Search searchModel ->
|
||||
Search { searchModel | query = query }
|
||||
SearchPage searchModel ->
|
||||
SearchPage { searchModel | query = query }
|
||||
}
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
SearchQuerySubmit ->
|
||||
case model.page of
|
||||
Search searchModel ->
|
||||
SearchPage searchModel ->
|
||||
( model
|
||||
, Nav.pushUrl model.key <| "/search?query=" ++ searchModel.query
|
||||
)
|
||||
|
||||
SearchQueryResponse result ->
|
||||
case model.page of
|
||||
SearchPage searchModel ->
|
||||
let
|
||||
newPage =
|
||||
SearchPage { searchModel | result = result }
|
||||
in
|
||||
( { model | page = newPage }
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
|
||||
|
||||
-- ---------------------------
|
||||
|
@ -233,7 +396,7 @@ view model =
|
|||
[ h1 [] [ text "NixOS Search" ]
|
||||
]
|
||||
, case model.page of
|
||||
Search searchModel ->
|
||||
SearchPage searchModel ->
|
||||
searchPage searchModel
|
||||
]
|
||||
|
||||
|
@ -250,18 +413,34 @@ searchPage model =
|
|||
[]
|
||||
, button [ onClick SearchQuerySubmit ] [ text "Search" ]
|
||||
]
|
||||
, ul [] (List.map searchPageResult model.results)
|
||||
, case model.result of
|
||||
R.NotAsked ->
|
||||
div [] [ text "NotAsked" ]
|
||||
|
||||
R.Loading ->
|
||||
div [] [ text "Loading" ]
|
||||
|
||||
R.Success result ->
|
||||
ul [] (searchPageResult result.hits)
|
||||
|
||||
R.Failure error ->
|
||||
div [] [ text "Error!", pre [] [ text (Debug.toString error) ] ]
|
||||
]
|
||||
|
||||
|
||||
searchPageResult : SearchResult -> Html Msg
|
||||
searchPageResult : SearchResultHits -> List (Html Msg)
|
||||
searchPageResult result =
|
||||
case result of
|
||||
Package package ->
|
||||
li [] [ text package.attribute_name ]
|
||||
List.map searchPageResultItem result.hits
|
||||
|
||||
Option option ->
|
||||
li [] [ text option.option_name ]
|
||||
|
||||
searchPageResultItem : SearchResultItem -> Html Msg
|
||||
searchPageResultItem item =
|
||||
-- case item.source of
|
||||
-- Package package ->
|
||||
-- li [] [ text package.attr_name ]
|
||||
-- Option option ->
|
||||
-- li [] [ text option.option_name ]
|
||||
li [] [ text <| Debug.toString item ]
|
||||
|
||||
|
||||
|
||||
|
@ -270,7 +449,7 @@ searchPageResult result =
|
|||
-- ---------------------------
|
||||
|
||||
|
||||
main : Program Int Model Msg
|
||||
main : Program Flags Model Msg
|
||||
main =
|
||||
Browser.application
|
||||
{ init = init
|
||||
|
|
14
src/index.js
14
src/index.js
|
@ -3,13 +3,9 @@
|
|||
require("./styles.scss");
|
||||
|
||||
const {Elm} = require('./Main');
|
||||
var app = Elm.Main.init({flags: 6});
|
||||
|
||||
app.ports.toJs.subscribe(data => {
|
||||
console.log(data);
|
||||
})
|
||||
// Use ES2015 syntax and let Babel compile it for you
|
||||
var testFn = (inp) => {
|
||||
let a = inp + 1;
|
||||
return a;
|
||||
}
|
||||
Elm.Main.init({flags: {
|
||||
elasticsearchUrl: process.env.ELASTICSEARCH_URL || 'https://nixos-search-5886075189.us-east-1.bonsaisearch.net:443',
|
||||
elasticsearchUsername : process.env.ELASTICSEARCH_USERNAME || 'z3ZFJ6y2mR',
|
||||
elasticsearchPassword : process.env.ELASTICSEARCH_PASSWORD || 'ds8CEvALPf9pui7XG'
|
||||
}});
|
||||
|
|
Loading…
Reference in a new issue