Commit acd2ea75 authored by Alexandre Delanoë's avatar Alexandre Delanoë

[API] Search API using generics (WIP)

parent f1338ec8
...@@ -23,6 +23,7 @@ import Gargantext.Ends (url, Frontends) ...@@ -23,6 +23,7 @@ import Gargantext.Ends (url, Frontends)
import Gargantext.Hooks.Loader (useLoader) import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Components.DocsTable (Category(..), CategoryQuery(..), favCategory, decodeCategory, putCategories) import Gargantext.Components.DocsTable (Category(..), CategoryQuery(..), favCategory, decodeCategory, putCategories)
import Gargantext.Components.Table as T import Gargantext.Components.Table as T
import Gargantext.Components.Search
import Gargantext.Routes (SessionRoute(Search, NodeAPI)) import Gargantext.Routes (SessionRoute(Search, NodeAPI))
import Gargantext.Routes as Routes import Gargantext.Routes as Routes
import Gargantext.Sessions (Session, sessionId, post, deleteWithBody) import Gargantext.Sessions (Session, sessionId, post, deleteWithBody)
...@@ -32,29 +33,6 @@ import Gargantext.Utils.DecodeMaybe ((.|)) ...@@ -32,29 +33,6 @@ import Gargantext.Utils.DecodeMaybe ((.|))
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
------------------------------------------------------------------------ ------------------------------------------------------------------------
type TotalRecords = Int
-- Example:
-- [["machine","learning"],["artificial","intelligence"]]
-- This searches for documents with "machine learning" or "artificial intelligence"
type TextQuery = Array (Array String)
newtype SearchQuery = SearchQuery { query :: TextQuery }
instance encodeJsonSearchQuery :: EncodeJson SearchQuery where
encodeJson (SearchQuery {query})
-- = "query" := query !! 0 -- TODO anoe
= "query" := concat query
~> jsonEmptyObject
newtype SearchResults = SearchResults { results :: Array Response }
instance decodeSearchResults :: DecodeJson SearchResults where
decodeJson json = do
obj <- decodeJson json
results <- obj .: "results"
pure $ SearchResults {results}
type Props = type Props =
( chart :: R.Element ( chart :: R.Element
, container :: Record T.TableContainerProps -> R.Element , container :: Record T.TableContainerProps -> R.Element
...@@ -107,26 +85,6 @@ derive instance genericDocumentsView :: Generic DocumentsView _ ...@@ -107,26 +85,6 @@ derive instance genericDocumentsView :: Generic DocumentsView _
instance showDocumentsView :: Show DocumentsView where instance showDocumentsView :: Show DocumentsView where
show = genericShow show = genericShow
newtype Response = Response
{ id :: Int
, created :: String
, hyperdata :: Hyperdata
, category :: Category
, ngramCount :: Int
-- , date :: String
-- , score :: Int
-- , pairs :: Array Pair
}
newtype Hyperdata = Hyperdata
{ authors :: String
, title :: String
, source :: String
, publication_year :: Int
, publication_month :: Int
, publication_day :: Int
}
--instance decodeHyperdata :: DecodeJson Hyperdata where --instance decodeHyperdata :: DecodeJson Hyperdata where
-- decodeJson json = do -- decodeJson json = do
-- obj <- decodeJson json -- obj <- decodeJson json
...@@ -152,29 +110,6 @@ instance decodeHyperdata :: DecodeJson Hyperdata where ...@@ -152,29 +110,6 @@ instance decodeHyperdata :: DecodeJson Hyperdata where
publication_day <- obj .: "publication_day" publication_day <- obj .: "publication_day"
pure $ Hyperdata { authors, title, source, publication_year, publication_month, publication_day } pure $ Hyperdata { authors, title, source, publication_year, publication_month, publication_day }
{-
instance decodeResponse :: DecodeJson Response where
decodeJson json = do
obj <- decodeJson json
id <- obj .: "id"
-- date <- obj .: "date" -- TODO
date <- pure "2018"
score <- obj .: "score"
hyperdata <- obj .: "hyperdata"
pairs <- obj .: "pairs"
pure $ Response { id, date, score, hyperdata, pairs }
-}
instance decodeResponse :: DecodeJson Response where
decodeJson json = do
obj <- decodeJson json
id <- obj .: "id"
created <- obj .: "created"
hyperdata <- obj .: "hyperdata"
favorite <- obj .: "favorite"
--ngramCount <- obj .: "ngramCount"
let ngramCount = 1
pure $ Response { id, created, hyperdata, category: decodeCategory favorite, ngramCount}
-- | Main layout of the Documents Tab of a Corpus -- | Main layout of the Documents Tab of a Corpus
docView :: Record Props -> R.Element docView :: Record Props -> R.Element
...@@ -270,14 +205,36 @@ initialPagePath :: {session :: Session, nodeId :: Int, listId :: Int, query :: T ...@@ -270,14 +205,36 @@ initialPagePath :: {session :: Session, nodeId :: Int, listId :: Int, query :: T
initialPagePath {session, nodeId, listId, query} = {session, nodeId, listId, query, params: T.initialParams} initialPagePath {session, nodeId, listId, query} = {session, nodeId, listId, query, params: T.initialParams}
loadPage :: PagePath -> Aff (Array DocumentsView) loadPage :: PagePath -> Aff (Array DocumentsView)
loadPage {session, nodeId, listId, query, params: {limit, offset, orderBy}} = do loadPage {session, nodeId, listId, query, params: {limit, offset, orderBy, searchType}} = do
let p = Search { listId, offset, limit, orderBy: convOrderBy <$> orderBy } (Just nodeId) let p = Search { listId, offset, limit, orderBy: convOrderBy <$> orderBy } (Just nodeId)
SearchResults res <- post session p $ SearchQuery {query} res <- post session p $ SearchQuery {query, expected:searchType}
pure $ res2corpus <$> res.results pure $ res2corpus res
where where
res2corpus :: Response -> DocumentsView convOrderBy (T.ASC (T.ColumnName "Date")) = DateAsc
res2corpus (Response { id, created: date, ngramCount: score, category convOrderBy (T.DESC (T.ColumnName "Date")) = DateDesc
, hyperdata: Hyperdata {authors, title, source, publication_year, publication_month, publication_day} }) = convOrderBy (T.ASC (T.ColumnName "Title")) = TitleAsc
convOrderBy (T.DESC (T.ColumnName "Title")) = TitleDesc
convOrderBy (T.ASC (T.ColumnName "Source")) = SourceAsc
convOrderBy (T.DESC (T.ColumnName "Source")) = SourceDesc
convOrderBy _ = DateAsc -- TODO
res2corpus :: SearchResult -> Array DocumentsView
res2corpus :: Document -> DocumentsView
res2corpus (Document { id
, created: date
, score
, category
, hyperdata: HyperdataDocument { authors
, title
, source
, publication_year
, publication_month
, publication_day
}
}
) =
DocumentsView { id DocumentsView { id
, date , date
, title , title
...@@ -291,13 +248,11 @@ loadPage {session, nodeId, listId, query, params: {limit, offset, orderBy}} = do ...@@ -291,13 +248,11 @@ loadPage {session, nodeId, listId, query, params: {limit, offset, orderBy}} = do
, publication_month , publication_month
, publication_day , publication_day
} }
convOrderBy (T.ASC (T.ColumnName "Date")) = DateAsc
convOrderBy (T.DESC (T.ColumnName "Date")) = DateDesc -- TODO Contact 2 view
convOrderBy (T.ASC (T.ColumnName "Title")) = TitleAsc
convOrderBy (T.DESC (T.ColumnName "Title")) = TitleDesc
convOrderBy (T.ASC (T.ColumnName "Source")) = SourceAsc
convOrderBy (T.DESC (T.ColumnName "Source")) = SourceDesc
convOrderBy _ = DateAsc -- TODO
type PageLayoutProps = type PageLayoutProps =
( frontends :: Frontends ( frontends :: Frontends
......
...@@ -13,6 +13,7 @@ import Reactix as R ...@@ -13,6 +13,7 @@ import Reactix as R
import Thermite (PerformAction, Render, Spec, simpleSpec, createClass) import Thermite (PerformAction, Render, Spec, simpleSpec, createClass)
import Gargantext.Components.AutoUpdate (autoUpdateElt) import Gargantext.Components.AutoUpdate (autoUpdateElt)
import Gargantext.Components.Search (SearchType(..))
import Gargantext.Components.Node (NodePoly(..)) import Gargantext.Components.Node (NodePoly(..))
import Gargantext.Components.NgramsTable.Core import Gargantext.Components.NgramsTable.Core
( CoreState, NgramsPatch(..), NgramsTerm, Replace, Versioned(..) ( CoreState, NgramsPatch(..), NgramsTerm, Replace, Versioned(..)
...@@ -389,7 +390,7 @@ loadData {session, nodeId, listIds, tabType} = do ...@@ -389,7 +390,7 @@ loadData {session, nodeId, listIds, tabType} = do
{ session { session
, nodeId , nodeId
, listIds , listIds
, params: { offset : 0, limit : 100, orderBy: Nothing} , params: { offset : 0, limit : 100, orderBy: Nothing, searchType: SearchDoc}
, tabType , tabType
, searchQuery: "" , searchQuery: ""
, termListFilter: Nothing , termListFilter: Nothing
......
module Gargantext.Components.Search where
------------------------------------------------------------------------
import Data.Argonaut as Argonaut
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow)
import Gargantext.Utils.Argonaut (genericSumDecodeJson, genericSumEncodeJson, genericEnumDecodeJson, genericEnumEncodeJson)
import Data.Maybe (Maybe(..))
import Gargantext.Prelude (class Eq, class Read, class Show)
-- Example:
-- [["machine","learning"],["artificial","intelligence"]]
-- This searches for documents with "machine learning" or "artificial intelligence"
type TextQuery = Array (Array String)
------------------------------------------------------------------------
data SearchType = SearchDoc | SearchContact
derive instance eqSearchType :: Eq SearchType
derive instance genericSearchType :: Generic SearchType _
instance showSearchType :: Show SearchType where
show = genericShow
instance decodeJsonSearchType :: Argonaut.DecodeJson SearchType where
decodeJson = genericSumDecodeJson
instance encodeJsonSearchType :: Argonaut.EncodeJson SearchType where
encodeJson = genericSumEncodeJson
------------------------------------------------------------------------
data SearchQuery =
SearchQuery { query :: String
, expected :: SearchType
}
derive instance eqSearchQuery :: Eq SearchQuery
derive instance genericSearchQuery :: Generic SearchQuery _
instance showSearchQuery :: Show SearchQuery where
show = genericShow
instance decodeJsonSearchQuery :: Argonaut.DecodeJson SearchQuery where
decodeJson = genericSumDecodeJson
instance encodeJsonSearchQuery :: Argonaut.EncodeJson SearchQuery where
encodeJson = genericSumEncodeJson
------------------------------------------------------------------------
data SearchResult = SearchResultDoc { docs :: Array Document}
| SearchResultContact { contacts :: Array Contact }
| SearchNoResult { message :: String }
derive instance eqSearchResult :: Eq SearchResult
derive instance genericSearchResult :: Generic SearchResult _
instance showSearchResult :: Show SearchResult where
show = genericShow
instance decodeJsonSearchResult :: Argonaut.DecodeJson SearchResult where
decodeJson = genericSumDecodeJson
instance encodeJsonSearchResult :: Argonaut.EncodeJson SearchResult where
encodeJson = genericSumEncodeJson
------------------------------------------------------------------------
data Document =
Document { id :: Int
, created :: String
, title :: String
, hyperdata :: HyperdataDocument
, favorite :: Int
, score :: Number
}
derive instance eqDocument :: Eq Document
derive instance genericDocument :: Generic Document _
instance showDocument :: Show Document where
show = genericShow
instance decodeJsonDocument :: Argonaut.DecodeJson Document where
decodeJson = genericSumDecodeJson
instance encodeJsonDocument :: Argonaut.EncodeJson Document where
encodeJson = genericSumEncodeJson
------------------------------------------------------------------------
data HyperdataDocument =
HyperdataDocument { bdd :: Maybe String
, doi :: Maybe String
, url :: Maybe String
, uniqId :: Maybe String
, uniqIdBdd :: Maybe String
, page :: Maybe Int
, title :: Maybe String
, authors :: Maybe String
, institutes :: Maybe String
, source :: Maybe String
, abstract :: Maybe String
, publication_date :: Maybe String
, publication_year :: Maybe Int
, publication_month :: Maybe Int
, publication_day :: Maybe Int
, publication_hour :: Maybe Int
, publication_minute :: Maybe Int
, publication_second :: Maybe Int
, language_iso2 :: Maybe String
}
derive instance eqHyperdataDocument :: Eq HyperdataDocument
derive instance genericHyperdataDocument :: Generic HyperdataDocument _
instance showHyperdataDocument :: Show HyperdataDocument where
show = genericShow
instance decodeJsonHyperdataDocument :: Argonaut.DecodeJson HyperdataDocument where
decodeJson = genericSumDecodeJson
instance encodeJsonHyperdataDocument :: Argonaut.EncodeJson HyperdataDocument where
encodeJson = genericSumEncodeJson
------------------------------------------------------------------------
------------------------------------------------------------------------
------------------------------------------------------------------------
data Contact =
Contact { id :: Int
, created :: String
, hyperdata :: HyperdataContact
, score :: Number
}
derive instance eqContact :: Eq Contact
derive instance genericContact :: Generic Contact _
instance showContact :: Show Contact where
show = genericShow
instance decodeJsonContact :: Argonaut.DecodeJson Contact where
decodeJson = genericSumDecodeJson
instance encodeJsonContact :: Argonaut.EncodeJson Contact where
encodeJson = genericSumEncodeJson
data HyperdataContact =
HyperdataContact { bdd :: Maybe String
, who :: Maybe ContactWho
, "where" :: Array ContactWhere
, title :: Maybe String
, source :: Maybe String
, lastValidation :: Maybe String
, uniqIdBdd :: Maybe String
, uniqId :: Maybe String
}
derive instance eqHyperdataContact :: Eq HyperdataContact
derive instance genericHyperdataContact :: Generic HyperdataContact _
instance showHyperdataContact :: Show HyperdataContact where
show = genericShow
instance decodeJsonHyperdataContact :: Argonaut.DecodeJson HyperdataContact where
decodeJson = genericSumDecodeJson
instance encodeJsonHyperdataContact :: Argonaut.EncodeJson HyperdataContact where
encodeJson = genericSumEncodeJson
-------
data ContactWho =
ContactWho { id :: Maybe String
, firstName :: Maybe String
, lastName :: Maybe String
, keywords :: Array String
, freetags :: Array String
}
derive instance eqContactWho :: Eq ContactWho
derive instance genericContactWho :: Generic ContactWho _
instance showContactWho :: Show ContactWho where
show = genericShow
instance decodeJsonContactWho :: Argonaut.DecodeJson ContactWho where
decodeJson = genericSumDecodeJson
instance encodeJsonContactWho :: Argonaut.EncodeJson ContactWho where
encodeJson = genericSumEncodeJson
data ContactWhere =
ContactWhere { organization :: Array String
, labTeamDepts :: Array String
, role :: Maybe String
, office :: Maybe String
, country :: Maybe String
, city :: Maybe String
, touch :: Maybe ContactTouch
, entry :: Maybe String
, exit :: Maybe String
}
derive instance eqContactWhere :: Eq ContactWhere
derive instance genericContactWhere :: Generic ContactWhere _
instance showContactWhere :: Show ContactWhere where
show = genericShow
instance decodeJsonContactWhere :: Argonaut.DecodeJson ContactWhere where
decodeJson = genericSumDecodeJson
instance encodeJsonContactWhere :: Argonaut.EncodeJson ContactWhere where
encodeJson = genericSumEncodeJson
data ContactTouch =
ContactTouch { mail :: Maybe String
, phone :: Maybe String
, url :: Maybe String
}
derive instance eqContactTouch :: Eq ContactTouch
derive instance genericContactTouch :: Generic ContactTouch _
instance showContactTouch :: Show ContactTouch where
show = genericShow
instance decodeJsonContactTouch :: Argonaut.DecodeJson ContactTouch where
decodeJson = genericSumDecodeJson
instance encodeJsonContactTouch :: Argonaut.EncodeJson ContactTouch where
encodeJson = genericSumEncodeJson
...@@ -13,6 +13,7 @@ import Reactix as R ...@@ -13,6 +13,7 @@ import Reactix as R
import Reactix.DOM.HTML as H import Reactix.DOM.HTML as H
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Reactix (effectLink) import Gargantext.Utils.Reactix (effectLink)
import Gargantext.Components.Search
type TableContainerProps = type TableContainerProps =
( pageSizeControl :: R.Element ( pageSizeControl :: R.Element
...@@ -27,7 +28,11 @@ type Rows = L.List Row ...@@ -27,7 +28,11 @@ type Rows = L.List Row
type OrderBy = Maybe (OrderByDirection ColumnName) type OrderBy = Maybe (OrderByDirection ColumnName)
type Params = { offset :: Int, limit :: Int, orderBy :: OrderBy } type Params = { offset :: Int
, limit :: Int
, orderBy :: OrderBy
, searchType :: SearchType
}
newtype ColumnName = ColumnName String newtype ColumnName = ColumnName String
...@@ -64,16 +69,17 @@ type State = ...@@ -64,16 +69,17 @@ type State =
{ page :: Int { page :: Int
, pageSize :: PageSizes , pageSize :: PageSizes
, orderBy :: OrderBy , orderBy :: OrderBy
, searchType :: SearchType
} }
paramsState :: Params -> State paramsState :: Params -> State
paramsState {offset, limit, orderBy} = {pageSize, page, orderBy} paramsState {offset, limit, orderBy, searchType} = {pageSize, page, orderBy, searchType}
where where
pageSize = int2PageSizes limit pageSize = int2PageSizes limit
page = offset / limit + 1 page = offset / limit + 1
stateParams :: State -> Params stateParams :: State -> Params
stateParams {pageSize, page, orderBy} = {offset, limit, orderBy} stateParams {pageSize, page, orderBy, searchType} = {offset, limit, orderBy, searchType}
where where
limit = pageSizes2Int pageSize limit = pageSizes2Int pageSize
offset = limit * (page - 1) offset = limit * (page - 1)
...@@ -87,7 +93,7 @@ type TableHeaderLayoutProps = ...@@ -87,7 +93,7 @@ type TableHeaderLayoutProps =
) )
initialParams :: Params initialParams :: Params
initialParams = stateParams {page: 1, pageSize: PS10, orderBy: Nothing} initialParams = stateParams {page: 1, pageSize: PS10, orderBy: Nothing, searchType: SearchDoc}
-- TODO: Not sure this is the right place for this -- TODO: Not sure this is the right place for this
tableHeaderLayout :: Record TableHeaderLayoutProps -> R.Element tableHeaderLayout :: Record TableHeaderLayoutProps -> R.Element
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment