From e898585bfa517377b10902e5fe26b9db8f1a8ffd Mon Sep 17 00:00:00 2001
From: Przemek Kaminski <pk@intrepidus.pl>
Date: Fri, 6 Dec 2019 08:25:35 +0100
Subject: [PATCH] [Table] implement TableResult (with count) in multiple places

DocsTable
Annuaire
Corpus
---
 .../Components/Annotation/AnnotatedField.purs | 13 +++++----
 src/Gargantext/Components/DocsTable.purs      |  4 +--
 src/Gargantext/Components/Nodes/Annuaire.purs | 29 +++++++++----------
 src/Gargantext/Components/Nodes/Corpus.purs   |  6 ++--
 src/Gargantext/Types.purs                     |  4 +++
 src/Gargantext/Utils/Selection.purs           |  5 ++++
 6 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/src/Gargantext/Components/Annotation/AnnotatedField.purs b/src/Gargantext/Components/Annotation/AnnotatedField.purs
index 0a9cb989..ce9e6922 100644
--- a/src/Gargantext/Components/Annotation/AnnotatedField.purs
+++ b/src/Gargantext/Components/Annotation/AnnotatedField.purs
@@ -48,7 +48,7 @@ annotatedFieldComponent :: R.Component Props
 annotatedFieldComponent = R.hooksComponent "AnnotatedField" cpt
   where
     cpt {ngrams,setTermList,text} _ = do
-      menu /\ setMenu <- R.useState $ const Nothing
+      mMenu@(_ /\ setMenu) <- R.useState $ const Nothing
       let wrapperProps =
             { className: "annotated-field-wrapper" }
 
@@ -70,7 +70,7 @@ annotatedFieldComponent = R.hooksComponent "AnnotatedField" cpt
 
           runs =
             HTML.div { className: "annotated-field-runs" } $ map annotateRun compiled
-      pure $ HTML.div wrapperProps [maybeAddMenu setMenu runs menu]
+      pure $ HTML.div wrapperProps [maybeAddMenu mMenu runs]
 
 
 -- forall e. IsMouseEvent e => R2.Setter (Maybe AnnotationMenu) -> R2.Setter ? -> ? -> e -> Effect Unit
@@ -89,16 +89,17 @@ maybeShowMenu setMenu setTermList ngrams event = do
                 setTermList n list t
                 setMenu (const Nothing)
           E.preventDefault event
+          range <- Sel.getRange sel 0
+          log2 "[maybeShowMenu] selection range" $ Sel.rangeToTuple range
           setMenu (const $ Just { x, y, list, menuType: NewNgram, setList })
     Nothing -> pure unit
 
 maybeAddMenu
-  :: R2.Setter (Maybe AnnotationMenu)
+  :: R.State (Maybe AnnotationMenu)
   -> R.Element
-  -> Maybe AnnotationMenu
   -> R.Element
-maybeAddMenu setMenu e (Just props) = annotationMenu setMenu props <> e
-maybeAddMenu _ e _ = e
+maybeAddMenu (Just props /\ setMenu) e = annotationMenu setMenu props <> e
+maybeAddMenu _ e = e
 
 compile :: NgramsTable -> Maybe String -> Array (Tuple String (Maybe TermList))
 compile ngrams = maybe [] (highlightNgrams CTabTerms ngrams)
diff --git a/src/Gargantext/Components/DocsTable.purs b/src/Gargantext/Components/DocsTable.purs
index 668a579c..5ec3e165 100644
--- a/src/Gargantext/Components/DocsTable.purs
+++ b/src/Gargantext/Components/DocsTable.purs
@@ -34,7 +34,7 @@ import Gargantext.Utils.Reactix as R2
 import Gargantext.Routes as Routes
 import Gargantext.Routes (AppRoute, SessionRoute(NodeAPI))
 import Gargantext.Sessions (Session, sessionId, post, delete, put)
-import Gargantext.Types (NodeType(..), OrderBy(..), TabType, TabPostQuery(..))
+import Gargantext.Types (NodeType(..), OrderBy(..), TabType, TabPostQuery(..), AffTableResult)
 ------------------------------------------------------------------------
 
 data Category = Trash | UnRead | Checked | Topic | Favorite
@@ -339,7 +339,7 @@ loadPage session {nodeId, tabType, query, listId, corpusId, params: {limit, offs
     , orderBy: convOrderBy orderBy
     , tabType
     , query
-    }) :: Aff {count :: Int, docs :: Array Response}
+    }) :: AffTableResult Response
   let docs = res2corpus <$> res.docs
   pure $
     if mock then
diff --git a/src/Gargantext/Components/Nodes/Annuaire.purs b/src/Gargantext/Components/Nodes/Annuaire.purs
index 59a79cfb..bdff8193 100644
--- a/src/Gargantext/Components/Nodes/Annuaire.purs
+++ b/src/Gargantext/Components/Nodes/Annuaire.purs
@@ -15,7 +15,7 @@ import Gargantext.Ends (url, Frontends)
 import Gargantext.Routes (SessionRoute(..))
 import Gargantext.Routes as Routes
 import Gargantext.Sessions (Session, sessionId, get)
-import Gargantext.Types (NodeType(..))
+import Gargantext.Types (NodeType(..), AffTableResult, TableResult)
 import Gargantext.Hooks.Loader (useLoader)
 
 newtype IndividuView =
@@ -25,8 +25,8 @@ newtype IndividuView =
   , role    :: String
   , company :: String }
 
-toRows :: AnnuaireTable -> Array (Maybe Contact)
-toRows (AnnuaireTable a) = a.annuaireTable
+--toRows :: AnnuaireTable -> Array (Maybe Contact)
+--toRows (AnnuaireTable a) = a.annuaireTable
 
 -- | Top level layout component. Loads an annuaire by id and renders
 -- | the annuaire using the result
@@ -100,7 +100,7 @@ type PageProps =
   , frontends :: Frontends
   , pagePath :: R.State PagePath
   -- , info :: AnnuaireInfo
-  , table :: AnnuaireTable
+  , table :: TableResult Contact
   )
 
 page :: Record PageProps -> R.Element
@@ -110,12 +110,11 @@ pageCpt :: R.Component PageProps
 pageCpt = R.hooksComponent "LoadedAnnuairePage" cpt
   where
     cpt { session, pagePath, frontends
-        , table: (AnnuaireTable {annuaireTable})} _ = do
+        , table: ({count: totalRecords, docs})} _ = do
       pure $ T.table { rows, params, container, colNames, totalRecords, wrapColElts }
       where
-        totalRecords = 4361 -- TODO
         path = fst pagePath
-        rows = (\c -> {row: contactCells session frontends (fst pagePath).nodeId c, delete: false}) <$> annuaireTable
+        rows = (\c -> {row: contactCells session frontends (fst pagePath).nodeId c, delete: false}) <$> docs
         container = T.defaultContainer { title: "Annuaire" } -- TODO
         colNames = T.ColumnName <$> [ "", "Name", "Company", "Service", "Role"]
         wrapColElts = const identity
@@ -125,8 +124,8 @@ pageCpt = R.hooksComponent "LoadedAnnuairePage" cpt
 
 type AnnuaireId = Int
 
-contactCells :: Session -> Frontends -> AnnuaireId -> Maybe Contact -> Array R.Element
-contactCells session frontends aId = maybe [] render
+contactCells :: Session -> Frontends -> AnnuaireId -> Contact -> Array R.Element
+contactCells session frontends aId = render
   where
     render (Contact { id, hyperdata : (HyperdataContact contact@{who: who, ou:ou} ) }) =
       --let nodepath = NodePath (sessionId session) NodeContact (Just id)
@@ -190,16 +189,16 @@ instance decodeAnnuaireInfo :: DecodeJson AnnuaireInfo where
                         }
 
 
-newtype AnnuaireTable  = AnnuaireTable  { annuaireTable :: Array (Maybe Contact)}
+--newtype AnnuaireTable  = AnnuaireTable  { annuaireTable :: Array (Maybe Contact)}
 
-instance decodeAnnuaireTable :: DecodeJson AnnuaireTable where
-  decodeJson json = do
-    rows <- decodeJson json
-    pure $ AnnuaireTable { annuaireTable : rows}
+--instance decodeAnnuaireTable :: DecodeJson AnnuaireTable where
+--  decodeJson json = do
+--    rows <- decodeJson json
+--    pure $ AnnuaireTable { annuaireTable : rows}
 
 ------------------------------------------------------------------------
 
-loadPage :: Session -> PagePath -> Aff AnnuaireTable
+loadPage :: Session -> PagePath -> AffTableResult Contact
 loadPage session {nodeId, params: { offset, limit, orderBy }} =
     get session children
  -- TODO orderBy
diff --git a/src/Gargantext/Components/Nodes/Corpus.purs b/src/Gargantext/Components/Nodes/Corpus.purs
index d3ecc2c2..3b95bd17 100644
--- a/src/Gargantext/Components/Nodes/Corpus.purs
+++ b/src/Gargantext/Components/Nodes/Corpus.purs
@@ -10,7 +10,7 @@ import Reactix as R
 import Reactix.DOM.HTML as H
 import Gargantext.Prelude
 import Gargantext.Components.Node (NodePoly(..), HyperdataList)
-import Gargantext.Types (NodeType(..))
+import Gargantext.Types (NodeType(..), AffTableResult)
 import Gargantext.Routes (SessionRoute(NodeAPI, Children))
 import Gargantext.Sessions (Session, get)
 
@@ -77,8 +77,8 @@ loadCorpus {session, nodeId: listId} = do
   -- fetch corpus via lists parentId
   (NodePoly {parentId: corpusId} :: NodePoly {}) <- get session nodePolyRoute
   corpusNode     <- get session $ corpusNodeRoute     corpusId ""
-  defaultListIds <- get session $ defaultListIdsRoute corpusId
-  case (head defaultListIds :: Maybe (NodePoly HyperdataList)) of
+  defaultListIds <- (get session $ defaultListIdsRoute corpusId) :: forall a. DecodeJson a => AffTableResult (NodePoly a)
+  case (head defaultListIds.docs :: Maybe (NodePoly HyperdataList)) of
     Just (NodePoly { id: defaultListId }) ->
       pure {corpusId, corpusNode, defaultListId}
     Nothing ->
diff --git a/src/Gargantext/Types.purs b/src/Gargantext/Types.purs
index 968a21ba..9217d20a 100644
--- a/src/Gargantext/Types.purs
+++ b/src/Gargantext/Types.purs
@@ -4,6 +4,7 @@ import Prelude
 import Data.Argonaut ( class DecodeJson, decodeJson, class EncodeJson, encodeJson, (:=), (~>), jsonEmptyObject)
 import Data.Either (Either(..))
 import Data.Maybe (Maybe(..), maybe)
+import Effect.Aff (Aff)
 import Prim.Row (class Union)
 import URI.Query (Query)
 import Data.Generic.Rep (class Generic)
@@ -405,3 +406,6 @@ derive instance genericTabType :: Generic TabType _
 
 instance showTabType :: Show TabType where
   show = genericShow
+
+type TableResult a = {count :: Int, docs :: Array a}
+type AffTableResult a = Aff (TableResult a)
diff --git a/src/Gargantext/Utils/Selection.purs b/src/Gargantext/Utils/Selection.purs
index 2fcc15d8..2b4a8e0c 100644
--- a/src/Gargantext/Utils/Selection.purs
+++ b/src/Gargantext/Utils/Selection.purs
@@ -3,6 +3,7 @@ module Gargantext.Utils.Selection where
 import Prelude
 import Data.Maybe (Maybe, maybe)
 import Data.Nullable (Nullable, toMaybe)
+import Data.Tuple (Tuple(..))
 import DOM.Simple.Types (Element, DOMRect)
 import DOM.Simple.Element as Element
 import Effect (Effect)
@@ -43,6 +44,10 @@ selectionToString s = s ... "toString" $ []
 rangeToString :: Range -> String
 rangeToString s = s ... "toString" $ []
 
+--- | Convert range to an offset tuple
+rangeToTuple :: Range -> Tuple Int Int
+rangeToTuple r = Tuple (r .. "startOffset") (r .. "endOffset")
+
 -- | Whether the anchor and focus are at the same point
 isRangeCollapsed :: Range -> Boolean
 isRangeCollapsed r = r .. "isCollapsed"
-- 
2.21.0