add style to the search result
This commit is contained in:
parent
f19216fe5a
commit
40bd247ee9
|
@ -54,6 +54,7 @@ def get_packages(evaluation):
|
||||||
check=True,
|
check=True,
|
||||||
)
|
)
|
||||||
packages = json.loads(result.stdout).items()
|
packages = json.loads(result.stdout).items()
|
||||||
|
packages = list(packages)[:10]
|
||||||
|
|
||||||
def gen():
|
def gen():
|
||||||
for attr_name, data in packages:
|
for attr_name, data in packages:
|
||||||
|
@ -87,7 +88,14 @@ def get_packages(evaluation):
|
||||||
)
|
)
|
||||||
for maintainer in data["meta"].get("maintainers", [])
|
for maintainer in data["meta"].get("maintainers", [])
|
||||||
]
|
]
|
||||||
|
platforms = [
|
||||||
|
type(platform) == str
|
||||||
|
and platform
|
||||||
|
or None
|
||||||
|
for platform in data["meta"].get("platforms", [])
|
||||||
|
]
|
||||||
yield dict(
|
yield dict(
|
||||||
|
id=attr_name,
|
||||||
attr_name=attr_name,
|
attr_name=attr_name,
|
||||||
name=data["pname"],
|
name=data["pname"],
|
||||||
version=data["version"],
|
version=data["version"],
|
||||||
|
@ -95,6 +103,7 @@ def get_packages(evaluation):
|
||||||
longDescription=data["meta"].get("longDescription", ""),
|
longDescription=data["meta"].get("longDescription", ""),
|
||||||
license=licenses,
|
license=licenses,
|
||||||
maintainers=maintainers,
|
maintainers=maintainers,
|
||||||
|
platforms=[i for i in platforms if i],
|
||||||
position=position,
|
position=position,
|
||||||
homepage=data["meta"].get("homepage"),
|
homepage=data["meta"].get("homepage"),
|
||||||
)
|
)
|
||||||
|
@ -114,6 +123,7 @@ def get_options(evaluation):
|
||||||
if os.path.exists(options_file):
|
if os.path.exists(options_file):
|
||||||
with open(options_file) as f:
|
with open(options_file) as f:
|
||||||
options = json.load(f).items()
|
options = json.load(f).items()
|
||||||
|
options = list(options)[:10]
|
||||||
|
|
||||||
def gen():
|
def gen():
|
||||||
for name, option in options:
|
for name, option in options:
|
||||||
|
@ -123,6 +133,7 @@ def get_options(evaluation):
|
||||||
example.get("_type") == "literalExample":
|
example.get("_type") == "literalExample":
|
||||||
example = str(example["text"])
|
example = str(example["text"])
|
||||||
yield dict(
|
yield dict(
|
||||||
|
id=name,
|
||||||
option_name=name,
|
option_name=name,
|
||||||
description=option.get("description"),
|
description=option.get("description"),
|
||||||
type=option.get("type"),
|
type=option.get("type"),
|
||||||
|
@ -133,6 +144,7 @@ def get_options(evaluation):
|
||||||
|
|
||||||
return len(options), gen
|
return len(options), gen
|
||||||
|
|
||||||
|
|
||||||
def recreate_index(es, channel):
|
def recreate_index(es, channel):
|
||||||
if es.indices.exists(f"{channel}-packages"):
|
if es.indices.exists(f"{channel}-packages"):
|
||||||
es.indices.delete(index=f"{channel}-packages")
|
es.indices.delete(index=f"{channel}-packages")
|
||||||
|
@ -162,6 +174,7 @@ def recreate_index(es, channel):
|
||||||
github=dict(type="text"),
|
github=dict(type="text"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
platforms=dict(type="keyword"),
|
||||||
position=dict(type="text"),
|
position=dict(type="text"),
|
||||||
homepage=dict(type="text"),
|
homepage=dict(type="text"),
|
||||||
),
|
),
|
||||||
|
|
288
src/Main.elm
288
src/Main.elm
|
@ -6,19 +6,33 @@ import Browser.Navigation as Nav exposing (Key)
|
||||||
import Html
|
import Html
|
||||||
exposing
|
exposing
|
||||||
( Html
|
( Html
|
||||||
|
, a
|
||||||
, button
|
, button
|
||||||
, div
|
, div
|
||||||
|
, footer
|
||||||
|
, form
|
||||||
, h1
|
, h1
|
||||||
, header
|
, header
|
||||||
|
, img
|
||||||
, input
|
, input
|
||||||
, li
|
, li
|
||||||
|
, p
|
||||||
, pre
|
, pre
|
||||||
|
, table
|
||||||
|
, tbody
|
||||||
|
, td
|
||||||
, text
|
, text
|
||||||
|
, th
|
||||||
|
, thead
|
||||||
|
, tr
|
||||||
, ul
|
, ul
|
||||||
)
|
)
|
||||||
import Html.Attributes
|
import Html.Attributes
|
||||||
exposing
|
exposing
|
||||||
( class
|
( class
|
||||||
|
, colspan
|
||||||
|
, href
|
||||||
|
, src
|
||||||
, type_
|
, type_
|
||||||
, value
|
, value
|
||||||
)
|
)
|
||||||
|
@ -26,6 +40,7 @@ import Html.Events
|
||||||
exposing
|
exposing
|
||||||
( onClick
|
( onClick
|
||||||
, onInput
|
, onInput
|
||||||
|
, onSubmit
|
||||||
)
|
)
|
||||||
import Http
|
import Http
|
||||||
import Json.Decode as D
|
import Json.Decode as D
|
||||||
|
@ -33,6 +48,7 @@ import Json.Decode.Pipeline as DP
|
||||||
import Json.Encode as E
|
import Json.Encode as E
|
||||||
import RemoteData as R
|
import RemoteData as R
|
||||||
import Url exposing (Url)
|
import Url exposing (Url)
|
||||||
|
import Url.Builder as UrlBuilder
|
||||||
import Url.Parser as UrlParser
|
import Url.Parser as UrlParser
|
||||||
exposing
|
exposing
|
||||||
( (<?>)
|
( (<?>)
|
||||||
|
@ -64,8 +80,9 @@ type alias Model =
|
||||||
|
|
||||||
|
|
||||||
type alias SearchModel =
|
type alias SearchModel =
|
||||||
{ query : String
|
{ query : Maybe String
|
||||||
, result : R.WebData SearchResult
|
, result : R.WebData SearchResult
|
||||||
|
, showDetailsFor : Maybe String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -117,6 +134,7 @@ type alias SearchResultPackage =
|
||||||
, longDescription : Maybe String
|
, longDescription : Maybe String
|
||||||
, licenses : List SearchResultPackageLicense
|
, licenses : List SearchResultPackageLicense
|
||||||
, maintainers : List SearchResultPackageMaintainer
|
, maintainers : List SearchResultPackageMaintainer
|
||||||
|
, platforms : List String
|
||||||
, position : Maybe String
|
, position : Maybe String
|
||||||
, homepage : Maybe String
|
, homepage : Maybe String
|
||||||
}
|
}
|
||||||
|
@ -133,7 +151,7 @@ type alias SearchResultOption =
|
||||||
|
|
||||||
|
|
||||||
type alias SearchResultPackageLicense =
|
type alias SearchResultPackageLicense =
|
||||||
{ fullName : String
|
{ fullName : Maybe String
|
||||||
, url : Maybe String
|
, url : Maybe String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,21 +165,77 @@ type alias SearchResultPackageMaintainer =
|
||||||
|
|
||||||
emptySearch : Page
|
emptySearch : Page
|
||||||
emptySearch =
|
emptySearch =
|
||||||
SearchPage { query = "", result = R.NotAsked }
|
SearchPage
|
||||||
|
{ query = Nothing
|
||||||
|
, result = R.NotAsked
|
||||||
|
, showDetailsFor = Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
init : Flags -> Url -> Key -> ( Model, Cmd Msg )
|
init : Flags -> Url -> Key -> ( Model, Cmd Msg )
|
||||||
init flags url key =
|
init flags url key =
|
||||||
( { key = key
|
let
|
||||||
|
model =
|
||||||
|
{ key = key
|
||||||
, elasticsearchUrl = flags.elasticsearchUrl
|
, elasticsearchUrl = flags.elasticsearchUrl
|
||||||
, elasticsearchUsername = flags.elasticsearchUsername
|
, elasticsearchUsername = flags.elasticsearchUsername
|
||||||
, elasticsearchPassword = flags.elasticsearchPassword
|
, elasticsearchPassword = flags.elasticsearchPassword
|
||||||
, page = UrlParser.parse urlParser url |> Maybe.withDefault emptySearch
|
, page = UrlParser.parse urlParser url |> Maybe.withDefault emptySearch
|
||||||
}
|
}
|
||||||
, Cmd.none
|
in
|
||||||
|
( model
|
||||||
|
, initPageCmd model model
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
initPageCmd : Model -> Model -> Cmd Msg
|
||||||
|
initPageCmd oldModel model =
|
||||||
|
let
|
||||||
|
makeRequest query =
|
||||||
|
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
|
||||||
|
[ ( "attr_name"
|
||||||
|
, E.object
|
||||||
|
[ ( "query", E.string query )
|
||||||
|
|
||||||
|
-- I'm not sure we need fuziness
|
||||||
|
--, ( "fuzziness", E.int 1 )
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
, expect = Http.expectJson (R.fromResult >> SearchQueryResponse) decodeResult
|
||||||
|
, timeout = Nothing
|
||||||
|
, tracker = Nothing
|
||||||
|
}
|
||||||
|
in
|
||||||
|
case oldModel.page of
|
||||||
|
SearchPage oldSearchModel ->
|
||||||
|
case model.page of
|
||||||
|
SearchPage searchModel ->
|
||||||
|
if (oldSearchModel.query == searchModel.query) && R.isSuccess oldSearchModel.result then
|
||||||
|
Cmd.none
|
||||||
|
|
||||||
|
else
|
||||||
|
searchModel.query
|
||||||
|
|> Maybe.map makeRequest
|
||||||
|
|> Maybe.withDefault Cmd.none
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- ---------------------------
|
-- ---------------------------
|
||||||
-- URL Parsing and Routing
|
-- URL Parsing and Routing
|
||||||
|
@ -182,13 +256,14 @@ urlParser : Parser (Page -> msg) msg
|
||||||
urlParser =
|
urlParser =
|
||||||
UrlParser.oneOf
|
UrlParser.oneOf
|
||||||
[ UrlParser.map
|
[ UrlParser.map
|
||||||
(\q ->
|
(\query showDetailsFor ->
|
||||||
SearchPage
|
SearchPage
|
||||||
{ query = q |> Maybe.withDefault ""
|
{ query = query
|
||||||
, result = R.NotAsked
|
, result = R.NotAsked
|
||||||
|
, showDetailsFor = showDetailsFor
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
(UrlParser.s "search" <?> UrlParserQuery.string "query")
|
(UrlParser.s "search" <?> UrlParserQuery.string "query" <?> UrlParserQuery.string "showDetailsFor")
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -204,6 +279,7 @@ type Msg
|
||||||
| SearchPageInput String
|
| SearchPageInput String
|
||||||
| SearchQuerySubmit
|
| SearchQuerySubmit
|
||||||
| SearchQueryResponse (R.WebData SearchResult)
|
| SearchQueryResponse (R.WebData SearchResult)
|
||||||
|
| SearchShowPackageDetails String
|
||||||
|
|
||||||
|
|
||||||
decodeResult : D.Decoder SearchResult
|
decodeResult : D.Decoder SearchResult
|
||||||
|
@ -255,6 +331,7 @@ decodeResultPackage =
|
||||||
|> DP.required "longDescription" (D.nullable D.string)
|
|> DP.required "longDescription" (D.nullable D.string)
|
||||||
|> DP.required "license" (D.list decodeResultPackageLicense)
|
|> DP.required "license" (D.list decodeResultPackageLicense)
|
||||||
|> DP.required "maintainers" (D.list decodeResultPackageMaintainer)
|
|> DP.required "maintainers" (D.list decodeResultPackageMaintainer)
|
||||||
|
|> DP.required "platforms" (D.list D.string)
|
||||||
|> DP.required "position" (D.nullable D.string)
|
|> DP.required "position" (D.nullable D.string)
|
||||||
|> DP.required "homepage" (D.nullable D.string)
|
|> DP.required "homepage" (D.nullable D.string)
|
||||||
|
|
||||||
|
@ -262,7 +339,7 @@ decodeResultPackage =
|
||||||
decodeResultPackageLicense : D.Decoder SearchResultPackageLicense
|
decodeResultPackageLicense : D.Decoder SearchResultPackageLicense
|
||||||
decodeResultPackageLicense =
|
decodeResultPackageLicense =
|
||||||
D.map2 SearchResultPackageLicense
|
D.map2 SearchResultPackageLicense
|
||||||
(D.field "fullName" D.string)
|
(D.field "fullName" (D.nullable D.string))
|
||||||
(D.field "url" (D.nullable D.string))
|
(D.field "url" (D.nullable D.string))
|
||||||
|
|
||||||
|
|
||||||
|
@ -285,44 +362,6 @@ decodeResultOption =
|
||||||
(D.field "source" 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 )
|
update : Msg -> Model -> ( Model, Cmd Msg )
|
||||||
update message model =
|
update message model =
|
||||||
case message of
|
case message of
|
||||||
|
@ -340,18 +379,19 @@ update message model =
|
||||||
SearchPage
|
SearchPage
|
||||||
{ searchModel
|
{ searchModel
|
||||||
| result =
|
| result =
|
||||||
if searchModel.query == "" then
|
case searchModel.query of
|
||||||
R.NotAsked
|
Just query ->
|
||||||
|
|
||||||
else
|
|
||||||
R.Loading
|
R.Loading
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
R.NotAsked
|
||||||
}
|
}
|
||||||
|
|
||||||
newNewModel =
|
newNewModel =
|
||||||
{ newModel | page = newPage }
|
{ newModel | page = newPage }
|
||||||
in
|
in
|
||||||
( newNewModel
|
( newNewModel
|
||||||
, initPage newNewModel
|
, initPageCmd newModel newNewModel
|
||||||
)
|
)
|
||||||
|
|
||||||
SearchPageInput query ->
|
SearchPageInput query ->
|
||||||
|
@ -359,7 +399,7 @@ update message model =
|
||||||
| page =
|
| page =
|
||||||
case model.page of
|
case model.page of
|
||||||
SearchPage searchModel ->
|
SearchPage searchModel ->
|
||||||
SearchPage { searchModel | query = query }
|
SearchPage { searchModel | query = Just query }
|
||||||
}
|
}
|
||||||
, Cmd.none
|
, Cmd.none
|
||||||
)
|
)
|
||||||
|
@ -368,7 +408,7 @@ update message model =
|
||||||
case model.page of
|
case model.page of
|
||||||
SearchPage searchModel ->
|
SearchPage searchModel ->
|
||||||
( model
|
( model
|
||||||
, Nav.pushUrl model.key <| "/search?query=" ++ searchModel.query
|
, Nav.pushUrl model.key <| createSearchUrl searchModel
|
||||||
)
|
)
|
||||||
|
|
||||||
SearchQueryResponse result ->
|
SearchQueryResponse result ->
|
||||||
|
@ -382,6 +422,47 @@ update message model =
|
||||||
, Cmd.none
|
, Cmd.none
|
||||||
)
|
)
|
||||||
|
|
||||||
|
SearchShowPackageDetails showDetailsFor ->
|
||||||
|
case model.page of
|
||||||
|
SearchPage searchModel ->
|
||||||
|
let
|
||||||
|
newSearchModel =
|
||||||
|
{ searchModel
|
||||||
|
| showDetailsFor =
|
||||||
|
if searchModel.showDetailsFor == Just showDetailsFor then
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
else
|
||||||
|
Just showDetailsFor
|
||||||
|
}
|
||||||
|
in
|
||||||
|
( model
|
||||||
|
, Nav.pushUrl model.key <| createSearchUrl newSearchModel
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
createSearchUrl : SearchModel -> String
|
||||||
|
createSearchUrl model =
|
||||||
|
[]
|
||||||
|
|> List.append
|
||||||
|
(model.query
|
||||||
|
|> Maybe.map
|
||||||
|
(\query ->
|
||||||
|
[ UrlBuilder.string "query" query ]
|
||||||
|
)
|
||||||
|
|> Maybe.withDefault []
|
||||||
|
)
|
||||||
|
|> List.append
|
||||||
|
(model.showDetailsFor
|
||||||
|
|> Maybe.map
|
||||||
|
(\x ->
|
||||||
|
[ UrlBuilder.string "showDetailsFor" x
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|> Maybe.withDefault []
|
||||||
|
)
|
||||||
|
|> UrlBuilder.absolute [ "search" ]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- ---------------------------
|
-- ---------------------------
|
||||||
|
@ -391,27 +472,54 @@ update message model =
|
||||||
|
|
||||||
view : Model -> Html Msg
|
view : Model -> Html Msg
|
||||||
view model =
|
view model =
|
||||||
div [ class "container" ]
|
div []
|
||||||
[ header []
|
[ header []
|
||||||
[ h1 [] [ text "NixOS Search" ]
|
[ div [ class "navbar navbar-static-top" ]
|
||||||
|
[ div [ class "navbar-inner" ]
|
||||||
|
[ div [ class "container" ]
|
||||||
|
[ a [ class "brand", href "https://search.nixos.org" ]
|
||||||
|
[ img [ src "https://nixos.org/logo/nix-wiki.png", class "logo" ] []
|
||||||
]
|
]
|
||||||
, case model.page of
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, div [ class "container main" ]
|
||||||
|
[ case model.page of
|
||||||
SearchPage searchModel ->
|
SearchPage searchModel ->
|
||||||
searchPage searchModel
|
searchPage searchModel
|
||||||
|
, footer [] []
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
searchPage : SearchModel -> Html Msg
|
searchPage : SearchModel -> Html Msg
|
||||||
searchPage model =
|
searchPage model =
|
||||||
div []
|
div [ class "search-page" ]
|
||||||
[ div []
|
[ h1 [ class "page-header" ] [ text "Search for packages and options" ]
|
||||||
|
, div [ class "search-input" ]
|
||||||
|
[ form [ onSubmit SearchQuerySubmit ]
|
||||||
|
[ div [ class "input-append" ]
|
||||||
[ input
|
[ input
|
||||||
[ type_ "text"
|
[ type_ "text"
|
||||||
, onInput SearchPageInput
|
, onInput SearchPageInput
|
||||||
, value model.query
|
, value <| Maybe.withDefault "" model.query
|
||||||
]
|
]
|
||||||
[]
|
[]
|
||||||
, button [ onClick SearchQuerySubmit ] [ text "Search" ]
|
, div [ class "btn-group" ]
|
||||||
|
[ button [ class "btn" ] [ text "Search" ]
|
||||||
|
|
||||||
|
--TODO: and option to select the right channel+version+evaluation
|
||||||
|
--, button [ class "btn" ] [ text "Loading ..." ]
|
||||||
|
--, div [ class "popover bottom" ]
|
||||||
|
-- [ div [ class "arrow" ] []
|
||||||
|
-- , div [ class "popover-title" ] [ text "Select options" ]
|
||||||
|
-- , div [ class "popover-content" ]
|
||||||
|
-- [ p [] [ text "Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum." ] ]
|
||||||
|
-- ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
, case model.result of
|
, case model.result of
|
||||||
R.NotAsked ->
|
R.NotAsked ->
|
||||||
|
@ -421,26 +529,60 @@ searchPage model =
|
||||||
div [] [ text "Loading" ]
|
div [] [ text "Loading" ]
|
||||||
|
|
||||||
R.Success result ->
|
R.Success result ->
|
||||||
ul [] (searchPageResult result.hits)
|
searchPageResult model.showDetailsFor result.hits
|
||||||
|
|
||||||
R.Failure error ->
|
R.Failure error ->
|
||||||
div [] [ text "Error!", pre [] [ text (Debug.toString error) ] ]
|
div [] [ text "Error!", pre [] [ text (Debug.toString error) ] ]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
searchPageResult : SearchResultHits -> List (Html Msg)
|
searchPageResult : Maybe String -> SearchResultHits -> Html Msg
|
||||||
searchPageResult result =
|
searchPageResult showDetailsFor result =
|
||||||
List.map searchPageResultItem result.hits
|
div [ class "search-result" ]
|
||||||
|
[ table [ class "table table-hover" ]
|
||||||
|
[ thead []
|
||||||
|
[ tr []
|
||||||
|
[ th [] [ text "Attribute name" ]
|
||||||
|
, th [] [ text "Name" ]
|
||||||
|
, th [] [ text "Version" ]
|
||||||
|
, th [] [ text "Description" ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, tbody [] <| List.concatMap (searchPageResultItem showDetailsFor) result.hits
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
searchPageResultItem : SearchResultItem -> Html Msg
|
searchPageResultItem : Maybe String -> SearchResultItem -> List (Html Msg)
|
||||||
searchPageResultItem item =
|
searchPageResultItem showDetailsFor item =
|
||||||
-- case item.source of
|
case item.source of
|
||||||
-- Package package ->
|
Package package ->
|
||||||
-- li [] [ text package.attr_name ]
|
let
|
||||||
-- Option option ->
|
packageDetails =
|
||||||
-- li [] [ text option.option_name ]
|
if Just item.id == showDetailsFor then
|
||||||
li [] [ text <| Debug.toString item ]
|
[ td [ colspan 4 ] [ text "works!" ] ]
|
||||||
|
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
in
|
||||||
|
[ tr [ onClick <| SearchShowPackageDetails item.id ]
|
||||||
|
[ td [] [ text package.attr_name ]
|
||||||
|
, td [] [ text package.name ]
|
||||||
|
, td [] [ text package.version ]
|
||||||
|
, td [] [ text <| Maybe.withDefault "" package.description ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
++ packageDetails
|
||||||
|
|
||||||
|
Option option ->
|
||||||
|
[ tr
|
||||||
|
[]
|
||||||
|
[-- td [] [ text option.option_name ]
|
||||||
|
--, td [] [ text option.name ]
|
||||||
|
--, td [] [ text option.version ]
|
||||||
|
--, td [] [ text option.description ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,28 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
|
||||||
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Elm hotloading dev environment</title>
|
<title>Elm hotloading dev environment</title>
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
</body>
|
<script type="text/javascript" src="https://nixos.org/js/jquery.min.js"></script>
|
||||||
|
<script type="text/javascript" src="https://nixos.org/js/jquery-ui.min.js"></script>
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
|
||||||
|
<script type="text/javascript" src="https://nixos.org/bootstrap/js/bootstrap.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="https://nixos.org/bootstrap/css/bootstrap.min.css" />
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://nixos.org/bootstrap/css/bootstrap-responsive.min.css" />
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" />
|
||||||
|
|
||||||
|
<link rel="shortcut icon" type="image/png" href="https://nixos.org/favicon.png" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,30 +1,27 @@
|
||||||
@import '~purecss/build/pure.css';
|
|
||||||
|
|
||||||
body {
|
header .navbar a.brand {
|
||||||
background-color: #ddd;
|
line-height: 1.5em;
|
||||||
margin-top: 20px;
|
img.logo {
|
||||||
}
|
height: 1.5em;
|
||||||
.container {
|
margin-right: 0.5em;
|
||||||
max-width: 800px;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
img {
|
|
||||||
width: 60px;
|
|
||||||
margin-right: 30px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
.search-page {
|
||||||
margin-right: 15px;
|
.search-input {
|
||||||
}
|
text-align: center;
|
||||||
|
.input-append input {
|
||||||
.logo {
|
font-size: 24px;
|
||||||
background: url('images/logo.png');
|
height: 40px;
|
||||||
width: 60px;
|
}
|
||||||
height: 60px;
|
.input-append button {
|
||||||
background-size: cover;
|
font-size: 24px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.search-result {
|
||||||
|
tbody tr {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue