mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-21 09:58:26 +00:00
162
website/elm/Search.elm
Normal file
162
website/elm/Search.elm
Normal file
@ -0,0 +1,162 @@
|
||||
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
|
Reference in New Issue
Block a user