Commit 249321f5 authored by Alexandre Delanoë's avatar Alexandre Delanoë

[API] Search uniform table for docs and contact (WIP)

parent acd2ea75
-- TODO: this module should be replaced by FacetsTable
module Gargantext.Components.Category where
import Data.Argonaut (class DecodeJson, class EncodeJson, decodeJson, jsonEmptyObject, (.:), (:=), (~>), encodeJson)
import Data.Array as A
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Eq (genericEq)
import Data.Generic.Rep.Show (genericShow)
import Data.Lens ((^.))
import Data.Lens.At (at)
import Data.Lens.Record (prop)
import Data.List as L
import Data.Map (Map)
import Data.Map as Map
import Data.Maybe (Maybe(..), fromMaybe, isJust)
import Data.Ord.Down (Down(..))
import Data.Set (Set)
import Data.Set as Set
import Data.String as Str
import Data.Symbol (SProxy(..))
import Data.Tuple (Tuple(..), fst)
import Data.Tuple.Nested ((/\))
import DOM.Simple.Event as DE
import Effect (Effect)
import Effect.Aff (Aff, launchAff)
import Effect.Class (liftEffect)
import Reactix as R
import Reactix.DOM.HTML as H
------------------------------------------------------------------------
import Gargantext.Prelude
import Gargantext.Ends (Frontends, url)
import Gargantext.Hooks.Loader (useLoaderWithCacheAPI, HashedResponse(..))
import Gargantext.Utils.List (sortWith) as L
import Gargantext.Utils.Reactix as R2
import Gargantext.Routes as Routes
import Gargantext.Routes (SessionRoute(NodeAPI))
import Gargantext.Sessions (Session, sessionId, get, delete, put)
import Gargantext.Types (NodeType(..), OrderBy(..), TableResult, TabType, showTabType')
import Gargantext.Utils.CacheAPI as GUC
------------------------------------------------------------------------
data Category = Trash | UnRead | Checked | Topic | Favorite
categories :: Array Category
categories = [Trash, UnRead, Checked, Topic, Favorite]
derive instance genericFavorite :: Generic Category _
instance showCategory :: Show Category where
show = genericShow
instance eqCategory :: Eq Category where
eq = genericEq
instance decodeJsonCategory :: DecodeJson Category where
decodeJson json = do
obj <- decodeJson json
pure $ decodeCategory obj
instance encodeJsonCategory :: EncodeJson Category where
encodeJson cat = encodeJson (cat2score cat)
favCategory :: Category -> Category
favCategory Favorite = Topic
favCategory _ = Favorite
trashCategory :: Category -> Category
trashCategory _ = Trash
-- TODO: ?
--trashCategory Trash = UnRead
decodeCategory :: Int -> Category
decodeCategory 0 = Trash
decodeCategory 1 = UnRead
decodeCategory 2 = Checked
decodeCategory 3 = Topic
decodeCategory 4 = Favorite
decodeCategory _ = UnRead
cat2score :: Category -> Int
cat2score Trash = 0
cat2score UnRead = 1
cat2score Checked = 2
cat2score Topic = 3
cat2score Favorite = 4
-- caroussel :: Category -> R.Element
caroussel session nodeId setLocalCategories r cat = H.div {className:"flex"} divs
where
divs = map (\c -> if cat == c
then
H.div { className : icon c (cat == c) } []
else
H.div { className : icon c (cat == c)
, on: { click: onClick c}
} []
) (caroussel' cat)
caroussel' :: Category -> Array Category
caroussel' Trash = A.take 2 categories
caroussel' c = A.take 3 $ A.drop (cat2score c - 1 ) categories
onClick c = \_-> do
setLocalCategories $ Map.insert r._id c
void $ launchAff $ putCategories session nodeId $ CategoryQuery {nodeIds: [r._id], category: c}
icon :: Category -> Boolean -> String
icon cat b = btn b $ "glyphicon glyphicon-" <> (color $ size b $ icon' cat b)
where
icon' :: Category -> Boolean -> String
icon' Trash false = "remove"
icon' Trash true = "remove-sign"
icon' UnRead true = "question-sign"
icon' UnRead false = "question-sign"
icon' Checked true = "ok-sign"
icon' Checked false = "ok"
icon' Topic true = "star"
icon' Topic false = "star-empty"
icon' Favorite true = "heart"
icon' Favorite false = "heart-empty"
size :: Boolean -> String -> String
size true s = s <> " btn-lg"
size false s = s <> " btn-xs"
color :: String -> String
color x = x <> " text-primary"
btn :: Boolean -> String -> String
btn true s = s
btn false s = "btn " <> s
newtype CategoryQuery = CategoryQuery {
nodeIds :: Array Int
, category :: Category
}
instance encodeJsonCategoryQuery :: EncodeJson CategoryQuery where
encodeJson (CategoryQuery post) =
"ntc_nodesId" := post.nodeIds
~> "ntc_category" := encodeJson post.category
~> jsonEmptyObject
categoryRoute :: Int -> SessionRoute
categoryRoute nodeId = NodeAPI Node (Just nodeId) "category"
putCategories :: Session -> Int -> CategoryQuery -> Aff (Array Int)
putCategories session nodeId = put session $ categoryRoute nodeId
......@@ -28,7 +28,7 @@ import Reactix as R
import Reactix.DOM.HTML as H
------------------------------------------------------------------------
import Gargantext.Prelude
import Gargantext.Components.Category
import Gargantext.Components.Table as T
import Gargantext.Ends (Frontends, url)
import Gargantext.Hooks.Loader (useLoaderWithCacheAPI, HashedResponse(..))
......@@ -41,117 +41,6 @@ import Gargantext.Types (NodeType(..), OrderBy(..), TableResult, TabType, showTa
import Gargantext.Utils.CacheAPI as GUC
------------------------------------------------------------------------
data Category = Trash | UnRead | Checked | Topic | Favorite
categories :: Array Category
categories = [Trash, UnRead, Checked, Topic, Favorite]
derive instance genericFavorite :: Generic Category _
instance showCategory :: Show Category where
show = genericShow
instance eqCategory :: Eq Category where
eq = genericEq
instance decodeJsonCategory :: DecodeJson Category where
decodeJson json = do
obj <- decodeJson json
pure $ decodeCategory obj
instance encodeJsonCategory :: EncodeJson Category where
encodeJson cat = encodeJson (cat2score cat)
favCategory :: Category -> Category
favCategory Favorite = Topic
favCategory _ = Favorite
trashCategory :: Category -> Category
trashCategory _ = Trash
-- TODO: ?
--trashCategory Trash = UnRead
decodeCategory :: Int -> Category
decodeCategory 0 = Trash
decodeCategory 1 = UnRead
decodeCategory 2 = Checked
decodeCategory 3 = Topic
decodeCategory 4 = Favorite
decodeCategory _ = UnRead
cat2score :: Category -> Int
cat2score Trash = 0
cat2score UnRead = 1
cat2score Checked = 2
cat2score Topic = 3
cat2score Favorite = 4
-- caroussel :: Category -> R.Element
caroussel session nodeId setLocalCategories r cat = H.div {className:"flex"} divs
where
divs = map (\c -> if cat == c
then
H.div { className : icon c (cat == c) } []
else
H.div { className : icon c (cat == c)
, on: { click: onClick c}
} []
) (caroussel' cat)
caroussel' :: Category -> Array Category
caroussel' Trash = A.take 2 categories
caroussel' c = A.take 3 $ A.drop (cat2score c - 1 ) categories
onClick c = \_-> do
setLocalCategories $ Map.insert r._id c
void $ launchAff $ putCategories session nodeId $ CategoryQuery {nodeIds: [r._id], category: c}
icon :: Category -> Boolean -> String
icon cat b = btn b $ "glyphicon glyphicon-" <> (color $ size b $ icon' cat b)
where
icon' :: Category -> Boolean -> String
icon' Trash false = "remove"
icon' Trash true = "remove-sign"
icon' UnRead true = "question-sign"
icon' UnRead false = "question-sign"
icon' Checked true = "ok-sign"
icon' Checked false = "ok"
icon' Topic true = "star"
icon' Topic false = "star-empty"
icon' Favorite true = "heart"
icon' Favorite false = "heart-empty"
size :: Boolean -> String -> String
size true s = s <> " btn-lg"
size false s = s <> " btn-xs"
color :: String -> String
color x = x <> " text-primary"
btn :: Boolean -> String -> String
btn true s = s
btn false s = "btn " <> s
newtype CategoryQuery = CategoryQuery {
nodeIds :: Array Int
, category :: Category
}
instance encodeJsonCategoryQuery :: EncodeJson CategoryQuery where
encodeJson (CategoryQuery post) =
"ntc_nodesId" := post.nodeIds
~> "ntc_category" := encodeJson post.category
~> jsonEmptyObject
categoryRoute :: Int -> SessionRoute
categoryRoute nodeId = NodeAPI Node (Just nodeId) "category"
putCategories :: Session -> Int -> CategoryQuery -> Aff (Array Int)
putCategories session nodeId = put session $ categoryRoute nodeId
type TotalRecords = Int
type LayoutProps =
......
......@@ -3,27 +3,25 @@
-- has not been ported to this module yet.
module Gargantext.Components.FacetsTable where
import Prelude
------------------------------------------------------------------------
import Data.Argonaut (class DecodeJson, class EncodeJson, decodeJson, jsonEmptyObject, (.:), (:=), (~>))
import Data.Array (concat, filter)
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow)
import Data.List as L
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..), fromMaybe)
import Data.Set (Set)
import Data.String as String
import Data.Set as Set
import Data.Tuple (fst, snd)
import Data.Tuple.Nested ((/\))
import Effect (Effect)
import Effect.Aff (Aff, launchAff_)
import Reactix as R
import Reactix.DOM.HTML as H
------------------------------------------------------------------------
import Gargantext.Components.Category (Category(..), CategoryQuery(..), favCategory, decodeCategory, putCategories)
import Gargantext.Components.Search
import Gargantext.Components.Table as T
import Gargantext.Ends (url, Frontends)
import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Components.DocsTable (Category(..), CategoryQuery(..), favCategory, decodeCategory, putCategories)
import Gargantext.Components.Table as T
import Gargantext.Components.Search
import Gargantext.Routes (SessionRoute(Search, NodeAPI))
import Gargantext.Routes as Routes
import Gargantext.Sessions (Session, sessionId, post, deleteWithBody)
......@@ -31,6 +29,9 @@ import Gargantext.Types (NodeType(..), OrderBy(..), NodePath(..), NodeID)
import Gargantext.Utils (toggleSet, zeroPad)
import Gargantext.Utils.DecodeMaybe ((.|))
import Gargantext.Utils.Reactix as R2
import Prelude
import Reactix as R
import Reactix.DOM.HTML as H
------------------------------------------------------------------------
type Props =
......@@ -85,32 +86,6 @@ derive instance genericDocumentsView :: Generic DocumentsView _
instance showDocumentsView :: Show DocumentsView where
show = genericShow
--instance decodeHyperdata :: DecodeJson Hyperdata where
-- decodeJson json = do
-- obj <- decodeJson json
-- title <- obj .: "title"
-- source <- obj .: "source"
-- pure $ Hyperdata { title,source }
instance decodePair :: DecodeJson Pair where
decodeJson json = do
obj <- decodeJson json
id <- obj .: "id"
label <- obj .: "label"
pure $ Pair { id, label }
instance decodeHyperdata :: DecodeJson Hyperdata where
decodeJson json = do
obj <- decodeJson json
authors <- obj .| "authors"
title <- obj .| "title"
source <- obj .| "source"
publication_year <- obj .: "publication_year"
publication_month <- obj .: "publication_month"
publication_day <- obj .: "publication_day"
pure $ Hyperdata { authors, title, source, publication_year, publication_month, publication_day }
-- | Main layout of the Documents Tab of a Corpus
docView :: Record Props -> R.Element
docView props = R.createElement docViewCpt props []
......@@ -155,7 +130,7 @@ performDeletions session nodeId (deletions /\ setDeletions) =
markCategory :: Session -> NodeID -> Category -> Array NodeID -> Effect Unit
markCategory session nodeId category nids =
void $ launchAff_ $putCategories session nodeId (CategoryQuery q)
void $ launchAff_ $ putCategories session nodeId (CategoryQuery q)
where -- TODO add array of delete rows here
q = {nodeIds: nids, category: favCategory category}
......@@ -207,8 +182,8 @@ initialPagePath {session, nodeId, listId, query} = {session, nodeId, listId, que
loadPage :: PagePath -> Aff (Array DocumentsView)
loadPage {session, nodeId, listId, query, params: {limit, offset, orderBy, searchType}} = do
let p = Search { listId, offset, limit, orderBy: convOrderBy <$> orderBy } (Just nodeId)
res <- post session p $ SearchQuery {query, expected:searchType}
pure $ res2corpus res
searchResult <- post session p $ SearchQuery {query: concat query, expected:searchType}
pure $ res2view searchResult
where
convOrderBy (T.ASC (T.ColumnName "Date")) = DateAsc
convOrderBy (T.DESC (T.ColumnName "Date")) = DateDesc
......@@ -219,13 +194,12 @@ loadPage {session, nodeId, listId, query, params: {limit, offset, orderBy, searc
convOrderBy _ = DateAsc -- TODO
res2corpus :: SearchResult -> Array DocumentsView
res2corpus :: Document -> DocumentsView
res2corpus (Document { id
res2view :: SearchResult -> Array DocumentsView
res2view (SearchResultDoc {docs}) = map toView docs
where
toView :: Document -> DocumentsView
toView (Document { id
, created: date
, score
, category
, hyperdata: HyperdataDocument { authors
, title
, source
......@@ -233,24 +207,48 @@ res2corpus (Document { id
, publication_month
, publication_day
}
, category
, score
}
) =
DocumentsView { id
) = DocumentsView { id
, date
, title: fromMaybe "Title" title
, source: fromMaybe "Source" source
, score
, authors: fromMaybe "Authors" authors
, category: decodeCategory category
, pairs: []
, delete: false
, publication_year : fromMaybe 2020 publication_year
, publication_month: fromMaybe 1 publication_month
, publication_day : fromMaybe 1 publication_day
}
res2view (SearchResultContact {contacts}) = map toView contacts
where
toView :: Contact -> DocumentsView
toView (Contact { id
, created: date
, hyperdata: HyperdataContact { who
, title
, source
, "where": contactWhere
}
, score
, authors
, category
}
) = DocumentsView { id
, date
, title : fromMaybe "Title" title
, source: fromMaybe "Source" title
, score: 1
, authors: fromMaybe "Authors" title
, category: decodeCategory 1
, pairs: []
, delete: false
, publication_year
, publication_month
, publication_day
, publication_year: 2020
, publication_month: 10
, publication_day: 1
}
-- TODO Contact 2 view
-- res2view (SearchNoResult {message}) = map toView contacts
......
......@@ -5,7 +5,8 @@ import Data.Array (fromFoldable)
import Data.Tuple (Tuple(..), fst)
import Reactix as R
import Gargantext.Components.GraphExplorer.Types (GraphSideCorpus(..))
import Gargantext.Components.FacetsTable (TextQuery, docView)
import Gargantext.Components.FacetsTable (docView)
import Gargantext.Components.Search (TextQuery)
import Gargantext.Components.Table as T
import Gargantext.Components.Tab as Tab
import Gargantext.Ends (Frontends)
......
......@@ -5,6 +5,7 @@ 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 Gargantext.Components.Category (Category)
import Data.Maybe (Maybe(..))
import Gargantext.Prelude (class Eq, class Read, class Show)
......@@ -27,7 +28,7 @@ instance encodeJsonSearchType :: Argonaut.EncodeJson SearchType where
------------------------------------------------------------------------
data SearchQuery =
SearchQuery { query :: String
SearchQuery { query :: Array String
, expected :: SearchType
}
......@@ -43,7 +44,7 @@ instance encodeJsonSearchQuery :: Argonaut.EncodeJson SearchQuery where
------------------------------------------------------------------------
data SearchResult = SearchResultDoc { docs :: Array Document}
| SearchResultContact { contacts :: Array Contact }
| SearchNoResult { message :: String }
-- | SearchNoResult { message :: String }
derive instance eqSearchResult :: Eq SearchResult
derive instance genericSearchResult :: Generic SearchResult _
......@@ -61,8 +62,8 @@ data Document =
, created :: String
, title :: String
, hyperdata :: HyperdataDocument
, favorite :: Int
, score :: Number
, category :: Int
, score :: Int
}
derive instance eqDocument :: Eq Document
......@@ -113,7 +114,7 @@ data Contact =
Contact { id :: Int
, created :: String
, hyperdata :: HyperdataContact
, score :: Number
, score :: Int
}
derive instance eqContact :: Eq Contact
......
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