2020-03-31 03:22:27 +00:00
|
|
|
module Main exposing (main)
|
2020-03-28 04:09:01 +00:00
|
|
|
|
|
|
|
import Browser exposing (UrlRequest(..))
|
|
|
|
import Browser.Navigation as Nav exposing (Key)
|
2020-03-31 03:22:27 +00:00
|
|
|
import Html
|
|
|
|
exposing
|
|
|
|
( Html
|
|
|
|
, button
|
|
|
|
, div
|
|
|
|
, h1
|
|
|
|
, header
|
|
|
|
, input
|
|
|
|
, li
|
|
|
|
, text
|
|
|
|
, ul
|
|
|
|
)
|
|
|
|
import Html.Attributes
|
|
|
|
exposing
|
|
|
|
( class
|
|
|
|
, type_
|
|
|
|
, value
|
|
|
|
)
|
|
|
|
import Html.Events
|
|
|
|
exposing
|
|
|
|
( onClick
|
|
|
|
, onInput
|
|
|
|
)
|
2020-03-28 04:09:01 +00:00
|
|
|
import Http exposing (Error(..))
|
|
|
|
import Url exposing (Url)
|
2020-03-31 03:22:27 +00:00
|
|
|
import Url.Parser as UrlParser
|
|
|
|
exposing
|
|
|
|
( (<?>)
|
|
|
|
, Parser
|
|
|
|
)
|
2020-03-31 00:59:06 +00:00
|
|
|
import Url.Parser.Query as UrlParserQuery
|
2020-03-28 04:09:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- ---------------------------
|
|
|
|
-- MODEL
|
|
|
|
-- ---------------------------
|
|
|
|
|
|
|
|
|
|
|
|
type alias Model =
|
|
|
|
{ key : Key
|
|
|
|
, page : Page
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-03-31 00:59:06 +00:00
|
|
|
type alias SearchModel =
|
|
|
|
{ query : String
|
2020-03-31 03:22:27 +00:00
|
|
|
, results : List SearchResult
|
2020-03-31 00:59:06 +00:00
|
|
|
}
|
2020-03-28 04:09:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
type Page
|
2020-03-31 00:59:06 +00:00
|
|
|
= Search SearchModel
|
|
|
|
|
|
|
|
|
2020-03-31 03:22:27 +00:00
|
|
|
type SearchResult
|
|
|
|
= Package SearchResultPackage
|
|
|
|
| Option SearchResultOption
|
|
|
|
|
|
|
|
|
|
|
|
type alias SearchResultPackage =
|
|
|
|
{ attribute_name : String
|
|
|
|
, name : String
|
|
|
|
, version : String
|
|
|
|
, description : String
|
|
|
|
, longDescription : String
|
|
|
|
, license : List SearchResultPackageLicense
|
|
|
|
, position : String
|
|
|
|
, homepage : String
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
type alias SearchResultOption =
|
|
|
|
{ option_name : String
|
|
|
|
, description : String
|
|
|
|
, type_ : String
|
|
|
|
, default : String
|
|
|
|
, example : String
|
|
|
|
, source : String
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
type alias SearchResultPackageLicense =
|
|
|
|
{ fullName : String
|
|
|
|
, url : String
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
type alias SearchResultPackageMaintainer =
|
|
|
|
{ name : String
|
|
|
|
, email : String
|
|
|
|
, github : String
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
emptySearch : Page
|
2020-03-31 00:59:06 +00:00
|
|
|
emptySearch =
|
|
|
|
Search { query = "", results = [] }
|
|
|
|
|
|
|
|
|
|
|
|
init : Int -> Url -> Key -> ( Model, Cmd Msg )
|
2020-03-31 03:22:27 +00:00
|
|
|
init _ url key =
|
2020-03-31 00:59:06 +00:00
|
|
|
( { key = key
|
|
|
|
, page = UrlParser.parse urlParser url |> Maybe.withDefault emptySearch
|
|
|
|
}
|
|
|
|
, Cmd.none
|
|
|
|
)
|
2020-03-28 04:09:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- ---------------------------
|
|
|
|
-- URL Parsing and Routing
|
|
|
|
-- ---------------------------
|
|
|
|
|
|
|
|
|
|
|
|
handleUrlRequest : Key -> UrlRequest -> Cmd msg
|
|
|
|
handleUrlRequest key urlRequest =
|
|
|
|
case urlRequest of
|
|
|
|
Internal url ->
|
|
|
|
Nav.pushUrl key (Url.toString url)
|
|
|
|
|
|
|
|
External url ->
|
|
|
|
Nav.load url
|
|
|
|
|
|
|
|
|
|
|
|
urlParser : Parser (Page -> msg) msg
|
|
|
|
urlParser =
|
|
|
|
UrlParser.oneOf
|
2020-03-31 00:59:06 +00:00
|
|
|
[ UrlParser.map
|
|
|
|
(\q ->
|
|
|
|
Search
|
|
|
|
{ query = q |> Maybe.withDefault ""
|
|
|
|
, results = []
|
|
|
|
}
|
|
|
|
)
|
|
|
|
(UrlParser.s "search" <?> UrlParserQuery.string "query")
|
2020-03-28 04:09:01 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- ---------------------------
|
|
|
|
-- UPDATE
|
|
|
|
-- ---------------------------
|
|
|
|
|
|
|
|
|
|
|
|
type Msg
|
|
|
|
= OnUrlRequest UrlRequest
|
|
|
|
| OnUrlChange Url
|
2020-03-31 00:59:06 +00:00
|
|
|
| SearchPageInput String
|
|
|
|
| SearchQuerySubmit
|
|
|
|
|
|
|
|
|
|
|
|
initPage : Page -> Cmd Msg
|
|
|
|
initPage page =
|
|
|
|
case page of
|
2020-03-31 03:22:27 +00:00
|
|
|
Search _ ->
|
2020-03-31 00:59:06 +00:00
|
|
|
Cmd.none
|
2020-03-28 04:09:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
update : Msg -> Model -> ( Model, Cmd Msg )
|
|
|
|
update message model =
|
|
|
|
case message of
|
|
|
|
OnUrlRequest urlRequest ->
|
|
|
|
( model, handleUrlRequest model.key urlRequest )
|
|
|
|
|
|
|
|
OnUrlChange url ->
|
|
|
|
let
|
2020-03-31 00:59:06 +00:00
|
|
|
newModel =
|
|
|
|
{ model | page = UrlParser.parse urlParser url |> Maybe.withDefault model.page }
|
2020-03-31 03:22:27 +00:00
|
|
|
|
|
|
|
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 =
|
2020-03-31 00:59:06 +00:00
|
|
|
case newModel.page of
|
|
|
|
Search searchModel ->
|
|
|
|
Search
|
|
|
|
{ searchModel
|
|
|
|
| results =
|
|
|
|
if searchModel.query == "" then
|
|
|
|
[]
|
|
|
|
|
|
|
|
else
|
2020-03-31 03:22:27 +00:00
|
|
|
packages
|
2020-03-31 00:59:06 +00:00
|
|
|
}
|
2020-03-31 03:22:27 +00:00
|
|
|
in
|
|
|
|
( { newModel | page = newPage }
|
|
|
|
, initPage newPage
|
2020-03-28 04:09:01 +00:00
|
|
|
)
|
|
|
|
|
2020-03-31 00:59:06 +00:00
|
|
|
SearchPageInput query ->
|
|
|
|
( { model
|
|
|
|
| page =
|
|
|
|
case model.page of
|
|
|
|
Search searchModel ->
|
|
|
|
Search { searchModel | query = query }
|
|
|
|
}
|
|
|
|
, Cmd.none
|
|
|
|
)
|
2020-03-28 04:09:01 +00:00
|
|
|
|
2020-03-31 00:59:06 +00:00
|
|
|
SearchQuerySubmit ->
|
|
|
|
case model.page of
|
|
|
|
Search searchModel ->
|
|
|
|
( model
|
|
|
|
, Nav.pushUrl model.key <| "/search?query=" ++ searchModel.query
|
|
|
|
)
|
2020-03-28 04:09:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- ---------------------------
|
|
|
|
-- VIEW
|
|
|
|
-- ---------------------------
|
|
|
|
|
|
|
|
|
|
|
|
view : Model -> Html Msg
|
|
|
|
view model =
|
|
|
|
div [ class "container" ]
|
|
|
|
[ header []
|
2020-03-31 00:59:06 +00:00
|
|
|
[ h1 [] [ text "NixOS Search" ]
|
2020-03-28 04:09:01 +00:00
|
|
|
]
|
|
|
|
, case model.page of
|
2020-03-31 00:59:06 +00:00
|
|
|
Search searchModel ->
|
|
|
|
searchPage searchModel
|
2020-03-28 04:09:01 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
|
2020-03-31 00:59:06 +00:00
|
|
|
searchPage : SearchModel -> Html Msg
|
|
|
|
searchPage model =
|
|
|
|
div []
|
|
|
|
[ div []
|
|
|
|
[ input
|
|
|
|
[ type_ "text"
|
|
|
|
, onInput SearchPageInput
|
|
|
|
, value model.query
|
|
|
|
]
|
|
|
|
[]
|
|
|
|
, button [ onClick SearchQuerySubmit ] [ text "Search" ]
|
2020-03-28 04:09:01 +00:00
|
|
|
]
|
2020-03-31 00:59:06 +00:00
|
|
|
, ul [] (List.map searchPageResult model.results)
|
2020-03-28 04:09:01 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
|
2020-03-31 03:22:27 +00:00
|
|
|
searchPageResult : SearchResult -> Html Msg
|
|
|
|
searchPageResult result =
|
|
|
|
case result of
|
|
|
|
Package package ->
|
|
|
|
li [] [ text package.attribute_name ]
|
|
|
|
|
|
|
|
Option option ->
|
|
|
|
li [] [ text option.option_name ]
|
2020-03-28 04:09:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- ---------------------------
|
|
|
|
-- MAIN
|
|
|
|
-- ---------------------------
|
|
|
|
|
|
|
|
|
|
|
|
main : Program Int Model Msg
|
|
|
|
main =
|
|
|
|
Browser.application
|
|
|
|
{ init = init
|
|
|
|
, update = update
|
|
|
|
, view =
|
|
|
|
\m ->
|
2020-03-31 00:59:06 +00:00
|
|
|
{ title = "NixOS Search"
|
2020-03-28 04:09:01 +00:00
|
|
|
, body = [ view m ]
|
|
|
|
}
|
|
|
|
, subscriptions = \_ -> Sub.none
|
|
|
|
, onUrlRequest = OnUrlRequest
|
|
|
|
, onUrlChange = OnUrlChange
|
|
|
|
}
|