@@ -2,66 +2,71 @@ module Spago.Search.App.SearchResults where
3import Prelude
3import Prelude
5−import Spago.Search.App.SearchField (Message(..))
5+import Spago.Search.Declarations (loadDeclarations)
6−import Spago.Search.Declarations
6+import Spago.Search.Extra (whenJust)
7−import Spago.Search.Index
7+import Spago.Search.Index (SearchIndex, SearchResult, mkSearchIndex)
8−import Spago.Search.Extra
10−import CSS hiding (render,map)
11import Data.Array as Array
9import Data.Array as Array
10+import Data.Either (Either(..))
12import Data.List as List
11import Data.List as List
13−import Data.Maybe
12+import Data.Maybe (Maybe(..), isNothing)
14−import Data.Newtype
13+import Data.Newtype (unwrap, wrap)
15import Data.Search.Trie as Trie
14import Data.Search.Trie as Trie
16−import Data.String (null) as String
15+import Data.String (length) as String
17import Data.String.CodeUnits (toCharArray) as String
16import Data.String.CodeUnits (toCharArray) as String
18import Data.String.Common (toLower) as String
17import Data.String.Common (toLower) as String
19−import Effect.Aff
18+import Effect.Aff (Aff)
20−import Effect.Console
19+import Effect.Console (error)
21import Halogen as H
20import Halogen as H
22import Halogen.HTML as HH
21import Halogen.HTML as HH
23−import Halogen.HTML.CSS as HS
24−import Halogen.HTML.Events as HE
25import Halogen.HTML.Properties as HP
22import Halogen.HTML.Properties as HP
23+import Spago.Search.App.SearchField (Message(..))
24+import Web.DOM.Element (Element)
25+import Web.DOM.Element as Element
27−type State = { shown :: Boolean
28− , mbIndex :: Maybe SearchIndex
27+type State = { mbIndex :: Maybe SearchIndex
29 , results :: Array SearchResult
28 , results :: Array SearchResult
30 , input :: String
29 , input :: String
30+ , contents :: Element
33data Query a
33data Query a
34 = SearchFieldMessage Message a
34 = SearchFieldMessage Message a
36−component :: forall i o. H.Component HH.HTML Query i o Aff
36+mkComponent :: forall i o. Element -> H.Component HH.HTML Query i o Aff
37−component =
37+mkComponent contents =
38 H.mkComponent
38 H.mkComponent
39 { initialState:
39 { initialState:
40− const { mbIndex: Nothing, results: [], shown: false, input: "" }
40+ const { mbIndex: Nothing, results: [], input: "", contents }
42 , eval: H.mkEval $ H.defaultEval { handleQuery = handleQuery }
42 , eval: H.mkEval $ H.defaultEval { handleQuery = handleQuery }
45handleQuery :: forall o a. Query a -> H.HalogenM State Unit () o Aff (Maybe a)
45handleQuery :: forall o a. Query a -> H.HalogenM State Unit () o Aff (Maybe a)
46handleQuery (SearchFieldMessage Focused next) = do
46handleQuery (SearchFieldMessage Focused next) = do
47− H.modify_ (_ { shown = true })
48 state <- H.get
47 state <- H.get
49 when (isNothing state.mbIndex) do
48 when (isNothing state.mbIndex) do
50− declarations <- H.liftAff $ loadDeclarations "../spago-search-index.js"
49+ eiDeclarations <- H.liftAff $ loadDeclarations "../spago-search-index.js"
50+ case eiDeclarations of
53+ error $ "spago-search: couldn't load search index: " <> err
54+ Right declarations -> do
51− H.modify_ (_ { mbIndex = Just $ mkSearchIndex declarations })
55+ H.modify_ (_ { mbIndex = Just $ mkSearchIndex declarations })
52 pure Nothing
56 pure Nothing
53handleQuery (SearchFieldMessage LostFocus next) = do
57handleQuery (SearchFieldMessage LostFocus next) = do
54 state <- H.get
58 state <- H.get
55 when (Array.null state.results) do
59 when (Array.null state.results) do
56− H.modify_ (_ { shown = false })
60+ showPageContents
57 pure Nothing
61 pure Nothing
58handleQuery (SearchFieldMessage (InputUpdated input) next) = do
62handleQuery (SearchFieldMessage (InputUpdated input) next) = do
59 H.modify_ (_ { input = input })
63 H.modify_ (_ { input = input })
61− if String.null input
64+ if String.length input < 2
63 H.modify_ (_ { results = [] })
67 H.modify_ (_ { results = [] })
65 state <- H.get
70 state <- H.get
66 whenJust (unwrap <$> state.mbIndex) \index -> do
71 whenJust (unwrap <$> state.mbIndex) \index -> do
67 let path = List.fromFoldable $
72 let path = List.fromFoldable $
@@ -76,33 +81,91 @@ handleQuery (SearchFieldMessage (InputUpdated input) next) = do
77 pure Nothing
82 pure Nothing
84+showPageContents :: forall o. H.HalogenM State Unit () o Aff Unit
88+ Element.removeAttribute "style" state.contents
90+hidePageContents :: forall o. H.HalogenM State Unit () o Aff Unit
94+ Element.setAttribute "style" "display: none" state.contents
79render :: forall m. State -> H.ComponentHTML Unit () m
96render :: forall m. State -> H.ComponentHTML Unit () m
80−render { mbIndex: Nothing, shown: true } =
97+render { mbIndex: Nothing } =
81− renderSummary "Loading index..."
98+ HH.div_ []
82−render { mbIndex: Nothing, shown: false } =
99+render { input: "" } =
83 HH.div_ []
100 HH.div_ []
84−render state
101+render state =
85− | not state.shown || String.null state.input = HH.div_ []
102+ HH.div [ HP.classes [ wrap "container"
86− | otherwise =
103+ , wrap "clearfix"
89− float floatLeft
106+ if Array.null state.results
108+ [ renderSummary "No search results" ]
112+ show (Array.length state.results) <>
115+ [ HH.div [ HP.id_ "spage-search-results-container" ] $
117+ state.results <#> renderResult
91− if Array.null state.results
93− [ renderSummary "No search results" ]
97− show (Array.length state.results) <>
100− [ HH.div_ $ state.results <#> \result ->
101− HH.div_ [ HH.text (unwrap result).name ]
104renderSummary :: forall a b. String -> HH.HTML b a
120renderSummary :: forall a b. String -> HH.HTML b a
105renderSummary text =
121renderSummary text =
106 HH.div [ HP.id_ "spago-search-summary" ]
122 HH.div [ HP.id_ "spago-search-summary" ]
107 [ HH.text text
123 [ HH.text text
126+renderResult :: forall a b. SearchResult -> Array (HH.HTML a b)
127+renderResult = unwrap >>> \result ->
128+ [ HH.div [ HP.class_ (wrap "result") ]
129+ [ HH.h3 [ HP.class_ (wrap "result__title") ]
130+ [ HH.a [ HP.class_ (wrap "result__link") ]
131+ [ HH.text result.name ]
135+ , HH.div [ HP.class_ (wrap "result__body") ] $
136+ [ HH.pre [ HP.class_ (wrap "result__signature") ]
141+ case result.comments of
142+ Just comments -> [ HH.pre_
148+ , HH.div [ HP.class_ (wrap "result__actions") ]
149+ [ HH.span [ HP.class_ (wrap "result__actions__item") ]
150+ [ HH.span [ HP.classes [ wrap "badge"
151+ , wrap "badge--package"
153+ , HP.title "Package"
157+ , HH.text result.packageName
160+ , HH.span [ HP.class_ (wrap "result__actions__item") ]
161+ [ HH.span [ HP.classes [ wrap "badge"
162+ , wrap "badge--module"
168+ , HH.text result.moduleName