2020-09-29 22:17:18 +00:00
|
|
|
port module Search exposing (..)
|
|
|
|
|
2022-01-27 19:23:15 +00:00
|
|
|
import Browser
|
2020-09-29 22:17:18 +00:00
|
|
|
import Html as H exposing (..)
|
|
|
|
import Html.Attributes exposing (..)
|
|
|
|
import Html.Events exposing (onClick, onInput, onSubmit)
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-01-27 19:23:15 +00:00
|
|
|
type SearchState
|
|
|
|
= Initial
|
|
|
|
| Found (List SearchEntry)
|
|
|
|
|
|
|
|
|
2020-09-29 22:17:18 +00:00
|
|
|
type alias Model =
|
|
|
|
{ searchInput : String
|
2022-01-27 19:23:15 +00:00
|
|
|
, results : SearchState
|
|
|
|
, searchVisible : Bool
|
2020-09-29 22:17:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
type Msg
|
|
|
|
= SetSearch String
|
2022-01-27 19:23:15 +00:00
|
|
|
| ToggleBar
|
2020-09-29 22:17:18 +00:00
|
|
|
| SubmitSearch
|
|
|
|
| GetSearchResults (List SearchEntry)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--- Init
|
|
|
|
|
|
|
|
|
|
|
|
init : Flags -> ( Model, Cmd Msg )
|
|
|
|
init flags =
|
|
|
|
( { searchInput = ""
|
2022-01-27 19:23:15 +00:00
|
|
|
, results = Initial
|
|
|
|
, searchVisible = False
|
2020-09-29 22:17:18 +00:00
|
|
|
}
|
|
|
|
, Cmd.none
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--- Update
|
|
|
|
|
|
|
|
|
|
|
|
update : Msg -> Model -> ( Model, Cmd Msg )
|
|
|
|
update msg model =
|
|
|
|
case msg of
|
2022-01-27 19:23:15 +00:00
|
|
|
ToggleBar ->
|
|
|
|
( { model | searchVisible = not model.searchVisible }
|
|
|
|
, Cmd.none
|
|
|
|
)
|
|
|
|
|
2020-09-29 22:17:18 +00:00
|
|
|
SetSearch str ->
|
|
|
|
( { model | searchInput = str }
|
|
|
|
, Cmd.none
|
|
|
|
)
|
|
|
|
|
|
|
|
SubmitSearch ->
|
|
|
|
( model, doSearch model.searchInput )
|
|
|
|
|
|
|
|
GetSearchResults list ->
|
2022-01-27 19:23:15 +00:00
|
|
|
( { model | results = Found <| List.take 20 list }, Cmd.none )
|
2020-09-29 22:17:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
subscriptions : Model -> Sub Msg
|
|
|
|
subscriptions _ =
|
|
|
|
receiveSearch GetSearchResults
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--- View
|
|
|
|
|
|
|
|
|
|
|
|
view : Model -> Html Msg
|
|
|
|
view model =
|
2022-01-27 19:23:15 +00:00
|
|
|
div
|
|
|
|
[ class " inline-flex px-4 items-center hover:bg-amber-600 hover:bg-opacity-10 dark:hover:bg-stone-800"
|
2020-09-29 22:17:18 +00:00
|
|
|
]
|
2022-01-27 19:23:15 +00:00
|
|
|
[ a
|
|
|
|
[ href "#"
|
|
|
|
, class "h-full w-full inline-flex items-center"
|
|
|
|
, onClick ToggleBar
|
|
|
|
]
|
|
|
|
[ i [ class "fa fa-search" ] []
|
|
|
|
]
|
|
|
|
, div
|
|
|
|
[ class "absolute px-2 mx-2 right-0 max-w-screen-md rounded top-12 w-full border-l border-r border-b bg-white h-12 dark:bg-stone-800 dark:border-stone-700"
|
|
|
|
, classList [ ( "hidden", not model.searchVisible ) ]
|
|
|
|
]
|
|
|
|
[ H.form [ onSubmit SubmitSearch ]
|
2020-09-29 22:17:18 +00:00
|
|
|
[ input
|
2022-01-27 19:23:15 +00:00
|
|
|
[ type_ "text"
|
2020-09-29 22:17:18 +00:00
|
|
|
, value model.searchInput
|
2022-01-27 19:23:15 +00:00
|
|
|
, autofocus True
|
|
|
|
, placeholder "Search …"
|
|
|
|
, class "w-full block h-8 border-0 border-b border-stone-400 mt-2 focus:ring-0 focus:border-indigo-500 dark:bg-stone-800 dark:focus:border-cyan-400"
|
|
|
|
, onInput SetSearch
|
2020-09-29 22:17:18 +00:00
|
|
|
]
|
|
|
|
[]
|
2020-10-29 21:48:21 +00:00
|
|
|
]
|
2020-09-29 22:17:18 +00:00
|
|
|
, viewResults model.results
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
|
2022-01-27 19:23:15 +00:00
|
|
|
viewResults : SearchState -> Html Msg
|
|
|
|
viewResults state =
|
|
|
|
case state of
|
|
|
|
Initial ->
|
|
|
|
span [ class "hidden" ] []
|
|
|
|
|
|
|
|
Found [] ->
|
|
|
|
div
|
|
|
|
[ class "bg-white dark:bg-stone-800 mt-2 w-full"
|
|
|
|
]
|
|
|
|
[ div [ class "flex flex-row items-center h-14 justify-center text-xl" ]
|
|
|
|
[ i [ class "fa fa-meh font-thin mr-2" ]
|
|
|
|
[]
|
|
|
|
, text "No results."
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
Found entries ->
|
|
|
|
div
|
|
|
|
[ class "bg-white dark:bg-stone-800 mt-2 w-screen sm:w-full h-screen-12 md:h-fit md:max-h-96 overflow-auto shadow-lg border-l border-r border-b dark:border-stone-700"
|
|
|
|
]
|
|
|
|
[ div [ class "px-2 pt-2 pb-1 flex flex-col divide-y dark:divide-stone-700 " ]
|
|
|
|
(List.map viewResult entries)
|
|
|
|
]
|
2020-09-29 22:17:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
viewResult : SearchEntry -> Html Msg
|
|
|
|
viewResult result =
|
2022-01-27 19:23:15 +00:00
|
|
|
div [ class "py-2 content" ]
|
2020-09-29 22:17:18 +00:00
|
|
|
[ a
|
2022-01-27 19:23:15 +00:00
|
|
|
[ class "text-lg font-semibold"
|
2020-09-29 22:17:18 +00:00
|
|
|
, href result.ref
|
|
|
|
]
|
|
|
|
[ text result.doc.title
|
|
|
|
]
|
|
|
|
, Markdown.toHtml [ class "content" ] result.doc.body
|
|
|
|
]
|
|
|
|
|
|
|
|
|
2022-01-27 19:23:15 +00:00
|
|
|
textInput : String
|
|
|
|
textInput =
|
|
|
|
" placeholder-gray-400 w-full dark:text-slate-200 dark:bg-slate-800 dark:border-slate-500 border-gray-400 rounded " ++ formFocusRing
|
|
|
|
|
|
|
|
|
|
|
|
formFocusRing : String
|
|
|
|
formFocusRing =
|
|
|
|
" focus:ring focus:ring-black focus:ring-opacity-50 focus:ring-offset-0 dark:focus:ring-slate-400 "
|
|
|
|
|
|
|
|
|
2020-09-29 22:17:18 +00:00
|
|
|
|
|
|
|
--- Ports
|
|
|
|
|
|
|
|
|
|
|
|
port receiveSearch : (List SearchEntry -> msg) -> Sub msg
|
|
|
|
|
|
|
|
|
|
|
|
port doSearch : String -> Cmd msg
|