mirror of
https://github.com/TheAnachronism/docspell.git
synced 2024-11-13 02:31:10 +00:00
163 lines
3.0 KiB
Elm
163 lines
3.0 KiB
Elm
|
port module Search exposing (..)
|
||
|
|
||
|
import Browser exposing (Document)
|
||
|
import Browser.Navigation exposing (Key)
|
||
|
import Html as H exposing (..)
|
||
|
import Html.Attributes exposing (..)
|
||
|
import Html.Events exposing (onClick, onInput, onSubmit)
|
||
|
import Json.Decode as D
|
||
|
import Markdown
|
||
|
|
||
|
|
||
|
|
||
|
-- MAIN
|
||
|
|
||
|
|
||
|
main : Program Flags Model Msg
|
||
|
main =
|
||
|
Browser.element
|
||
|
{ init = init
|
||
|
, view = view
|
||
|
, update = update
|
||
|
, subscriptions = subscriptions
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
--- Model
|
||
|
|
||
|
|
||
|
type alias Flags =
|
||
|
{}
|
||
|
|
||
|
|
||
|
type alias Doc =
|
||
|
{ body : String
|
||
|
, title : String
|
||
|
, id : String
|
||
|
}
|
||
|
|
||
|
|
||
|
type alias SearchEntry =
|
||
|
{ ref : String
|
||
|
, score : Float
|
||
|
, doc : Doc
|
||
|
}
|
||
|
|
||
|
|
||
|
type alias Model =
|
||
|
{ searchInput : String
|
||
|
, results : List SearchEntry
|
||
|
}
|
||
|
|
||
|
|
||
|
type Msg
|
||
|
= SetSearch String
|
||
|
| SubmitSearch
|
||
|
| GetSearchResults (List SearchEntry)
|
||
|
|
||
|
|
||
|
|
||
|
--- Init
|
||
|
|
||
|
|
||
|
init : Flags -> ( Model, Cmd Msg )
|
||
|
init flags =
|
||
|
( { searchInput = ""
|
||
|
, results = []
|
||
|
}
|
||
|
, Cmd.none
|
||
|
)
|
||
|
|
||
|
|
||
|
|
||
|
--- Update
|
||
|
|
||
|
|
||
|
update : Msg -> Model -> ( Model, Cmd Msg )
|
||
|
update msg model =
|
||
|
case msg of
|
||
|
SetSearch str ->
|
||
|
( { model | searchInput = str }
|
||
|
, Cmd.none
|
||
|
)
|
||
|
|
||
|
SubmitSearch ->
|
||
|
( model, doSearch model.searchInput )
|
||
|
|
||
|
GetSearchResults list ->
|
||
|
( { model | results = List.take 8 list }, Cmd.none )
|
||
|
|
||
|
|
||
|
subscriptions : Model -> Sub Msg
|
||
|
subscriptions _ =
|
||
|
receiveSearch GetSearchResults
|
||
|
|
||
|
|
||
|
|
||
|
--- View
|
||
|
|
||
|
|
||
|
view : Model -> Html Msg
|
||
|
view model =
|
||
|
H.form
|
||
|
[ class "form"
|
||
|
, onSubmit SubmitSearch
|
||
|
]
|
||
|
[ div [ class "dropdown field is-active is-fullwidth" ]
|
||
|
[ div [ class "control has-icons-right is-fullwidth" ]
|
||
|
[ input
|
||
|
[ class "input"
|
||
|
, type_ "text"
|
||
|
, placeholder "Search docs…"
|
||
|
, onInput SetSearch
|
||
|
, value model.searchInput
|
||
|
]
|
||
|
[]
|
||
|
, span [ class "icon is-right is-small" ]
|
||
|
[ img [ src "/icons/search-20.svg" ] []
|
||
|
]
|
||
|
]
|
||
|
, viewResults model.results
|
||
|
]
|
||
|
]
|
||
|
|
||
|
|
||
|
viewResults : List SearchEntry -> Html Msg
|
||
|
viewResults entries =
|
||
|
div
|
||
|
[ classList
|
||
|
[ ( "dropdown-menu", True )
|
||
|
, ( "is-hidden", entries == [] )
|
||
|
]
|
||
|
]
|
||
|
[ div [ class "dropdown-content" ]
|
||
|
(List.intersperse
|
||
|
(div [ class "dropdown-divider" ] [])
|
||
|
(List.map viewResult entries)
|
||
|
)
|
||
|
]
|
||
|
|
||
|
|
||
|
viewResult : SearchEntry -> Html Msg
|
||
|
viewResult result =
|
||
|
div [ class "dropdown-item" ]
|
||
|
[ a
|
||
|
[ class "is-size-5"
|
||
|
, href result.ref
|
||
|
]
|
||
|
[ text result.doc.title
|
||
|
]
|
||
|
, Markdown.toHtml [ class "content" ] result.doc.body
|
||
|
]
|
||
|
|
||
|
|
||
|
|
||
|
--- Ports
|
||
|
|
||
|
|
||
|
port receiveSearch : (List SearchEntry -> msg) -> Sub msg
|
||
|
|
||
|
|
||
|
port doSearch : String -> Cmd msg
|