Commit c82a7f6b authored by Przemyslaw Kaminski's avatar Przemyslaw Kaminski

[errors] implement errors view in various places

parent 85f4f9f2
-- TODO: this module should be replaced by FacetsTable -- TODO: this module should be replaced by FacetsTable
module Gargantext.Components.DocsTable where module Gargantext.Components.DocsTable where
import Gargantext.Prelude
import Prelude
import Control.Monad.Error.Class (throwError)
import DOM.Simple.Console (log2) import DOM.Simple.Console (log2)
import DOM.Simple.Event as DE import DOM.Simple.Event as DE
import Data.Argonaut (class EncodeJson, jsonEmptyObject, (:=), (~>))
import Data.Array as A import Data.Array as A
import Data.Either (Either(..)) import Data.Either (Either)
import Data.Generic.Rep (class Generic) import Data.Generic.Rep (class Generic)
import Data.Lens ((^.)) import Data.Lens ((^.))
import Data.Lens.At (at) import Data.Lens.At (at)
...@@ -24,7 +19,7 @@ import Data.String as Str ...@@ -24,7 +19,7 @@ import Data.String as Str
import Data.Symbol (SProxy(..)) import Data.Symbol (SProxy(..))
import Data.Tuple (Tuple(..)) import Data.Tuple (Tuple(..))
import Effect (Effect) import Effect (Effect)
import Effect.Aff (Aff, error, launchAff_) import Effect.Aff (Aff)
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import Gargantext.Components.Category (rating) import Gargantext.Components.Category (rating)
import Gargantext.Components.Category.Types (Star(..)) import Gargantext.Components.Category.Types (Star(..))
...@@ -36,11 +31,11 @@ import Gargantext.Components.Table.Types as TT ...@@ -36,11 +31,11 @@ import Gargantext.Components.Table.Types as TT
import Gargantext.Config.REST (RESTError) import Gargantext.Config.REST (RESTError)
import Gargantext.Ends (Frontends, url) import Gargantext.Ends (Frontends, url)
import Gargantext.Hooks.Loader (useLoader, useLoaderWithCacheAPI, HashedResponse(..)) import Gargantext.Hooks.Loader (useLoader, useLoaderWithCacheAPI, HashedResponse(..))
import Gargantext.Prelude (class Ord, Unit, bind, const, discard, identity, mempty, otherwise, pure, show, unit, ($), (/=), (<$>), (<<<), (<>), (==)) import Gargantext.Prelude
import Gargantext.Routes (SessionRoute(NodeAPI)) import Gargantext.Routes (SessionRoute(NodeAPI))
import Gargantext.Routes as Routes import Gargantext.Routes as Routes
import Gargantext.Sessions (Session, sessionId, get, delete) import Gargantext.Sessions (Session, sessionId, get, delete)
import Gargantext.Types (ListId, NodeID, NodeType(..), OrderBy(..), SidePanelState(..), TableResult, TabSubType, TabType, showTabType') import Gargantext.Types (FrontendError, ListId, NodeID, NodeType(..), OrderBy(..), SidePanelState(..), TabSubType, TabType, TableResult, showTabType')
import Gargantext.Utils (sortWith) import Gargantext.Utils (sortWith)
import Gargantext.Utils.CacheAPI as GUC import Gargantext.Utils.CacheAPI as GUC
import Gargantext.Utils.QueryString (joinQueryStrings, mQueryParam, mQueryParamS, queryParam, queryParamS) import Gargantext.Utils.QueryString (joinQueryStrings, mQueryParam, mQueryParamS, queryParam, queryParamS)
...@@ -66,6 +61,7 @@ type Path a = ...@@ -66,6 +61,7 @@ type Path a =
type CommonProps = type CommonProps =
( cacheState :: T.Box NT.CacheState ( cacheState :: T.Box NT.CacheState
, errors :: T.Box (Array FrontendError)
, frontends :: Frontends , frontends :: Frontends
, listId :: Int , listId :: Int
, mCorpusId :: Maybe Int , mCorpusId :: Maybe Int
...@@ -101,7 +97,6 @@ _localCategories = prop (SProxy :: SProxy "localCategories") ...@@ -101,7 +97,6 @@ _localCategories = prop (SProxy :: SProxy "localCategories")
docViewLayout :: Record LayoutProps -> R.Element docViewLayout :: Record LayoutProps -> R.Element
docViewLayout props = R.createElement docViewLayoutCpt props [] docViewLayout props = R.createElement docViewLayoutCpt props []
docViewLayoutCpt :: R.Component LayoutProps docViewLayoutCpt :: R.Component LayoutProps
docViewLayoutCpt = here.component "docViewLayout" cpt docViewLayoutCpt = here.component "docViewLayout" cpt
where where
...@@ -118,11 +113,11 @@ type Props = ( ...@@ -118,11 +113,11 @@ type Props = (
docView :: R2.Component Props docView :: R2.Component Props
docView = R.createElement docViewCpt docView = R.createElement docViewCpt
docViewCpt :: R.Component Props docViewCpt :: R.Component Props
docViewCpt = here.component "docView" cpt where docViewCpt = here.component "docView" cpt where
cpt { layout: { cacheState cpt { layout: { cacheState
, chart , chart
, errors
, frontends , frontends
, listId , listId
, mCorpusId , mCorpusId
...@@ -147,6 +142,7 @@ docViewCpt = here.component "docView" cpt where ...@@ -147,6 +142,7 @@ docViewCpt = here.component "docView" cpt where
, if showSearch then searchBar { query } [] else H.div {} [] , if showSearch then searchBar { query } [] else H.div {} []
, H.div {className: "col-md-12"} , H.div {className: "col-md-12"}
[ pageLayout { cacheState [ pageLayout { cacheState
, errors
, frontends , frontends
, key: "docView-" <> (show cacheState') , key: "docView-" <> (show cacheState')
, listId , listId
...@@ -167,7 +163,6 @@ type SearchBarProps = ...@@ -167,7 +163,6 @@ type SearchBarProps =
searchBar :: R2.Component SearchBarProps searchBar :: R2.Component SearchBarProps
searchBar = R.createElement searchBarCpt searchBar = R.createElement searchBarCpt
searchBarCpt :: R.Component SearchBarProps searchBarCpt :: R.Component SearchBarProps
searchBarCpt = here.component "searchBar" cpt searchBarCpt = here.component "searchBar" cpt
where where
...@@ -268,6 +263,7 @@ pageLayout = R.createElement pageLayoutCpt ...@@ -268,6 +263,7 @@ pageLayout = R.createElement pageLayoutCpt
pageLayoutCpt :: R.Component PageLayoutProps pageLayoutCpt :: R.Component PageLayoutProps
pageLayoutCpt = here.component "pageLayout" cpt where pageLayoutCpt = here.component "pageLayout" cpt where
cpt props@{ cacheState cpt props@{ cacheState
, errors
, frontends , frontends
, listId , listId
, mCorpusId , mCorpusId
...@@ -303,6 +299,7 @@ pageLayoutCpt = here.component "pageLayout" cpt where ...@@ -303,6 +299,7 @@ pageLayoutCpt = here.component "pageLayout" cpt where
case cacheState' of case cacheState' of
NT.CacheOn -> do NT.CacheOn -> do
let paint (Tuple count docs) = page { documents: docs let paint (Tuple count docs) = page { documents: docs
, errors
, layout: props { totalRecords = count } , layout: props { totalRecords = count }
, params } [] , params } []
mkRequest :: PageParams -> GUC.Request mkRequest :: PageParams -> GUC.Request
...@@ -310,6 +307,7 @@ pageLayoutCpt = here.component "pageLayout" cpt where ...@@ -310,6 +307,7 @@ pageLayoutCpt = here.component "pageLayout" cpt where
useLoaderWithCacheAPI { useLoaderWithCacheAPI {
cacheEndpoint: getPageHash session cacheEndpoint: getPageHash session
, errors
, handleResponse , handleResponse
, mkRequest , mkRequest
, path , path
...@@ -339,13 +337,13 @@ pageLayoutCpt = here.component "pageLayout" cpt where ...@@ -339,13 +337,13 @@ pageLayoutCpt = here.component "pageLayout" cpt where
type PageProps = ( type PageProps = (
documents :: Array DocumentsView documents :: Array DocumentsView
, layout :: Record PageLayoutProps , errors :: T.Box (Array FrontendError)
, params :: TT.Params , layout :: Record PageLayoutProps
, params :: TT.Params
) )
page :: R2.Component PageProps page :: R2.Component PageProps
page = R.createElement pageCpt page = R.createElement pageCpt
pageCpt :: R.Component PageProps pageCpt :: R.Component PageProps
pageCpt = here.component "pageCpt" cpt where pageCpt = here.component "pageCpt" cpt where
cpt { documents, layout, params } _ = do cpt { documents, layout, params } _ = do
...@@ -361,7 +359,6 @@ type PagePaintProps = ( ...@@ -361,7 +359,6 @@ type PagePaintProps = (
pagePaint :: R2.Component PagePaintProps pagePaint :: R2.Component PagePaintProps
pagePaint = R.createElement pagePaintCpt pagePaint = R.createElement pagePaintCpt
pagePaintCpt :: R.Component PagePaintProps pagePaintCpt :: R.Component PagePaintProps
pagePaintCpt = here.component "pagePaintCpt" cpt pagePaintCpt = here.component "pagePaintCpt" cpt
where where
......
module Gargantext.Components.ErrorsView where
import Gargantext.Prelude
import Data.Array (deleteAt)
import Data.FunctorWithIndex (mapWithIndex)
import Data.Maybe (Maybe(..))
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
import Gargantext.Types (FrontendError(..))
import Gargantext.Utils.ReactBootstrap as RB
import Gargantext.Utils.Reactix as R2
here :: R2.Here
here = R2.here "Gargantext.Components.ErrorsView"
type ErrorsProps =
( errors :: T.Box (Array FrontendError) )
errorsView :: R2.Component ErrorsProps
errorsView = R.createElement errorsViewCpt
errorsViewCpt :: R.Component ErrorsProps
errorsViewCpt = here.component "errorsView" cpt
where
cpt { errors } _ = do
errors' <- T.useLive T.unequal errors
pure $ H.div {}
( mapWithIndex (showError errors) errors' )
showError errors i (FStringError { error }) =
RB.alert { dismissible: true
, onClose
, variant: "danger" } [ H.text error ]
where
onClose = do
here.log2 "click!" error
T.modify_ (\es -> case deleteAt i es of
Nothing -> es
Just es' -> es'
) errors
showError errors i (FRESTError { error }) =
RB.alert { dismissible: true
, onClose
, variant: "danger" } [ H.text $ show error ]
where
onClose = do
here.log2 "click!" error
T.modify_ (\es -> case deleteAt i es of
Nothing -> es
Just es' -> es'
) errors
...@@ -6,15 +6,9 @@ import Data.Either (Either(..)) ...@@ -6,15 +6,9 @@ import Data.Either (Either(..))
import Data.Maybe (Maybe(..), fromMaybe) import Data.Maybe (Maybe(..), fromMaybe)
import Data.Nullable (null) import Data.Nullable (null)
import Data.Traversable (traverse_) import Data.Traversable (traverse_)
import DOM.Simple.Console (log, log2)
import Effect (Effect) import Effect (Effect)
import Effect.Aff (Aff, error) import Effect.Aff (Aff, error)
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import Reactix as R
import Reactix.DOM.HTML as H
import Record as Record
import Toestand as T
import Gargantext.AsyncTasks as GAT import Gargantext.AsyncTasks as GAT
import Gargantext.Components.Forest.Tree.Node.Action (Action(..)) import Gargantext.Components.Forest.Tree.Node.Action (Action(..))
import Gargantext.Components.Forest.Tree.Node.Action.Add (AddNodeValue(..), addNode) import Gargantext.Components.Forest.Tree.Node.Action.Add (AddNodeValue(..), addNode)
...@@ -31,15 +25,20 @@ import Gargantext.Components.Forest.Tree.Node.Box (nodePopupView) ...@@ -31,15 +25,20 @@ import Gargantext.Components.Forest.Tree.Node.Box (nodePopupView)
import Gargantext.Components.Forest.Tree.Node.Tools.FTree (FTree, LNode(..), NTree(..), fTreeID) import Gargantext.Components.Forest.Tree.Node.Tools.FTree (FTree, LNode(..), NTree(..), fTreeID)
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree.Types (SubTreeOut(..)) import Gargantext.Components.Forest.Tree.Node.Tools.SubTree.Types (SubTreeOut(..))
import Gargantext.Config.REST (RESTError) import Gargantext.Config.REST (RESTError)
import Gargantext.Config.Utils (handleRESTError)
import Gargantext.Hooks.Loader (useLoader) import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Prelude (Ordering, Unit, bind, compare, discard, pure, unit, void, ($), (<$>), (<>)) import Gargantext.Prelude (Ordering, Unit, bind, compare, discard, pure, unit, void, ($), (<$>), (<>))
import Gargantext.Routes (AppRoute(Home), SessionRoute(..), appPath, nodeTypeAppRoute) import Gargantext.Routes (AppRoute(Home), SessionRoute(..), appPath, nodeTypeAppRoute)
import Gargantext.Sessions (Session, get, sessionId) import Gargantext.Sessions (Session, get, sessionId)
import Gargantext.Types (NodeType(..)) import Gargantext.Types (FrontendError, NodeType(..))
import Gargantext.Types as GT import Gargantext.Types as GT
import Gargantext.Utils.Popover as Popover import Gargantext.Utils.Popover as Popover
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2 import Gargantext.Utils.Toestand as T2
import Reactix as R
import Reactix.DOM.HTML as H
import Record as Record
import Toestand as T
foreign import back :: Effect Unit foreign import back :: Effect Unit
foreign import link :: String -> Effect Unit foreign import link :: String -> Effect Unit
...@@ -48,11 +47,12 @@ here :: R2.Here ...@@ -48,11 +47,12 @@ here :: R2.Here
here = R2.here "Gargantext.Components.FolderView" here = R2.here "Gargantext.Components.FolderView"
type Props = type Props =
( nodeId :: Int ( backFolder :: Boolean
, session :: Session , errors :: T.Box (Array FrontendError)
, backFolder :: Boolean , nodeId :: Int
, tasks :: T.Box GAT.Storage
, reloadForest :: T.Box T2.Reload , reloadForest :: T.Box T2.Reload
, session :: Session
, tasks :: T.Box GAT.Storage
) )
data FolderStyle = FolderUp | FolderChild data FolderStyle = FolderUp | FolderChild
...@@ -61,35 +61,43 @@ folderView :: R2.Leaf Props ...@@ -61,35 +61,43 @@ folderView :: R2.Leaf Props
folderView props = R.createElement folderViewCpt props [] folderView props = R.createElement folderViewCpt props []
folderViewCpt :: R.Component Props folderViewCpt :: R.Component Props
folderViewCpt = here.component "folderViewCpt" cpt where folderViewCpt = here.component "folderViewCpt" cpt where
cpt {nodeId, session, backFolder, tasks, reloadForest} _ = do cpt { errors, nodeId, session, backFolder, tasks, reloadForest } _ = do
setPopoverRef <- R.useRef Nothing setPopoverRef <- R.useRef Nothing
reload <- T.useBox T2.newReload reload <- T.useBox T2.newReload
reload' <- T.useLive T.unequal reload reload' <- T.useLive T.unequal reload
useLoader { errorHandler useLoader { errorHandler
, loader: loadFolders , loader: loadFolders
, path: { nodeId, session, reload: reload'} , path: { nodeId, session, reload: reload'}
, render: \folders -> folderViewMain {folders, nodeId, session, backFolder, tasks, reload, setPopoverRef, reloadForest} } , render: \folders -> folderViewMain { backFolder
, errors
, folders
, nodeId
, session
, tasks
, reload
, setPopoverRef
, reloadForest} }
where where
errorHandler err = here.log2 "[folderView] RESTError" err errorHandler err = here.log2 "[folderView] RESTError" err
type FolderViewProps = type FolderViewProps =
( ( backFolder :: Boolean
nodeId :: Int , errors :: T.Box (Array FrontendError)
, folders:: FTree , folders :: FTree
, session :: Session , nodeId :: Int
, backFolder :: Boolean , reload :: T.Box T2.Reload
, tasks :: T.Box GAT.Storage , reloadForest :: T.Box T2.Reload
, reload :: T.Box T2.Reload , session :: Session
, reloadForest :: T.Box T2.Reload
, setPopoverRef :: R.Ref (Maybe (Boolean -> Effect Unit)) , setPopoverRef :: R.Ref (Maybe (Boolean -> Effect Unit))
, tasks :: T.Box GAT.Storage
) )
folderViewMain :: Record FolderViewProps -> R.Element folderViewMain :: Record FolderViewProps -> R.Element
folderViewMain props = R.createElement folderViewMainCpt props [] folderViewMain props = R.createElement folderViewMainCpt props []
folderViewMainCpt :: R.Component FolderViewProps folderViewMainCpt :: R.Component FolderViewProps
folderViewMainCpt = here.component "folderViewMainCpt" cpt where folderViewMainCpt = here.component "folderViewMainCpt" cpt where
cpt { backFolder cpt { backFolder
, errors
, folders: NTree (LNode {parent_id: parentId, nodeType}) (folders) , folders: NTree (LNode {parent_id: parentId, nodeType}) (folders)
, nodeId , nodeId
, reload , reload
...@@ -100,22 +108,23 @@ folderViewMainCpt = here.component "folderViewMainCpt" cpt where ...@@ -100,22 +108,23 @@ folderViewMainCpt = here.component "folderViewMainCpt" cpt where
let foldersS = A.sortBy sortFolders folders let foldersS = A.sortBy sortFolders folders
let backHome = isBackHome nodeType let backHome = isBackHome nodeType
let parent = makeParentFolder parentId session backFolder backHome let parent = makeParentFolder parentId session backFolder backHome
let children = makeFolderElements foldersS {session, setPopoverRef, nodeId, tasks, reload, reloadForest} let children = makeFolderElements foldersS { errors, session, setPopoverRef, nodeId, tasks, reload, reloadForest }
pure $ H.div {className: "fv folders"} $ parent <> children pure $ H.div {className: "fv folders"} $ parent <> children
makeFolderElements foldersS props = makeFolderElementsMap <$> foldersS where makeFolderElements foldersS props = makeFolderElementsMap <$> foldersS where
makeFolderElementsMap :: NTree LNode -> R.Element makeFolderElementsMap :: NTree LNode -> R.Element
makeFolderElementsMap (NTree (LNode node) _) = folder {style: FolderChild makeFolderElementsMap (NTree (LNode node) _) = folder { errors: props.errors
, text: node.name
, nodeId: node.id , nodeId: node.id
, nodeType: node.nodeType , nodeType: node.nodeType
, session: props.session
, setPopoverRef: props.setPopoverRef
, parentId: props.nodeId , parentId: props.nodeId
, tasks: props.tasks , tasks: props.tasks
, reload: props.reload , reload: props.reload
, reloadForest: props.reloadForest} [] , reloadForest: props.reloadForest
, session: props.session
, setPopoverRef: props.setPopoverRef
, style: FolderChild
, text: node.name } []
makeParentFolder :: Maybe Int -> Session -> Boolean -> Boolean -> Array R.Element makeParentFolder :: Maybe Int -> Session -> Boolean -> Boolean -> Array R.Element
makeParentFolder (Just parentId) session _ _ = makeParentFolder (Just parentId) session _ _ =
...@@ -171,23 +180,22 @@ folderSimpleCpt = here.component "folderSimpleCpt" cpt where ...@@ -171,23 +180,22 @@ folderSimpleCpt = here.component "folderSimpleCpt" cpt where
getFolderPath nodeType sid nodeId = appPath $ fromMaybe Home $ nodeTypeAppRoute nodeType sid nodeId getFolderPath nodeType sid nodeId = appPath $ fromMaybe Home $ nodeTypeAppRoute nodeType sid nodeId
type FolderProps = type FolderProps =
( ( errors :: T.Box (Array FrontendError)
setPopoverRef :: R.Ref (Maybe (Boolean -> Effect Unit)) , parentId :: Int
, parentId :: Int , reload :: T.Box T2.Reload
, tasks :: T.Box GAT.Storage , reloadForest :: T.Box T2.Reload
, reload :: T.Box T2.Reload , setPopoverRef :: R.Ref (Maybe (Boolean -> Effect Unit))
, reloadForest :: T.Box T2.Reload , tasks :: T.Box GAT.Storage
| FolderSimpleProps | FolderSimpleProps
) )
folder :: R2.Component FolderProps folder :: R2.Component FolderProps
folder = R.createElement folderCpt folder = R.createElement folderCpt
folderCpt :: R.Component FolderProps folderCpt :: R.Component FolderProps
folderCpt = here.component "folderCpt" cpt where folderCpt = here.component "folderCpt" cpt where
cpt props@{style, text, nodeId, session, nodeType, setPopoverRef, parentId, tasks, reload, reloadForest} _ = do cpt props@{ errors, style, text, nodeId, session, nodeType, setPopoverRef, parentId, tasks, reload, reloadForest } _ = do
let sid = sessionId session let sid = sessionId session
let dispatch a = performAction a {setPopoverRef, session, nodeId, parentId, tasks, reload, reloadForest} let dispatch a = performAction a { errors, nodeId, parentId, tasks, reload, reloadForest, session, setPopoverRef }
popoverRef <- R.useRef null popoverRef <- R.useRef null
R.useEffect' $ do R.useEffect' $ do
...@@ -226,11 +234,12 @@ folderCpt = here.component "folderCpt" cpt where ...@@ -226,11 +234,12 @@ folderCpt = here.component "folderCpt" cpt where
<> "Click here to execute one of them." } [] <> "Click here to execute one of them." } []
] ]
mNodePopupView props opc = nodePopupView {onPopoverClose: opc mNodePopupView props opc = nodePopupView { dispatch: props.dispatch
,nodeType: props.nodeType , errors: props.errors
, name: props.text
, id: props.nodeId , id: props.nodeId
, dispatch: props.dispatch , onPopoverClose: opc
, nodeType: props.nodeType
, name: props.text
, session: props.session , session: props.session
, handed: GT.RightHanded , handed: GT.RightHanded
} }
...@@ -264,14 +273,14 @@ loadFolders :: Record LoadProps -> Aff (Either RESTError FTree) ...@@ -264,14 +273,14 @@ loadFolders :: Record LoadProps -> Aff (Either RESTError FTree)
loadFolders {nodeId, session} = get session $ TreeFirstLevel (Just nodeId) "" loadFolders {nodeId, session} = get session $ TreeFirstLevel (Just nodeId) ""
type PerformActionProps = type PerformActionProps =
( ( errors :: T.Box (Array FrontendError)
setPopoverRef :: R.Ref (Maybe (Boolean -> Effect Unit)) , nodeId :: Int
, session :: Session , parentId :: Int
, nodeId :: Int , reload :: T.Box T2.Reload
, parentId :: Int , reloadForest :: T.Box T2.Reload
, tasks :: T.Box GAT.Storage , setPopoverRef :: R.Ref (Maybe (Boolean -> Effect Unit))
, reload :: T.Box T2.Reload , session :: Session
, reloadForest :: T.Box T2.Reload , tasks :: T.Box GAT.Storage
) )
performAction :: Action -> Record PerformActionProps -> Aff Unit performAction :: Action -> Record PerformActionProps -> Aff Unit
...@@ -286,13 +295,13 @@ performAction = performAction' where ...@@ -286,13 +295,13 @@ performAction = performAction' where
performAction' (AddNode name nodeType) p = addNode' name nodeType p performAction' (AddNode name nodeType) p = addNode' name nodeType p
performAction' (UploadFile nodeType fileType mName contents) p = uploadFile' nodeType fileType mName contents p performAction' (UploadFile nodeType fileType mName contents) p = uploadFile' nodeType fileType mName contents p
performAction' (UploadArbitraryFile mName blob) p = uploadArbitraryFile' mName blob p performAction' (UploadArbitraryFile mName blob) p = uploadArbitraryFile' mName blob p
performAction' DownloadNode _ = liftEffect $ log "[performAction] DownloadNode" performAction' DownloadNode _ = liftEffect $ here.log "[performAction] DownloadNode"
performAction' (MoveNode {params}) p = moveNode params p performAction' (MoveNode {params}) p = moveNode params p
performAction' (MergeNode {params}) p = mergeNode params p performAction' (MergeNode {params}) p = mergeNode params p
performAction' (LinkNode { nodeType, params }) p = linkNode nodeType params p performAction' (LinkNode { nodeType, params }) p = linkNode nodeType params p
performAction' NoAction _ = liftEffect $ log "[performAction] NoAction" performAction' NoAction _ = liftEffect $ here.log "[performAction] NoAction"
performAction' ClosePopover p = closePopover p performAction' ClosePopover p = closePopover p
performAction' _ _ = liftEffect $ log "[performAction] unsupported action" performAction' _ _ = liftEffect $ here.log "[performAction] unsupported action"
closePopover { setPopoverRef } = closePopover { setPopoverRef } =
liftEffect $ traverse_ (\set -> set false) (R.readRef setPopoverRef) liftEffect $ traverse_ (\set -> set false) (R.readRef setPopoverRef)
...@@ -311,59 +320,63 @@ performAction = performAction' where ...@@ -311,59 +320,63 @@ performAction = performAction' where
doSearch task { tasks, nodeId: id } = liftEffect $ do doSearch task { tasks, nodeId: id } = liftEffect $ do
GAT.insert id task tasks GAT.insert id task tasks
log2 "[performAction] DoSearch task:" task here.log2 "[performAction] DoSearch task:" task
updateNode params p@{ tasks, nodeId: id } = do updateNode params p@{ errors, tasks, nodeId: id } = do
task <- updateRequest params p.session id eTask <- updateRequest params p.session id
liftEffect $ do handleRESTError errors eTask $ \task -> liftEffect $ do
GAT.insert id task tasks GAT.insert id task tasks
log2 "[performAction] UpdateNode task:" task here.log2 "[performAction] UpdateNode task:" task
shareTeam username p@{ nodeId: id} = shareTeam username p@{ errors, nodeId: id} = do
void $ Share.shareReq p.session id $ Share.ShareTeamParams {username} eTask <- Share.shareReq p.session id $ Share.ShareTeamParams {username}
handleRESTError errors eTask $ \_task -> pure unit
sharePublic params p = traverse_ f params where sharePublic params p@{ errors } = traverse_ f params where
f (SubTreeOut { in: inId, out }) = do f (SubTreeOut { in: inId, out }) = do
void $ Share.shareReq p.session inId $ Share.SharePublicParams { node_id: out } eTask <- Share.shareReq p.session inId $ Share.SharePublicParams { node_id: out }
handleRESTError errors eTask $ \_task -> pure unit
refreshFolders p refreshFolders p
addContact params p@{ nodeId: id } = addContact params p@{ nodeId: id } =
void $ Contact.contactReq p.session id params void $ Contact.contactReq p.session id params
uploadFile' nodeType fileType mName contents p@{ tasks, nodeId: id } = do uploadFile' nodeType fileType mName contents p@{ errors, tasks, nodeId: id } = do
task <- uploadFile p.session nodeType id fileType {mName, contents} eTask <- uploadFile { contents, fileType, id, nodeType, mName, session: p.session }
liftEffect $ do handleRESTError errors eTask $ \task -> liftEffect $ do
GAT.insert id task tasks GAT.insert id task tasks
log2 "[performAction] UploadFile, uploaded, task:" task here.log2 "[performAction] UploadFile, uploaded, task:" task
uploadArbitraryFile' mName blob p@{ tasks, nodeId: id } = do uploadArbitraryFile' mName blob p@{ errors, tasks, nodeId: id } = do
eTask <- uploadArbitraryFile p.session id { blob, mName } eTask <- uploadArbitraryFile p.session id { blob, mName }
case eTask of handleRESTError errors eTask $ \task -> liftEffect $ do
Left _err -> throwError $ error "[uploadArbitraryFile] RESTError" GAT.insert id task tasks
Right task -> do here.log2 "[performAction] UploadArbitraryFile, uploaded, task:" task
liftEffect $ do
GAT.insert id task tasks moveNode params p@{ errors } = traverse_ f params where
log2 "[performAction] UploadArbitraryFile, uploaded, task:" task
moveNode params p = traverse_ f params where
f (SubTreeOut { in: in', out }) = do f (SubTreeOut { in: in', out }) = do
void $ moveNodeReq p.session in' out eTask <- moveNodeReq p.session in' out
handleRESTError errors eTask $ \_task -> pure unit
refreshFolders p refreshFolders p
mergeNode params p = traverse_ f params where mergeNode params p@{ errors } = traverse_ f params where
f (SubTreeOut { in: in', out }) = do f (SubTreeOut { in: in', out }) = do
void $ mergeNodeReq p.session in' out eTask <- mergeNodeReq p.session in' out
handleRESTError errors eTask $ \_task -> pure unit
refreshFolders p refreshFolders p
linkNode nodeType params p = traverse_ f params where linkNode nodeType params p@{ errors } = traverse_ f params where
f (SubTreeOut { in: in', out }) = do f (SubTreeOut { in: in', out }) = do
void $ linkNodeReq p.session nodeType in' out eTask <- linkNodeReq p.session nodeType in' out
handleRESTError errors eTask $ \_task -> pure unit
refreshFolders p refreshFolders p
renameNode name p@{ nodeId: id } = do renameNode name p@{ errors, nodeId: id } = do
void $ rename p.session id $ RenameValue { text: name } eTask <- rename p.session id $ RenameValue { text: name }
handleRESTError errors eTask $ \_task -> pure unit
refreshFolders p refreshFolders p
addNode' name nodeType p@{ nodeId: id } = do addNode' name nodeType p@{ errors, nodeId: id } = do
void $ addNode p.session id $ AddNodeValue {name, nodeType} eTask <- addNode p.session id $ AddNodeValue {name, nodeType}
handleRESTError errors eTask $ \_task -> pure unit
refreshFolders p refreshFolders p
...@@ -14,7 +14,7 @@ import Gargantext.Components.Forest.Tree (treeLoader) ...@@ -14,7 +14,7 @@ import Gargantext.Components.Forest.Tree (treeLoader)
import Gargantext.Ends (Frontends, Backend) import Gargantext.Ends (Frontends, Backend)
import Gargantext.Routes (AppRoute) import Gargantext.Routes (AppRoute)
import Gargantext.Sessions (Session(..), Sessions, OpenNodes, unSessions) import Gargantext.Sessions (Session(..), Sessions, OpenNodes, unSessions)
import Gargantext.Types (Handed, switchHanded) import Gargantext.Types (FrontendError, Handed, switchHanded)
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2 import Gargantext.Utils.Toestand as T2
import Reactix as R import Reactix as R
...@@ -36,6 +36,7 @@ type Common = ...@@ -36,6 +36,7 @@ type Common =
type Props = type Props =
( backend :: T.Box (Maybe Backend) ( backend :: T.Box (Maybe Backend)
, errors :: T.Box (Array FrontendError)
, forestOpen :: T.Box OpenNodes , forestOpen :: T.Box OpenNodes
, reloadForest :: T2.ReloadS , reloadForest :: T2.ReloadS
, sessions :: T.Box Sessions , sessions :: T.Box Sessions
...@@ -53,6 +54,7 @@ forest = R.createElement forestCpt ...@@ -53,6 +54,7 @@ forest = R.createElement forestCpt
forestCpt :: R.Component Props forestCpt :: R.Component Props
forestCpt = here.component "forest" cpt where forestCpt = here.component "forest" cpt where
cpt props@{ backend cpt props@{ backend
, errors
, forestOpen , forestOpen
, frontends , frontends
, handed , handed
...@@ -81,7 +83,8 @@ forestCpt = here.component "forest" cpt where ...@@ -81,7 +83,8 @@ forestCpt = here.component "forest" cpt where
common = RX.pick props :: Record Common common = RX.pick props :: Record Common
trees handed' sessions' = (tree handed') <$> unSessions sessions' trees handed' sessions' = (tree handed') <$> unSessions sessions'
tree handed' s@(Session {treeId}) = tree handed' s@(Session {treeId}) =
treeLoader { forestOpen treeLoader { errors
, forestOpen
, frontends , frontends
, handed: handed' , handed: handed'
, reload: reloadForest , reload: reloadForest
......
...@@ -2,21 +2,13 @@ module Gargantext.Components.Forest.Tree where ...@@ -2,21 +2,13 @@ module Gargantext.Components.Forest.Tree where
import Gargantext.Prelude import Gargantext.Prelude
import Control.Monad.Error.Class (throwError)
import Data.Array as A import Data.Array as A
import Data.Either (Either(..)) import Data.Either (Either)
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Data.Traversable (traverse_, traverse) import Data.Traversable (traverse_, traverse)
import DOM.Simple.Console (log, log2)
import Effect (Effect) import Effect (Effect)
import Effect.Aff (Aff, error) import Effect.Aff (Aff)
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import Reactix as R
import Reactix.DOM.HTML as H
import Record as Record
import Record.Extra as RecordE
import Toestand as T
import Gargantext.AsyncTasks as GAT import Gargantext.AsyncTasks as GAT
import Gargantext.Components.Forest.Tree.Node (nodeSpan) import Gargantext.Components.Forest.Tree.Node (nodeSpan)
import Gargantext.Components.Forest.Tree.Node.Action (Action(..)) import Gargantext.Components.Forest.Tree.Node.Action (Action(..))
...@@ -33,16 +25,22 @@ import Gargantext.Components.Forest.Tree.Node.Action.Upload (uploadFile, uploadA ...@@ -33,16 +25,22 @@ import Gargantext.Components.Forest.Tree.Node.Action.Upload (uploadFile, uploadA
import Gargantext.Components.Forest.Tree.Node.Tools.FTree (FTree, LNode(..), NTree(..), fTreeID) import Gargantext.Components.Forest.Tree.Node.Tools.FTree (FTree, LNode(..), NTree(..), fTreeID)
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree.Types (SubTreeOut(..)) import Gargantext.Components.Forest.Tree.Node.Tools.SubTree.Types (SubTreeOut(..))
import Gargantext.Config.REST (RESTError) import Gargantext.Config.REST (RESTError)
import Gargantext.Config.Utils (handleRESTError)
import Gargantext.Ends (Frontends) import Gargantext.Ends (Frontends)
import Gargantext.Hooks.Loader (useLoader) import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Routes (AppRoute) import Gargantext.Routes (AppRoute)
import Gargantext.Routes as GR import Gargantext.Routes as GR
import Gargantext.Sessions (OpenNodes, Session, get, mkNodeId) import Gargantext.Sessions (OpenNodes, Session, get, mkNodeId)
import Gargantext.Sessions.Types (useOpenNodesMemberBox, openNodesInsert, openNodesDelete) import Gargantext.Sessions.Types (useOpenNodesMemberBox, openNodesInsert, openNodesDelete)
import Gargantext.Types (Handed, ID, isPublic, publicize, switchHanded) import Gargantext.Types (FrontendError, Handed, ID, isPublic, publicize, switchHanded)
import Gargantext.Types as GT import Gargantext.Types as GT
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2 import Gargantext.Utils.Toestand as T2
import Reactix as R
import Reactix.DOM.HTML as H
import Record as Record
import Record.Extra as RecordE
import Toestand as T
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.Forest.Tree" here = R2.here "Gargantext.Components.Forest.Tree"
...@@ -61,8 +59,9 @@ type Global = ...@@ -61,8 +59,9 @@ type Global =
| Universal ) | Universal )
-- Shared by every component here -- Shared by every component here
type Common = ( type Common =
forestOpen :: T.Box OpenNodes ( errors :: T.Box (Array FrontendError)
, forestOpen :: T.Box OpenNodes
, reload :: T2.ReloadS , reload :: T2.ReloadS
| Global | Global
) )
...@@ -105,12 +104,12 @@ tree :: R2.Leaf TreeProps ...@@ -105,12 +104,12 @@ tree :: R2.Leaf TreeProps
tree props = R.createElement treeCpt props [] tree props = R.createElement treeCpt props []
treeCpt :: R.Component TreeProps treeCpt :: R.Component TreeProps
treeCpt = here.component "tree" cpt where treeCpt = here.component "tree" cpt where
cpt p@{ reload, session, tree: NTree (LNode { id, name, nodeType }) children } _ = do cpt p@{ errors, reload, session, tree: NTree (LNode { id, name, nodeType }) children } _ = do
setPopoverRef <- R.useRef Nothing setPopoverRef <- R.useRef Nothing
folderOpen <- useOpenNodesMemberBox nodeId p.forestOpen folderOpen <- useOpenNodesMemberBox nodeId p.forestOpen
pure $ H.ul { className: ulClass } pure $ H.ul { className: ulClass }
[ H.li { className: childrenClass children' } [ H.li { className: childrenClass children' }
[ nodeSpan (nsprops { folderOpen, name, id, nodeType, setPopoverRef, isLeaf }) [ nodeSpan (nsprops { errors, folderOpen, name, id, nodeType, setPopoverRef, isLeaf })
[ renderChildren (Record.merge p { childProps: { children', folderOpen, render: tree } } ) [] ] [ renderChildren (Record.merge p { childProps: { children', folderOpen, render: tree } } ) [] ]
] ]
] ]
...@@ -125,7 +124,7 @@ treeCpt = here.component "tree" cpt where ...@@ -125,7 +124,7 @@ treeCpt = here.component "tree" cpt where
extra' = Record.merge extra { dispatch, reload } where extra' = Record.merge extra { dispatch, reload } where
dispatch a = performAction a (Record.merge common' spr) where dispatch a = performAction a (Record.merge common' spr) where
common' = RecordE.pick p :: Record PACommon common' = RecordE.pick p :: Record PACommon
spr = { setPopoverRef: extra.setPopoverRef } spr = { errors, setPopoverRef: extra.setPopoverRef }
pub (LNode n@{ nodeType: t }) = LNode (n { nodeType = publicize t }) pub (LNode n@{ nodeType: t }) = LNode (n { nodeType = publicize t })
childrenClass [] = "no-children" childrenClass [] = "no-children"
childrenClass _ = "with-children" childrenClass _ = "with-children"
...@@ -167,7 +166,8 @@ renderTreeChildrenCpt = here.component "renderTreeChildren" cpt where ...@@ -167,7 +166,8 @@ renderTreeChildrenCpt = here.component "renderTreeChildren" cpt where
--- The properties tree shares in common with performAction --- The properties tree shares in common with performAction
type PACommon = type PACommon =
( forestOpen :: T.Box OpenNodes ( errors :: T.Box (Array FrontendError)
, forestOpen :: T.Box OpenNodes
, reloadTree :: T2.ReloadS , reloadTree :: T2.ReloadS
, session :: Session , session :: Session
, tasks :: T.Box GAT.Storage , tasks :: T.Box GAT.Storage
...@@ -220,83 +220,88 @@ deleteNode' nt p@{ tree: (NTree (LNode {id, parent_id}) _) } = do ...@@ -220,83 +220,88 @@ deleteNode' nt p@{ tree: (NTree (LNode {id, parent_id}) _) } = do
doSearch task p@{ tasks, tree: NTree (LNode {id}) _ } = liftEffect $ do doSearch task p@{ tasks, tree: NTree (LNode {id}) _ } = liftEffect $ do
GAT.insert id task tasks GAT.insert id task tasks
log2 "[performAction] DoSearch task:" task here.log2 "[doSearch] DoSearch task:" task
updateNode params p@{ tasks, tree: (NTree (LNode {id}) _) } = do updateNode params p@{ errors, tasks, tree: (NTree (LNode {id}) _) } = do
task <- updateRequest params p.session id eTask <- updateRequest params p.session id
liftEffect $ do handleRESTError errors eTask $ \task -> liftEffect $ do
GAT.insert id task tasks GAT.insert id task tasks
log2 "[performAction] UpdateNode task:" task here.log2 "[updateNode] UpdateNode task:" task
renameNode name p@{ tree: (NTree (LNode {id}) _) } = do renameNode name p@{ errors, tree: (NTree (LNode {id}) _) } = do
void $ rename p.session id $ RenameValue { text: name } eTask <- rename p.session id $ RenameValue { text: name }
handleRESTError errors eTask $ \_task -> pure unit
refreshTree p refreshTree p
shareTeam username p@{ tree: (NTree (LNode {id}) _)} = shareTeam username p@{ errors, tree: (NTree (LNode {id}) _)} = do
void $ Share.shareReq p.session id $ Share.ShareTeamParams {username} eTask <- Share.shareReq p.session id $ Share.ShareTeamParams {username}
handleRESTError errors eTask $ \_task -> pure unit
sharePublic params p@{ forestOpen } = traverse_ f params where sharePublic params p@{ errors, forestOpen } = traverse_ f params where
f (SubTreeOut { in: inId, out }) = do f (SubTreeOut { in: inId, out }) = do
void $ Share.shareReq p.session inId $ Share.SharePublicParams { node_id: out } eTask <- Share.shareReq p.session inId $ Share.SharePublicParams { node_id: out }
liftEffect $ T.modify_ (openNodesInsert (mkNodeId p.session out)) forestOpen handleRESTError errors eTask $ \_task -> do
liftEffect $ T.modify_ (openNodesInsert (mkNodeId p.session out)) forestOpen
refreshTree p
addContact params p@{ errors, tree: (NTree (LNode {id}) _) } = do
eTask <- Contact.contactReq p.session id params
handleRESTError errors eTask $ \_task -> pure unit
addNode' name nodeType p@{ errors, forestOpen, tree: (NTree (LNode { id }) _) } = do
eId <- addNode p.session id $ AddNodeValue {name, nodeType}
handleRESTError errors eId $ \_id -> liftEffect $ do
liftEffect $ T.modify_ (openNodesInsert (mkNodeId p.session id)) forestOpen
refreshTree p refreshTree p
addContact params p@{ tree: (NTree (LNode {id}) _) } = uploadFile' nodeType fileType mName contents p@{ errors, tasks, tree: (NTree (LNode { id }) _) } = do
void $ Contact.contactReq p.session id params eTask <- uploadFile { contents, fileType, id, mName, nodeType, session: p.session }
handleRESTError errors eTask $ \task -> liftEffect $ do
addNode' name nodeType p@{ forestOpen, tree: (NTree (LNode { id }) _) } = do
task <- addNode p.session id $ AddNodeValue {name, nodeType}
liftEffect $ T.modify_ (openNodesInsert (mkNodeId p.session id)) forestOpen
refreshTree p
uploadFile' nodeType fileType mName contents p@{ tasks, tree: (NTree (LNode { id }) _) } = do
task <- uploadFile p.session nodeType id fileType {mName, contents}
liftEffect $ do
GAT.insert id task tasks GAT.insert id task tasks
log2 "[performAction] UploadFile, uploaded, task:" task here.log2 "[uploadFile'] UploadFile, uploaded, task:" task
uploadArbitraryFile' mName blob p@{ tasks, tree: (NTree (LNode { id }) _) } = do uploadArbitraryFile' mName blob p@{ errors, tasks, tree: (NTree (LNode { id }) _) } = do
eTask <- uploadArbitraryFile p.session id { blob, mName } eTask <- uploadArbitraryFile p.session id { blob, mName }
case eTask of handleRESTError errors eTask $ \task -> liftEffect $ do
Left err -> throwError $ error $ "[uploadArbitraryFile'] RESTError" GAT.insert id task tasks
Right task -> do here.log2 "[uploadArbitraryFile'] UploadArbitraryFile, uploaded, task:" task
liftEffect $ do
GAT.insert id task tasks moveNode params p@{ errors, forestOpen, session } = traverse_ f params where
log2 "[performAction] UploadArbitraryFile, uploaded, task:" task
moveNode params p@{ forestOpen, session } = traverse_ f params where
f (SubTreeOut { in: in', out }) = do f (SubTreeOut { in: in', out }) = do
void $ moveNodeReq p.session in' out eTask <- moveNodeReq p.session in' out
handleRESTError errors eTask $ \_task -> pure unit
liftEffect $ T.modify_ (openNodesInsert (mkNodeId session out)) forestOpen liftEffect $ T.modify_ (openNodesInsert (mkNodeId session out)) forestOpen
refreshTree p refreshTree p
mergeNode params p = traverse_ f params where mergeNode params p@{ errors } = traverse_ f params where
f (SubTreeOut { in: in', out }) = do f (SubTreeOut { in: in', out }) = do
void $ mergeNodeReq p.session in' out eTask <- mergeNodeReq p.session in' out
handleRESTError errors eTask $ \_task -> pure unit
refreshTree p refreshTree p
linkNode nodeType params p = traverse_ f params where linkNode nodeType params p@{ errors } = traverse_ f params where
f (SubTreeOut { in: in', out }) = do f (SubTreeOut { in: in', out }) = do
void $ linkNodeReq p.session nodeType in' out eTask <- linkNodeReq p.session nodeType in' out
handleRESTError errors eTask $ \_task -> pure unit
refreshTree p refreshTree p
-- | This thing is basically a hangover from when garg was a thermite -- | This thing is basically a hangover from when garg was a thermite
-- | application. we should slowly get rid of it. -- | application. we should slowly get rid of it.
performAction :: Action -> Record PerformActionProps -> Aff Unit performAction :: Action -> Record PerformActionProps -> Aff Unit
performAction (DeleteNode nt) p = deleteNode' nt p performAction (DeleteNode nt) p = deleteNode' nt p
performAction (DoSearch task) p = doSearch task p performAction (DoSearch task) p = doSearch task p
performAction (UpdateNode params) p = updateNode params p performAction (UpdateNode params) p = updateNode params p
performAction (RenameNode name) p = renameNode name p performAction (RenameNode name) p = renameNode name p
performAction (ShareTeam username) p = shareTeam username p performAction (ShareTeam username) p = shareTeam username p
performAction (SharePublic { params }) p = sharePublic params p performAction (SharePublic { params }) p = sharePublic params p
performAction (AddContact params) p = addContact params p performAction (AddContact params) p = addContact params p
performAction (AddNode name nodeType) p = addNode' name nodeType p performAction (AddNode name nodeType) p = addNode' name nodeType p
performAction (UploadFile nodeType fileType mName contents) p = uploadFile' nodeType fileType mName contents p performAction (UploadFile nodeType fileType mName contents) p = uploadFile' nodeType fileType mName contents p
performAction (UploadArbitraryFile mName blob) p = uploadArbitraryFile' mName blob p performAction (UploadArbitraryFile mName blob) p = uploadArbitraryFile' mName blob p
performAction DownloadNode _ = liftEffect $ log "[performAction] DownloadNode" performAction DownloadNode _ = liftEffect $ here.log "[performAction] DownloadNode"
performAction (MoveNode {params}) p = moveNode params p performAction (MoveNode {params}) p = moveNode params p
performAction (MergeNode {params}) p = mergeNode params p performAction (MergeNode {params}) p = mergeNode params p
performAction (LinkNode { nodeType, params }) p = linkNode nodeType params p performAction (LinkNode { nodeType, params }) p = linkNode nodeType params p
performAction RefreshTree p = refreshTree p performAction RefreshTree p = refreshTree p
performAction NoAction _ = liftEffect $ log "[performAction] NoAction" performAction NoAction _ = liftEffect $ here.log "[performAction] NoAction"
performAction ClosePopover p = closePopover p performAction ClosePopover p = closePopover p
...@@ -10,12 +10,6 @@ import Data.Tuple.Nested ((/\)) ...@@ -10,12 +10,6 @@ import Data.Tuple.Nested ((/\))
import Effect (Effect) import Effect (Effect)
import Effect.Aff (Aff, launchAff) import Effect.Aff (Aff, launchAff)
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import React.SyntheticEvent as E
import Reactix as R
import Reactix.DOM.HTML as H
import Record as Record
import Toestand as T
import Gargantext.AsyncTasks as GAT import Gargantext.AsyncTasks as GAT
import Gargantext.Components.Forest.Tree.Node.Action (Action(..)) import Gargantext.Components.Forest.Tree.Node.Action (Action(..))
import Gargantext.Components.Forest.Tree.Node.Action.Upload (DroppedFile(..), fileTypeView) import Gargantext.Components.Forest.Tree.Node.Action.Upload (DroppedFile(..), fileTypeView)
...@@ -33,19 +27,25 @@ import Gargantext.Ends (Frontends) ...@@ -33,19 +27,25 @@ import Gargantext.Ends (Frontends)
import Gargantext.Hooks.Loader (useLoader) import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Routes as Routes import Gargantext.Routes as Routes
import Gargantext.Sessions (Session, sessionId) import Gargantext.Sessions (Session, sessionId)
import Gargantext.Types (Name, ID, reverseHanded) import Gargantext.Types (FrontendError, ID, Name, reverseHanded)
import Gargantext.Types as GT import Gargantext.Types as GT
import Gargantext.Utils.Popover as Popover import Gargantext.Utils.Popover as Popover
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2 import Gargantext.Utils.Toestand as T2
import Gargantext.Version as GV import Gargantext.Version as GV
import React.SyntheticEvent as E
import Reactix as R
import Reactix.DOM.HTML as H
import Record as Record
import Toestand as T
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.Forest.Tree.Node" here = R2.here "Gargantext.Components.Forest.Tree.Node"
-- Main Node -- Main Node
type NodeMainSpanProps = type NodeMainSpanProps =
( folderOpen :: T.Box Boolean ( errors :: T.Box (Array FrontendError)
, folderOpen :: T.Box Boolean
, frontends :: Frontends , frontends :: Frontends
, id :: ID , id :: ID
, isLeaf :: IsLeaf , isLeaf :: IsLeaf
...@@ -64,7 +64,6 @@ type IsLeaf = Boolean ...@@ -64,7 +64,6 @@ type IsLeaf = Boolean
nodeSpan :: R2.Component NodeMainSpanProps nodeSpan :: R2.Component NodeMainSpanProps
nodeSpan = R.createElement nodeSpanCpt nodeSpan = R.createElement nodeSpanCpt
nodeSpanCpt :: R.Component NodeMainSpanProps nodeSpanCpt :: R.Component NodeMainSpanProps
nodeSpanCpt = here.component "nodeSpan" cpt nodeSpanCpt = here.component "nodeSpan" cpt
where where
...@@ -77,11 +76,11 @@ nodeSpanCpt = here.component "nodeSpan" cpt ...@@ -77,11 +76,11 @@ nodeSpanCpt = here.component "nodeSpan" cpt
nodeMainSpan :: R2.Component NodeMainSpanProps nodeMainSpan :: R2.Component NodeMainSpanProps
nodeMainSpan = R.createElement nodeMainSpanCpt nodeMainSpan = R.createElement nodeMainSpanCpt
nodeMainSpanCpt :: R.Component NodeMainSpanProps nodeMainSpanCpt :: R.Component NodeMainSpanProps
nodeMainSpanCpt = here.component "nodeMainSpan" cpt nodeMainSpanCpt = here.component "nodeMainSpan" cpt
where where
cpt props@{ dispatch cpt props@{ dispatch
, errors
, folderOpen , folderOpen
, frontends , frontends
, handed , handed
...@@ -129,10 +128,11 @@ nodeMainSpanCpt = here.component "nodeMainSpan" cpt ...@@ -129,10 +128,11 @@ nodeMainSpanCpt = here.component "nodeMainSpan" cpt
, fileTypeView { dispatch, droppedFile, id, isDragOver, nodeType } , fileTypeView { dispatch, droppedFile, id, isDragOver, nodeType }
, H.div {} (map (\t -> asyncProgressBar { asyncTask: t , H.div {} (map (\t -> asyncProgressBar { asyncTask: t
, barType: Pie , barType: Pie
, nodeId: id , errors
, onFinish: onTaskFinish id t , nodeId: id
, session } [] , onFinish: onTaskFinish id t
, session } []
) currentTasks' ) currentTasks'
) )
, if nodeType == GT.NodeUser , if nodeType == GT.NodeUser
...@@ -188,7 +188,7 @@ nodeMainSpanCpt = here.component "nodeMainSpan" cpt ...@@ -188,7 +188,7 @@ nodeMainSpanCpt = here.component "nodeMainSpan" cpt
name' {name: n, nodeType: nt} = if nt == GT.NodeUser then show session else n name' {name: n, nodeType: nt} = if nt == GT.NodeUser then show session else n
mNodePopupView props'@{ id: i, nodeType: nt, handed: h } opc = mNodePopupView props'@{ id: i, nodeType: nt, handed: h } opc =
nodePopupView { dispatch, handed: h, id: i, name: name' props' nodePopupView { dispatch, errors, handed: h, id: i, name: name' props'
, nodeType: nt, onPopoverClose: opc, session } , nodeType: nt, onPopoverClose: opc, session }
popOverIcon = popOverIcon =
......
module Gargantext.Components.Forest.Tree.Node.Action where module Gargantext.Components.Forest.Tree.Node.Action where
import Data.Generic.Rep (class Generic) import Data.Generic.Rep (class Generic)
import Data.Eq.Generic (genericEq)
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Effect.Aff (Aff) import Effect.Aff (Aff)
......
...@@ -2,7 +2,6 @@ module Gargantext.Components.Forest.Tree.Node.Action.Add where ...@@ -2,7 +2,6 @@ module Gargantext.Components.Forest.Tree.Node.Action.Add where
import Gargantext.Prelude import Gargantext.Prelude
import Control.Monad.Error.Class (throwError)
import Data.Array (head, length) import Data.Array (head, length)
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.Generic.Rep (class Generic) import Data.Generic.Rep (class Generic)
...@@ -11,16 +10,7 @@ import Data.Newtype (class Newtype) ...@@ -11,16 +10,7 @@ import Data.Newtype (class Newtype)
import Data.String (Pattern(..), indexOf) import Data.String (Pattern(..), indexOf)
import Data.Tuple.Nested ((/\)) import Data.Tuple.Nested ((/\))
import Effect (Effect) import Effect (Effect)
import Effect.Aff (Aff, error, launchAff_) import Effect.Aff (Aff, launchAff_)
import Effect.Class (liftEffect)
import Reactix as R
import Reactix.DOM.HTML as H
import Simple.JSON as JSON
import Toestand as T
import Web.HTML (window)
import Web.HTML.Navigator (userAgent)
import Web.HTML.Window (navigator)
import Gargantext.Components.Forest.Tree.Node.Action (Action(..)) import Gargantext.Components.Forest.Tree.Node.Action (Action(..))
import Gargantext.Components.Forest.Tree.Node.Settings (SettingsBox(..), settingsBox) import Gargantext.Components.Forest.Tree.Node.Settings (SettingsBox(..), settingsBox)
import Gargantext.Components.Forest.Tree.Node.Tools (formChoiceSafe, panel, submitButton) import Gargantext.Components.Forest.Tree.Node.Tools (formChoiceSafe, panel, submitButton)
...@@ -33,6 +23,13 @@ import Gargantext.Types (NodeType(..), charCodeIcon) ...@@ -33,6 +23,13 @@ import Gargantext.Types (NodeType(..), charCodeIcon)
import Gargantext.Types as GT import Gargantext.Types as GT
import Gargantext.Utils (nbsp) import Gargantext.Utils (nbsp)
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
import Simple.JSON as JSON
import Toestand as T
import Web.HTML (window)
import Web.HTML.Navigator (userAgent)
import Web.HTML.Window (navigator)
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.Forest.Tree.Node.Action.Add" here = R2.here "Gargantext.Components.Forest.Tree.Node.Action.Add"
...@@ -43,12 +40,12 @@ addNode session parentId = post session $ GR.NodeAPI GT.Node (Just parentId) "" ...@@ -43,12 +40,12 @@ addNode session parentId = post session $ GR.NodeAPI GT.Node (Just parentId) ""
addNodeAsync :: Session addNodeAsync :: Session
-> GT.ID -> GT.ID
-> AddNodeValue -> AddNodeValue
-> Aff GT.AsyncTaskWithType -> Aff (Either RESTError GT.AsyncTaskWithType)
addNodeAsync session parentId q = do addNodeAsync session parentId q = do
eTask :: Either RESTError GT.AsyncTask <- post session p q eTask :: Either RESTError GT.AsyncTask <- post session p q
case eTask of case eTask of
Left _err -> liftEffect $ throwError $ error "[addNodeAsync] RESTError" Left err -> pure $ Left err
Right task -> pure $ GT.AsyncTaskWithType { task, typ: GT.AddNode } Right task -> pure $ Right $ GT.AsyncTaskWithType { task, typ: GT.AddNode }
where where
p = GR.NodeAPI GT.Node (Just parentId) (GT.asyncTaskTypePath GT.AddNode) p = GR.NodeAPI GT.Node (Just parentId) (GT.asyncTaskTypePath GT.AddNode)
......
...@@ -2,19 +2,11 @@ module Gargantext.Components.Forest.Tree.Node.Action.Link where ...@@ -2,19 +2,11 @@ module Gargantext.Components.Forest.Tree.Node.Action.Link where
import Gargantext.Prelude import Gargantext.Prelude
import Control.Monad.Error.Class (throwError) import Data.Either (Either)
import Data.Either (Either(..))
import Data.Generic.Rep (class Generic) import Data.Generic.Rep (class Generic)
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Data.Show.Generic (genericShow) import Data.Show.Generic (genericShow)
import Effect.Aff (Aff) import Effect.Aff (Aff)
import Effect.Class (liftEffect)
import Effect.Exception (error)
import Reactix as R
import Reactix.DOM.HTML as H
import Simple.JSON as JSON
import Toestand as T
import Gargantext.Components.Forest.Tree.Node.Action (Action(..)) import Gargantext.Components.Forest.Tree.Node.Action (Action(..))
import Gargantext.Components.Forest.Tree.Node.Tools (submitButton, panel) import Gargantext.Components.Forest.Tree.Node.Tools (submitButton, panel)
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree (subTreeView, SubTreeParamsIn) import Gargantext.Components.Forest.Tree.Node.Tools.SubTree (subTreeView, SubTreeParamsIn)
...@@ -23,6 +15,10 @@ import Gargantext.Routes (SessionRoute(..)) ...@@ -23,6 +15,10 @@ import Gargantext.Routes (SessionRoute(..))
import Gargantext.Sessions (Session, post) import Gargantext.Sessions (Session, post)
import Gargantext.Types as GT import Gargantext.Types as GT
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
import Simple.JSON as JSON
import Toestand as T
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.Forest.Tree.Node.Action.Link" here = R2.here "Gargantext.Components.Forest.Tree.Node.Action.Link"
...@@ -35,13 +31,11 @@ derive newtype instance JSON.ReadForeign LinkNodeReq ...@@ -35,13 +31,11 @@ derive newtype instance JSON.ReadForeign LinkNodeReq
derive newtype instance JSON.WriteForeign LinkNodeReq derive newtype instance JSON.WriteForeign LinkNodeReq
linkNodeReq :: Session -> Maybe GT.NodeType -> GT.ID -> GT.ID -> Aff GT.AsyncTaskWithType linkNodeReq :: Session -> Maybe GT.NodeType -> GT.ID -> GT.ID -> Aff (Either RESTError GT.AsyncTaskWithType)
linkNodeReq session nt fromId toId = do linkNodeReq session nt fromId toId = do
eTask :: Either RESTError GT.AsyncTask <- post session (NodeAPI GT.Node (Just fromId) "update") eTask :: Either RESTError GT.AsyncTask <- post session (NodeAPI GT.Node (Just fromId) "update")
(LinkNodeReq { nodeType: linkNodeType nt, id: toId }) (LinkNodeReq { nodeType: linkNodeType nt, id: toId })
case eTask of pure $ (\task -> GT.AsyncTaskWithType { task, typ: GT.UpdateNode }) <$> eTask
Left _err -> liftEffect $ throwError $ error "[linkNodeReq] RESTError"
Right task -> pure $ GT.AsyncTaskWithType { task, typ: GT.UpdateNode }
linkNodeType :: Maybe GT.NodeType -> GT.NodeType linkNodeType :: Maybe GT.NodeType -> GT.NodeType
linkNodeType (Just GT.Corpus) = GT.Annuaire linkNodeType (Just GT.Corpus) = GT.Annuaire
......
module Gargantext.Components.Forest.Tree.Node.Action.Search where module Gargantext.Components.Forest.Tree.Node.Action.Search where
import Gargantext.Prelude
import Data.Maybe (Maybe) import Data.Maybe (Maybe)
import Effect (Effect) import Effect (Effect)
import Effect.Aff (Aff, launchAff) import Effect.Aff (Aff, launchAff)
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
import Gargantext.Prelude
import Gargantext.Components.Forest.Tree.Node.Action (Action(..)) import Gargantext.Components.Forest.Tree.Node.Action (Action(..))
import Gargantext.Components.Forest.Tree.Node.Action.Add (NodePopup) import Gargantext.Components.Forest.Tree.Node.Action.Add (NodePopup)
import Gargantext.Components.Forest.Tree.Node.Action.Search.SearchBar (searchBar) import Gargantext.Components.Forest.Tree.Node.Action.Search.SearchBar (searchBar)
import Gargantext.Components.Forest.Tree.Node.Action.Search.SearchField (defaultSearch) import Gargantext.Components.Forest.Tree.Node.Action.Search.SearchField (defaultSearch)
import Gargantext.Components.Lang (allLangs) import Gargantext.Components.Lang (allLangs)
import Gargantext.Sessions (Session) import Gargantext.Sessions (Session)
import Gargantext.Types (ID) import Gargantext.Types (FrontendError, ID)
import Gargantext.Types as GT import Gargantext.Types as GT
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.Forest.Tree.Node.Action.Search" here = R2.here "Gargantext.Components.Forest.Tree.Node.Action.Search"
...@@ -25,6 +24,7 @@ here = R2.here "Gargantext.Components.Forest.Tree.Node.Action.Search" ...@@ -25,6 +24,7 @@ here = R2.here "Gargantext.Components.Forest.Tree.Node.Action.Search"
type Props = type Props =
( dispatch :: Action -> Aff Unit ( dispatch :: Action -> Aff Unit
, errors :: T.Box (Array FrontendError)
, id :: Maybe ID , id :: Maybe ID
, nodePopup :: Maybe NodePopup , nodePopup :: Maybe NodePopup
, session :: Session ) , session :: Session )
...@@ -35,12 +35,13 @@ actionSearch = R.createElement actionSearchCpt ...@@ -35,12 +35,13 @@ actionSearch = R.createElement actionSearchCpt
actionSearchCpt :: R.Component Props actionSearchCpt :: R.Component Props
actionSearchCpt = here.component "actionSearch" cpt actionSearchCpt = here.component "actionSearch" cpt
where where
cpt { dispatch, id, nodePopup, session } _ = do cpt { dispatch, errors, id, nodePopup, session } _ = do
search <- T.useBox $ defaultSearch { node_id = id } search <- T.useBox $ defaultSearch { node_id = id }
pure $ R.fragment [ H.p { className: "action-search" } pure $ R.fragment [ H.p { className: "action-search" }
[ H.text $ "Search and create a private " [ H.text $ "Search and create a private "
<> "corpus with the search query as corpus name." ] <> "corpus with the search query as corpus name." ]
, searchBar { langs: allLangs , searchBar { errors
, langs: allLangs
, onSearch: searchOn dispatch nodePopup , onSearch: searchOn dispatch nodePopup
, search , search
, session , session
......
...@@ -3,24 +3,25 @@ module Gargantext.Components.Forest.Tree.Node.Action.Search.SearchBar ...@@ -3,24 +3,25 @@ module Gargantext.Components.Forest.Tree.Node.Action.Search.SearchBar
, searchBar , searchBar
) where ) where
import Data.Tuple.Nested ((/\)) import Gargantext.Components.Forest.Tree.Node.Action.Search.Types
import Effect (Effect)
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
import Effect (Effect)
import Gargantext.Components.Forest.Tree.Node.Action.Search.SearchField (searchField) import Gargantext.Components.Forest.Tree.Node.Action.Search.SearchField (searchField)
import Gargantext.Components.Forest.Tree.Node.Action.Search.Types -- (Database, SearchQuery(..), defaultSearchQuery, performSearch, Lang(..))
import Gargantext.Components.Lang (Lang) import Gargantext.Components.Lang (Lang)
import Gargantext.Prelude (Unit, pure, ($)) import Gargantext.Prelude (Unit, pure, ($))
import Gargantext.Sessions (Session) import Gargantext.Sessions (Session)
import Gargantext.Types (FrontendError)
import Gargantext.Types as GT import Gargantext.Types as GT
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.Forest.Tree.Node.Action.Search.SearchBar" here = R2.here "Gargantext.Components.Forest.Tree.Node.Action.Search.SearchBar"
type Props = ( langs :: Array Lang type Props = ( errors :: T.Box (Array FrontendError)
, langs :: Array Lang
, onSearch :: GT.AsyncTaskWithType -> Effect Unit , onSearch :: GT.AsyncTaskWithType -> Effect Unit
, search :: T.Box Search , search :: T.Box Search
, session :: Session , session :: Session
...@@ -28,14 +29,14 @@ type Props = ( langs :: Array Lang ...@@ -28,14 +29,14 @@ type Props = ( langs :: Array Lang
searchBar :: R2.Component Props searchBar :: R2.Component Props
searchBar = R.createElement searchBarCpt searchBar = R.createElement searchBarCpt
searchBarCpt :: R.Component Props searchBarCpt :: R.Component Props
searchBarCpt = here.component "searchBar" cpt searchBarCpt = here.component "searchBar" cpt
where where
cpt { langs, onSearch, search, session } _ = do cpt { errors, langs, onSearch, search, session } _ = do
--onSearchChange session s --onSearchChange session s
pure $ H.div { className: "search-bar" } pure $ H.div { className: "search-bar" }
[ searchField { databases:allDatabases [ searchField { databases:allDatabases
, errors
, langs , langs
, onSearch , onSearch
, search , search
......
module Gargantext.Components.Forest.Tree.Node.Action.Search.SearchField where module Gargantext.Components.Forest.Tree.Node.Action.Search.SearchField where
import Gargantext.Prelude
import DOM.Simple.Console (log, log2) import DOM.Simple.Console (log, log2)
import Data.Maybe (Maybe(..), maybe, fromMaybe) import Data.Maybe (Maybe(..), maybe, fromMaybe)
import Data.Nullable (null)
import Data.Newtype (over) import Data.Newtype (over)
import Data.Nullable (null)
import Data.Set as Set import Data.Set as Set
import Data.Tuple.Nested ((/\)) import Data.Tuple.Nested ((/\))
import Effect (Effect) import Effect (Effect)
import Effect.Aff (launchAff_) import Effect.Aff (launchAff_)
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import Reactix as R import Gargantext.Components.Forest.Tree.Node.Action.Search.Frame (searchIframes)
import Reactix.DOM.HTML as H
import Toestand as T
import Gargantext.Prelude
import Gargantext.Components.Forest.Tree.Node.Action.Search.Types (DataField(..), Database(..), IMT_org(..), Org(..), SearchQuery(..), allIMTorgs, allOrgs, dataFields, defaultSearchQuery, doc, performSearch, datafield2database, Search) import Gargantext.Components.Forest.Tree.Node.Action.Search.Types (DataField(..), Database(..), IMT_org(..), Org(..), SearchQuery(..), allIMTorgs, allOrgs, dataFields, defaultSearchQuery, doc, performSearch, datafield2database, Search)
import Gargantext.Components.InputWithEnter (inputWithEnter) import Gargantext.Components.InputWithEnter (inputWithEnter)
import Gargantext.Components.Lang (Lang) import Gargantext.Components.Lang (Lang)
import Gargantext.Config.Utils (handleRESTError)
import Gargantext.Sessions (Session) import Gargantext.Sessions (Session)
import Gargantext.Components.Forest.Tree.Node.Action.Search.Frame (searchIframes) import Gargantext.Types (FrontendError)
import Gargantext.Types as GT import Gargantext.Types as GT
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.Forest.Tree.Node.Action.Search.SearchField" here = R2.here "Gargantext.Components.Forest.Tree.Node.Action.Search.SearchField"
...@@ -38,6 +39,7 @@ defaultSearch = { databases: Empty ...@@ -38,6 +39,7 @@ defaultSearch = { databases: Empty
type Props = type Props =
-- list of databases to search, or parsers to use on uploads -- list of databases to search, or parsers to use on uploads
( databases :: Array Database ( databases :: Array Database
, errors :: T.Box (Array FrontendError)
, langs :: Array Lang , langs :: Array Lang
-- State hook for a search, how we get data in and out -- State hook for a search, how we get data in and out
, onSearch :: GT.AsyncTaskWithType -> Effect Unit , onSearch :: GT.AsyncTaskWithType -> Effect Unit
...@@ -47,11 +49,10 @@ type Props = ...@@ -47,11 +49,10 @@ type Props =
searchField :: R2.Component Props searchField :: R2.Component Props
searchField = R.createElement searchFieldCpt searchField = R.createElement searchFieldCpt
searchFieldCpt :: R.Component Props searchFieldCpt :: R.Component Props
searchFieldCpt = here.component "searchField" cpt searchFieldCpt = here.component "searchField" cpt
where where
cpt props@{ onSearch, search } _ = do cpt props@{ errors, onSearch, search, session } _ = do
search' <- T.useLive T.unequal search search' <- T.useLive T.unequal search
iframeRef <- R.useRef null iframeRef <- R.useRef null
let params = let params =
...@@ -86,7 +87,7 @@ searchFieldCpt = here.component "searchField" cpt ...@@ -86,7 +87,7 @@ searchFieldCpt = here.component "searchField" cpt
] ]
] ]
let button = submitButton {onSearch, search, session: props.session} [] let button = submitButton { errors, onSearch, search, session } []
pure $ pure $
...@@ -103,7 +104,6 @@ type ComponentProps = ...@@ -103,7 +104,6 @@ type ComponentProps =
componentIMT :: R2.Component ComponentProps componentIMT :: R2.Component ComponentProps
componentIMT = R.createElement componentIMTCpt componentIMT = R.createElement componentIMTCpt
componentIMTCpt :: R.Component ComponentProps componentIMTCpt :: R.Component ComponentProps
componentIMTCpt = here.component "componentIMT" cpt componentIMTCpt = here.component "componentIMT" cpt
where where
...@@ -242,7 +242,6 @@ type LangNavProps = ...@@ -242,7 +242,6 @@ type LangNavProps =
langNav :: R2.Component LangNavProps langNav :: R2.Component LangNavProps
langNav = R.createElement langNavCpt langNav = R.createElement langNavCpt
langNavCpt :: R.Component LangNavProps langNavCpt :: R.Component LangNavProps
langNavCpt = here.component "langNav" cpt langNavCpt = here.component "langNav" cpt
where where
...@@ -267,7 +266,6 @@ type DataFieldNavProps = ...@@ -267,7 +266,6 @@ type DataFieldNavProps =
dataFieldNav :: R2.Component DataFieldNavProps dataFieldNav :: R2.Component DataFieldNavProps
dataFieldNav = R.createElement dataFieldNavCpt dataFieldNav = R.createElement dataFieldNavCpt
dataFieldNavCpt :: R.Component DataFieldNavProps dataFieldNavCpt :: R.Component DataFieldNavProps
dataFieldNavCpt = here.component "dataFieldNav" cpt dataFieldNavCpt = here.component "dataFieldNav" cpt
where where
...@@ -306,7 +304,6 @@ type DatabaseInputProps = ( ...@@ -306,7 +304,6 @@ type DatabaseInputProps = (
databaseInput :: R2.Component DatabaseInputProps databaseInput :: R2.Component DatabaseInputProps
databaseInput = R.createElement databaseInputCpt databaseInput = R.createElement databaseInputCpt
databaseInputCpt :: R.Component DatabaseInputProps databaseInputCpt :: R.Component DatabaseInputProps
databaseInputCpt = here.component "databaseInput" cpt databaseInputCpt = here.component "databaseInput" cpt
where where
...@@ -347,7 +344,6 @@ type OrgInputProps = ...@@ -347,7 +344,6 @@ type OrgInputProps =
orgInput :: R2.Component OrgInputProps orgInput :: R2.Component OrgInputProps
orgInput = R.createElement orgInputCpt orgInput = R.createElement orgInputCpt
orgInputCpt :: R.Component OrgInputProps orgInputCpt :: R.Component OrgInputProps
orgInputCpt = here.component "orgInput" cpt orgInputCpt = here.component "orgInput" cpt
where where
...@@ -390,7 +386,6 @@ type SearchInputProps = ...@@ -390,7 +386,6 @@ type SearchInputProps =
searchInput :: R2.Component SearchInputProps searchInput :: R2.Component SearchInputProps
searchInput = R.createElement searchInputCpt searchInput = R.createElement searchInputCpt
searchInputCpt :: R.Component SearchInputProps searchInputCpt :: R.Component SearchInputProps
searchInputCpt = here.component "searchInput" cpt searchInputCpt = here.component "searchInput" cpt
where where
...@@ -429,39 +424,40 @@ searchInputCpt = here.component "searchInput" cpt ...@@ -429,39 +424,40 @@ searchInputCpt = here.component "searchInput" cpt
-- setSearch $ _ { term = value } -- setSearch $ _ { term = value }
type SubmitButtonProps = type SubmitButtonProps =
( onSearch :: GT.AsyncTaskWithType -> Effect Unit ( errors :: T.Box (Array FrontendError)
, onSearch :: GT.AsyncTaskWithType -> Effect Unit
, search :: T.Box Search , search :: T.Box Search
, session :: Session , session :: Session
) )
submitButton :: R2.Component SubmitButtonProps submitButton :: R2.Component SubmitButtonProps
submitButton = R.createElement submitButtonComponent submitButton = R.createElement submitButtonComponent
submitButtonComponent :: R.Component SubmitButtonProps submitButtonComponent :: R.Component SubmitButtonProps
submitButtonComponent = here.component "submitButton" cpt submitButtonComponent = here.component "submitButton" cpt
where where
cpt { onSearch, search, session } _ = do cpt { errors, onSearch, search, session } _ = do
search' <- T.useLive T.unequal search search' <- T.useLive T.unequal search
pure $ pure $
H.button { className: "btn btn-primary" H.button { className: "btn btn-primary"
, "type" : "button" , "type" : "button"
, on : { click: doSearch onSearch session search' } , on : { click: doSearch onSearch errors session search' }
, style : { width: "100%" } , style : { width: "100%" }
} [ H.text "Launch Search" ] } [ H.text "Launch Search" ]
doSearch os s q = \_ -> do doSearch os errors s q = \_ -> do
log2 "[submitButton] searching" q log2 "[submitButton] searching" q
triggerSearch os s q triggerSearch os errors s q
--case search.term of --case search.term of
-- "" -> setSearch $ const defaultSearch -- "" -> setSearch $ const defaultSearch
-- _ -> setSearch $ const q -- _ -> setSearch $ const q
triggerSearch :: (GT.AsyncTaskWithType -> Effect Unit) triggerSearch :: (GT.AsyncTaskWithType -> Effect Unit)
-> T.Box (Array FrontendError)
-> Session -> Session
-> Search -> Search
-> Effect Unit -> Effect Unit
triggerSearch os s q = triggerSearch os errors s q =
launchAff_ $ do launchAff_ $ do
liftEffect $ do liftEffect $ do
let here' = "[triggerSearch] Searching " let here' = "[triggerSearch] Searching "
...@@ -473,8 +469,8 @@ triggerSearch os s q = ...@@ -473,8 +469,8 @@ triggerSearch os s q =
case q.node_id of case q.node_id of
Nothing -> liftEffect $ log "[triggerSearch] node_id is Nothing, don't know what to do" Nothing -> liftEffect $ log "[triggerSearch] node_id is Nothing, don't know what to do"
Just id -> do Just id -> do
task <- performSearch s id $ searchQuery q eTask <- performSearch s id $ searchQuery q
liftEffect $ do handleRESTError errors eTask $ \task -> liftEffect $ do
log2 "[triggerSearch] task" task log2 "[triggerSearch] task" task
os task os task
......
module Gargantext.Components.Forest.Tree.Node.Action.Search.Types where module Gargantext.Components.Forest.Tree.Node.Action.Search.Types where
import Control.Monad.Error.Class (throwError)
import Data.Array (concat) import Data.Array (concat)
import Data.Either (Either(..)) import Data.Either (Either)
import Data.Generic.Rep (class Generic) import Data.Generic.Rep (class Generic)
import Data.Maybe (Maybe(..), fromMaybe, maybe) import Data.Maybe (Maybe(..), fromMaybe, maybe)
import Data.Newtype (class Newtype) import Data.Newtype (class Newtype)
...@@ -11,8 +10,7 @@ import Data.Set as Set ...@@ -11,8 +10,7 @@ import Data.Set as Set
import Data.String as String import Data.String as String
import Data.Tuple (Tuple) import Data.Tuple (Tuple)
import Data.Tuple.Nested ((/\)) import Data.Tuple.Nested ((/\))
import Effect.Aff (Aff, error) import Effect.Aff (Aff)
import Effect.Class (liftEffect)
import Simple.JSON as JSON import Simple.JSON as JSON
import URI.Extra.QueryPairs as QP import URI.Extra.QueryPairs as QP
import URI.Query as Q import URI.Query as Q
...@@ -363,18 +361,16 @@ instance GT.ToQuery SearchQuery where ...@@ -363,18 +361,16 @@ instance GT.ToQuery SearchQuery where
pair k = maybe [] $ \v -> pair k = maybe [] $ \v ->
[ QP.keyFromString k /\ Just (QP.valueFromString $ show v) ] [ QP.keyFromString k /\ Just (QP.valueFromString $ show v) ]
instance JSON.WriteForeign SearchQuery where instance JSON.WriteForeign SearchQuery where
writeImpl (SearchQuery { datafield, databases, lang, node_id, query }) = writeImpl (SearchQuery { databases, lang, node_id, query }) =
JSON.writeImpl { query: String.replace (String.Pattern "\"") (String.Replacement "\\\"") query JSON.writeImpl { query: String.replace (String.Pattern "\"") (String.Replacement "\\\"") query
, databases: databases , databases: databases
, lang: maybe "EN" show lang , lang: maybe "EN" show lang
, node_id: fromMaybe 0 node_id , node_id: fromMaybe 0 node_id
} }
performSearch :: Session -> Int -> SearchQuery -> Aff GT.AsyncTaskWithType performSearch :: Session -> Int -> SearchQuery -> Aff (Either RESTError GT.AsyncTaskWithType)
performSearch session nodeId q = do performSearch session nodeId q = do
eTask :: Either RESTError GT.AsyncTask <- post session p q eTask :: Either RESTError GT.AsyncTask <- post session p q
case eTask of pure $ (\task -> GT.AsyncTaskWithType { task, typ: GT.Query }) <$> eTask
Left _err -> liftEffect $ throwError $ error "[performSearch] RESTError"
Right task -> pure $ GT.AsyncTaskWithType { task, typ: GT.Query }
where where
p = GR.NodeAPI GT.Corpus (Just nodeId) $ GT.asyncTaskTypePath GT.Query p = GR.NodeAPI GT.Corpus (Just nodeId) $ GT.asyncTaskTypePath GT.Query
module Gargantext.Components.Forest.Tree.Node.Action.Update where module Gargantext.Components.Forest.Tree.Node.Action.Update where
import Control.Monad.Error.Class (throwError)
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Effect.Aff (Aff) import Effect.Aff (Aff)
import Effect.Class (liftEffect)
import Effect.Exception (error)
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as H import Reactix.DOM.HTML as H
import Toestand as T import Toestand as T
...@@ -25,12 +22,12 @@ import Gargantext.Utils.Reactix as R2 ...@@ -25,12 +22,12 @@ import Gargantext.Utils.Reactix as R2
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.Forest.Tree.Node.Action.Update" here = R2.here "Gargantext.Components.Forest.Tree.Node.Action.Update"
updateRequest :: UpdateNodeParams -> Session -> ID -> Aff GT.AsyncTaskWithType updateRequest :: UpdateNodeParams -> Session -> ID -> Aff (Either RESTError GT.AsyncTaskWithType)
updateRequest updateNodeParams session nodeId = do updateRequest updateNodeParams session nodeId = do
eTask :: Either RESTError GT.AsyncTask <- post session p updateNodeParams eTask :: Either RESTError GT.AsyncTask <- post session p updateNodeParams
case eTask of case eTask of
Left _err -> liftEffect $ throwError $ error "[updateRequest] RESTError" Left err -> pure $ Left err
Right task -> pure $ GT.AsyncTaskWithType { task, typ: GT.UpdateNode } Right task -> pure $ Right $ GT.AsyncTaskWithType { task, typ: GT.UpdateNode }
where where
p = GR.NodeAPI GT.Node (Just nodeId) "update" p = GR.NodeAPI GT.Node (Just nodeId) "update"
......
...@@ -2,8 +2,6 @@ module Gargantext.Components.Forest.Tree.Node.Action.Upload where ...@@ -2,8 +2,6 @@ module Gargantext.Components.Forest.Tree.Node.Action.Upload where
import Gargantext.Prelude import Gargantext.Prelude
import Control.Monad.Error.Class (throwError)
import DOM.Simple.Console (log2)
import Data.Either (Either(..), fromRight') import Data.Either (Either(..), fromRight')
import Data.Eq.Generic (genericEq) import Data.Eq.Generic (genericEq)
import Data.Generic.Rep (class Generic) import Data.Generic.Rep (class Generic)
...@@ -16,7 +14,6 @@ import Data.Tuple.Nested ((/\)) ...@@ -16,7 +14,6 @@ import Data.Tuple.Nested ((/\))
import Effect (Effect) import Effect (Effect)
import Effect.Aff (Aff, launchAff) import Effect.Aff (Aff, launchAff)
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import Effect.Exception (error)
import Gargantext.Components.Forest.Tree.Node.Action (Action(..), Props) import Gargantext.Components.Forest.Tree.Node.Action (Action(..), Props)
import Gargantext.Components.Forest.Tree.Node.Action.Upload.Types (FileType(..), UploadFileBlob(..), readUFBAsText) import Gargantext.Components.Forest.Tree.Node.Action.Upload.Types (FileType(..), UploadFileBlob(..), readUFBAsText)
import Gargantext.Components.Forest.Tree.Node.Tools (fragmentPT, formChoiceSafe, panel) import Gargantext.Components.Forest.Tree.Node.Tools (fragmentPT, formChoiceSafe, panel)
...@@ -86,7 +83,7 @@ type UploadFile = ...@@ -86,7 +83,7 @@ type UploadFile =
} }
uploadFileView :: Record Props -> R.Element uploadFileView :: R2.Leaf Props
uploadFileView props = R.createElement uploadFileViewCpt props [] uploadFileView props = R.createElement uploadFileViewCpt props []
uploadFileViewCpt :: R.Component Props uploadFileViewCpt :: R.Component Props
uploadFileViewCpt = here.component "uploadFileView" cpt uploadFileViewCpt = here.component "uploadFileView" cpt
...@@ -191,7 +188,7 @@ uploadButtonCpt = here.component "uploadButton" cpt ...@@ -191,7 +188,7 @@ uploadButtonCpt = here.component "uploadButton" cpt
where where
onClick fileType' mFile' e = do onClick fileType' mFile' e = do
let { blob, name } = unsafePartial $ fromJust mFile' let { blob, name } = unsafePartial $ fromJust mFile'
log2 "[uploadButton] fileType" fileType' here.log2 "[uploadButton] fileType" fileType'
void $ launchAff do void $ launchAff do
case fileType' of case fileType' of
Arbitrary -> Arbitrary ->
...@@ -306,12 +303,13 @@ instance GT.ToQuery FileUploadQuery where ...@@ -306,12 +303,13 @@ instance GT.ToQuery FileUploadQuery where
where pair :: forall a. Show a => String -> a -> Array (Tuple QP.Key (Maybe QP.Value)) where pair :: forall a. Show a => String -> a -> Array (Tuple QP.Key (Maybe QP.Value))
pair k v = [ QP.keyFromString k /\ (Just $ QP.valueFromString $ show v) ] pair k v = [ QP.keyFromString k /\ (Just $ QP.valueFromString $ show v) ]
uploadFile :: Session uploadFile :: { contents :: String
-> GT.NodeType , fileType :: FileType
-> ID , id :: ID
-> FileType , nodeType :: GT.NodeType
-> {contents :: String, mName :: Maybe String} , mName :: Maybe String
-> Aff GT.AsyncTaskWithType , session :: Session }
-> Aff (Either RESTError GT.AsyncTaskWithType)
{- {-
uploadFile session NodeList id JSON { mName, contents } = do uploadFile session NodeList id JSON { mName, contents } = do
let url = GR.NodeAPI NodeList (Just id) $ GT.asyncTaskTypePath GT.ListUpload let url = GR.NodeAPI NodeList (Just id) $ GT.asyncTaskTypePath GT.ListUpload
...@@ -322,12 +320,12 @@ uploadFile session NodeList id JSON { mName, contents } = do ...@@ -322,12 +320,12 @@ uploadFile session NodeList id JSON { mName, contents } = do
task <- post session url body task <- post session url body
pure $ GT.AsyncTaskWithType { task, typ: GT.Form } pure $ GT.AsyncTaskWithType { task, typ: GT.Form }
-} -}
uploadFile session nodeType id fileType { mName, contents } = do uploadFile { contents, fileType, id, nodeType, mName, session } = do
-- contents <- readAsText blob -- contents <- readAsText blob
eTask :: Either RESTError GT.AsyncTask <- postWwwUrlencoded session p bodyParams eTask :: Either RESTError GT.AsyncTask <- postWwwUrlencoded session p bodyParams
case eTask of case eTask of
Left _err -> liftEffect $ throwError $ error "[uploadFile] RESTError" Left err -> pure $ Left err
Right task -> pure $ GT.AsyncTaskWithType { task, typ: GT.Form } Right task -> pure $ Right $ GT.AsyncTaskWithType { task, typ: GT.Form }
--postMultipartFormData session p fileContents --postMultipartFormData session p fileContents
where where
p = case nodeType of p = case nodeType of
......
...@@ -5,7 +5,7 @@ import Gargantext.Prelude ...@@ -5,7 +5,7 @@ import Gargantext.Prelude
import Data.Array as A import Data.Array as A
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Effect.Aff (Aff) import Effect.Aff (Aff)
import Gargantext.Components.Forest.Tree.Node.Action (Action(..)) import Gargantext.Components.Forest.Tree.Node.Action (Action)
import Gargantext.Components.Forest.Tree.Node.Action.Add (NodePopup(..), addNodeView) import Gargantext.Components.Forest.Tree.Node.Action.Add (NodePopup(..), addNodeView)
import Gargantext.Components.Forest.Tree.Node.Action.Contact as Contact import Gargantext.Components.Forest.Tree.Node.Action.Contact as Contact
import Gargantext.Components.Forest.Tree.Node.Action.Delete (actionDelete) import Gargantext.Components.Forest.Tree.Node.Action.Delete (actionDelete)
...@@ -22,9 +22,9 @@ import Gargantext.Components.Forest.Tree.Node.Action.Upload (actionUpload) ...@@ -22,9 +22,9 @@ import Gargantext.Components.Forest.Tree.Node.Action.Upload (actionUpload)
import Gargantext.Components.Forest.Tree.Node.Box.Types (NodePopupProps, NodePopupS) import Gargantext.Components.Forest.Tree.Node.Box.Types (NodePopupProps, NodePopupS)
import Gargantext.Components.Forest.Tree.Node.Settings (NodeAction(..), SettingsBox(..), glyphiconNodeAction, settingsBox) import Gargantext.Components.Forest.Tree.Node.Settings (NodeAction(..), SettingsBox(..), glyphiconNodeAction, settingsBox)
import Gargantext.Components.Forest.Tree.Node.Status (Status(..), hasStatus) import Gargantext.Components.Forest.Tree.Node.Status (Status(..), hasStatus)
import Gargantext.Components.Forest.Tree.Node.Tools (textInputBox, fragmentPT, panel) import Gargantext.Components.Forest.Tree.Node.Tools (textInputBox, fragmentPT)
import Gargantext.Sessions (Session) import Gargantext.Sessions (Session)
import Gargantext.Types (Name, ID, prettyNodeType) import Gargantext.Types (FrontendError, ID, Name, prettyNodeType)
import Gargantext.Types as GT import Gargantext.Types as GT
import Gargantext.Utils.Glyphicon (glyphicon, glyphiconActive) import Gargantext.Utils.Glyphicon (glyphicon, glyphiconActive)
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
...@@ -35,11 +35,12 @@ import Toestand as T ...@@ -35,11 +35,12 @@ import Toestand as T
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.Forest.Tree.Node.Box" here = R2.here "Gargantext.Components.Forest.Tree.Node.Box"
type CommonProps = ( dispatch :: Action -> Aff Unit, session :: Session ) type CommonProps =
( dispatch :: Action -> Aff Unit
, session :: Session )
nodePopupView :: Record NodePopupProps -> R.Element nodePopupView :: Record NodePopupProps -> R.Element
nodePopupView p = R.createElement nodePopupCpt p [] nodePopupView p = R.createElement nodePopupCpt p []
nodePopupCpt :: R.Component NodePopupProps nodePopupCpt :: R.Component NodePopupProps
nodePopupCpt = here.component "nodePopupView" cpt where nodePopupCpt = here.component "nodePopupView" cpt where
cpt p@{ id, name, nodeType } _ = do cpt p@{ id, name, nodeType } _ = do
...@@ -101,8 +102,8 @@ nodePopupCpt = here.component "nodePopupView" cpt where ...@@ -101,8 +102,8 @@ nodePopupCpt = here.component "nodePopupView" cpt where
else [] else []
mPanelAction :: Record NodePopupS -> Record NodePopupProps -> R.Element mPanelAction :: Record NodePopupS -> Record NodePopupProps -> R.Element
mPanelAction { action: Just action } mPanelAction { action: Just action }
{ dispatch, id, name, nodeType, session, handed } = { dispatch, errors, id, name, nodeType, session, handed } =
panelAction { action, dispatch, id, name, nodeType, session panelAction { action, dispatch, errors, id, name, nodeType, session
, handed, nodePopup: Just NodePopup } , handed, nodePopup: Just NodePopup }
mPanelAction { action: Nothing } _ = mPanelAction { action: Nothing } _ =
H.div { className: "card-footer" } H.div { className: "card-footer" }
...@@ -162,6 +163,7 @@ type PanelActionProps = ...@@ -162,6 +163,7 @@ type PanelActionProps =
( id :: ID ( id :: ID
, action :: NodeAction , action :: NodeAction
, dispatch :: Action -> Aff Unit , dispatch :: Action -> Aff Unit
, errors :: T.Box (Array FrontendError)
, name :: Name , name :: Name
, nodePopup :: Maybe NodePopup , nodePopup :: Maybe NodePopup
, nodeType :: GT.NodeType , nodeType :: GT.NodeType
...@@ -169,9 +171,8 @@ type PanelActionProps = ...@@ -169,9 +171,8 @@ type PanelActionProps =
, handed :: GT.Handed , handed :: GT.Handed
) )
panelAction :: Record PanelActionProps -> R.Element panelAction :: R2.Leaf PanelActionProps
panelAction p = R.createElement panelActionCpt p [] panelAction p = R.createElement panelActionCpt p []
panelActionCpt :: R.Component PanelActionProps panelActionCpt :: R.Component PanelActionProps
panelActionCpt = here.component "panelAction" cpt panelActionCpt = here.component "panelAction" cpt
where where
...@@ -195,6 +196,6 @@ panelActionCpt = here.component "panelAction" cpt ...@@ -195,6 +196,6 @@ panelActionCpt = here.component "panelAction" cpt
cpt {action : AddingContact, dispatch, id, name } _ = pure $ Contact.actionAddContact { dispatch, id } [] cpt {action : AddingContact, dispatch, id, name } _ = pure $ Contact.actionAddContact { dispatch, id } []
cpt {action : Publish {subTreeParams}, dispatch, id, nodeType, session, handed} _ = cpt {action : Publish {subTreeParams}, dispatch, id, nodeType, session, handed} _ =
pure $ Share.publishNode { dispatch, handed, id, nodeType, session, subTreeParams } [] pure $ Share.publishNode { dispatch, handed, id, nodeType, session, subTreeParams } []
cpt props@{action: SearchBox, id, session, dispatch, nodePopup} _ = cpt props@{action: SearchBox, errors, id, session, dispatch, nodePopup} _ =
pure $ actionSearch { dispatch, id: (Just id), nodePopup, session } [] pure $ actionSearch { dispatch, errors, id: (Just id), nodePopup, session } []
cpt _ _ = pure $ H.div {} [] cpt _ _ = pure $ H.div {} []
...@@ -4,12 +4,13 @@ import DOM.Simple as DOM ...@@ -4,12 +4,13 @@ import DOM.Simple as DOM
import Data.Maybe (Maybe) import Data.Maybe (Maybe)
import Effect (Effect) import Effect (Effect)
import Effect.Aff (Aff) import Effect.Aff (Aff)
import Gargantext.Components.Forest.Tree.Node.Settings (NodeAction)
import Gargantext.Components.Forest.Tree.Node.Action (Action) import Gargantext.Components.Forest.Tree.Node.Action (Action)
import Gargantext.Components.Forest.Tree.Node.Settings (NodeAction)
import Gargantext.Prelude (Unit) import Gargantext.Prelude (Unit)
import Gargantext.Sessions (Session) import Gargantext.Sessions (Session)
import Gargantext.Types (ID, Name) import Gargantext.Types (FrontendError, ID, Name)
import Gargantext.Types as GT import Gargantext.Types as GT
import Toestand as T
type CommonProps = type CommonProps =
( dispatch :: Action -> Aff Unit ( dispatch :: Action -> Aff Unit
...@@ -18,7 +19,8 @@ type CommonProps = ...@@ -18,7 +19,8 @@ type CommonProps =
) )
type NodePopupProps = type NodePopupProps =
( id :: ID ( errors :: T.Box (Array FrontendError)
, id :: ID
, name :: Name , name :: Name
, nodeType :: GT.NodeType , nodeType :: GT.NodeType
, onPopoverClose :: DOM.Element -> Effect Unit , onPopoverClose :: DOM.Element -> Effect Unit
......
...@@ -2,18 +2,18 @@ module Gargantext.Components.Forest.Tree.Node.Tools.ProgressBar where ...@@ -2,18 +2,18 @@ module Gargantext.Components.Forest.Tree.Node.Tools.ProgressBar where
import Gargantext.Prelude import Gargantext.Prelude
import Control.Monad.Error.Class (throwError) import Data.Either (Either)
import Data.Either (Either(..))
import Data.Int (fromNumber) import Data.Int (fromNumber)
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Data.Tuple.Nested ((/\))
import Effect (Effect) import Effect (Effect)
import Effect.Aff (Aff, error, launchAff_) import Effect.Aff (Aff, launchAff_)
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import Effect.Timer (clearInterval, setInterval) import Effect.Timer (clearInterval, setInterval)
import Gargantext.Config.REST (RESTError) import Gargantext.Config.REST (RESTError)
import Gargantext.Config.Utils (handleRESTError)
import Gargantext.Routes (SessionRoute(..)) import Gargantext.Routes (SessionRoute(..))
import Gargantext.Sessions (Session, get) import Gargantext.Sessions (Session, get)
import Gargantext.Types (FrontendError)
import Gargantext.Types as GT import Gargantext.Types as GT
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Reactix as R import Reactix as R
...@@ -29,6 +29,7 @@ data BarType = Bar | Pie ...@@ -29,6 +29,7 @@ data BarType = Bar | Pie
type Props = ( type Props = (
asyncTask :: GT.AsyncTaskWithType asyncTask :: GT.AsyncTaskWithType
, barType :: BarType , barType :: BarType
, errors :: T.Box (Array FrontendError)
, nodeId :: GT.ID , nodeId :: GT.ID
, onFinish :: Unit -> Effect Unit , onFinish :: Unit -> Effect Unit
, session :: Session , session :: Session
...@@ -42,6 +43,7 @@ asyncProgressBarCpt = here.component "asyncProgressBar" cpt ...@@ -42,6 +43,7 @@ asyncProgressBarCpt = here.component "asyncProgressBar" cpt
where where
cpt props@{ asyncTask: (GT.AsyncTaskWithType {task: GT.AsyncTask {id}}) cpt props@{ asyncTask: (GT.AsyncTaskWithType {task: GT.AsyncTask {id}})
, barType , barType
, errors
, onFinish , onFinish
} _ = do } _ = do
progress <- T.useBox 0.0 progress <- T.useBox 0.0
...@@ -51,19 +53,16 @@ asyncProgressBarCpt = here.component "asyncProgressBar" cpt ...@@ -51,19 +53,16 @@ asyncProgressBarCpt = here.component "asyncProgressBar" cpt
intervalId <- setInterval 1000 $ do intervalId <- setInterval 1000 $ do
launchAff_ $ do launchAff_ $ do
eAsyncProgress <- queryProgress props eAsyncProgress <- queryProgress props
case eAsyncProgress of handleRESTError errors eAsyncProgress $ \asyncProgress -> liftEffect $ do
Left _err -> throwError $ error "[asyncProgressBar] RESTError" let GT.AsyncProgress { status } = asyncProgress
Right asyncProgress -> do T.write_ (min 100.0 $ GT.progressPercent asyncProgress) progress
let GT.AsyncProgress { status } = asyncProgress if (status == GT.IsFinished) || (status == GT.IsKilled) || (status == GT.IsFailure) then do
liftEffect do _ <- case R.readRef intervalIdRef of
T.write_ (min 100.0 $ GT.progressPercent asyncProgress) progress Nothing -> pure unit
if (status == GT.IsFinished) || (status == GT.IsKilled) || (status == GT.IsFailure) then do Just iid -> clearInterval iid
_ <- case R.readRef intervalIdRef of onFinish unit
Nothing -> pure unit else
Just iid -> clearInterval iid pure unit
onFinish unit
else
pure unit
R.setRef intervalIdRef $ Just intervalId R.setRef intervalIdRef $ Just intervalId
......
...@@ -4,9 +4,8 @@ module Gargantext.Components.Nodes.Annuaire.Tabs where ...@@ -4,9 +4,8 @@ module Gargantext.Components.Nodes.Annuaire.Tabs where
import Prelude hiding (div) import Prelude hiding (div)
import Data.Generic.Rep (class Generic) import Data.Generic.Rep (class Generic)
import Data.Show.Generic (genericShow)
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Data.Tuple (fst) import Data.Show.Generic (genericShow)
import Data.Tuple.Nested ((/\)) import Data.Tuple.Nested ((/\))
import Effect.Aff (Aff) import Effect.Aff (Aff)
import Gargantext.AsyncTasks as GAT import Gargantext.AsyncTasks as GAT
...@@ -16,12 +15,11 @@ import Gargantext.Components.NgramsTable as NT ...@@ -16,12 +15,11 @@ import Gargantext.Components.NgramsTable as NT
import Gargantext.Components.NgramsTable.Core as NTC import Gargantext.Components.NgramsTable.Core as NTC
import Gargantext.Components.Nodes.Annuaire.User.Contacts.Types (ContactData) import Gargantext.Components.Nodes.Annuaire.User.Contacts.Types (ContactData)
import Gargantext.Components.Nodes.Lists.Types as LTypes import Gargantext.Components.Nodes.Lists.Types as LTypes
import Gargantext.Components.Nodes.Texts.Types as TTypes
import Gargantext.Components.Nodes.Texts.Types as TextsT import Gargantext.Components.Nodes.Texts.Types as TextsT
import Gargantext.Components.Tab as Tab import Gargantext.Components.Tab as Tab
import Gargantext.Ends (Frontends) import Gargantext.Ends (Frontends)
import Gargantext.Sessions (Session) import Gargantext.Sessions (Session)
import Gargantext.Types (CTabNgramType(..), PTabNgramType(..), SidePanelState, TabType(..), TabSubType(..)) import Gargantext.Types (CTabNgramType(..), FrontendError, PTabNgramType(..), SidePanelState, TabSubType(..), TabType(..))
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2 import Gargantext.Utils.Toestand as T2
import Reactix as R import Reactix as R
...@@ -55,6 +53,7 @@ modeTabType' Communication = CTabAuthors ...@@ -55,6 +53,7 @@ modeTabType' Communication = CTabAuthors
type TabsProps = type TabsProps =
( cacheState :: T.Box LTypes.CacheState ( cacheState :: T.Box LTypes.CacheState
, contactData :: ContactData , contactData :: ContactData
, errors :: T.Box (Array FrontendError)
, frontends :: Frontends , frontends :: Frontends
, nodeId :: Int , nodeId :: Int
, reloadForest :: T2.ReloadS , reloadForest :: T2.ReloadS
...@@ -89,6 +88,7 @@ tabsCpt = here.component "tabs" cpt where ...@@ -89,6 +88,7 @@ tabsCpt = here.component "tabs" cpt where
dtCommon = RX.pick props :: Record DTCommon dtCommon = RX.pick props :: Record DTCommon
dtExtra = dtExtra =
{ chart: mempty { chart: mempty
, errors: props.errors
, listId: props.contactData.defaultListId , listId: props.contactData.defaultListId
, mCorpusId: Nothing , mCorpusId: Nothing
, showSearch: true , showSearch: true
......
...@@ -23,7 +23,7 @@ import Gargantext.Ends (Frontends) ...@@ -23,7 +23,7 @@ import Gargantext.Ends (Frontends)
import Gargantext.Hooks.Loader (useLoader) import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Routes as Routes import Gargantext.Routes as Routes
import Gargantext.Sessions (WithSession, WithSessionContext, Session, get, put, sessionId) import Gargantext.Sessions (WithSession, WithSessionContext, Session, get, put, sessionId)
import Gargantext.Types (NodeType(..), SidePanelState) import Gargantext.Types (FrontendError, NodeType(..), SidePanelState)
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2 import Gargantext.Utils.Toestand as T2
import Reactix as R import Reactix as R
...@@ -153,7 +153,8 @@ listElement = H.li { className: "list-group-item justify-content-between" } ...@@ -153,7 +153,8 @@ listElement = H.li { className: "list-group-item justify-content-between" }
-} -}
type LayoutNoSessionProps = type LayoutNoSessionProps =
( frontends :: Frontends ( errors :: T.Box (Array FrontendError)
, frontends :: Frontends
, nodeId :: Int , nodeId :: Int
, reloadForest :: T2.ReloadS , reloadForest :: T2.ReloadS
, reloadRoot :: T2.ReloadS , reloadRoot :: T2.ReloadS
...@@ -176,7 +177,8 @@ userLayout = R.createElement userLayoutCpt ...@@ -176,7 +177,8 @@ userLayout = R.createElement userLayoutCpt
userLayoutCpt :: R.Component LayoutProps userLayoutCpt :: R.Component LayoutProps
userLayoutCpt = here.component "userLayout" cpt userLayoutCpt = here.component "userLayout" cpt
where where
cpt { frontends cpt { errors
, frontends
, nodeId , nodeId
, reloadForest , reloadForest
, reloadRoot , reloadRoot
...@@ -187,7 +189,8 @@ userLayoutCpt = here.component "userLayout" cpt ...@@ -187,7 +189,8 @@ userLayoutCpt = here.component "userLayout" cpt
let sid = sessionId session let sid = sessionId session
pure $ userLayoutWithKey { pure $ userLayoutWithKey {
frontends errors
, frontends
, key: show sid <> "-" <> show nodeId , key: show sid <> "-" <> show nodeId
, nodeId , nodeId
, reloadForest , reloadForest
...@@ -198,52 +201,53 @@ userLayoutCpt = here.component "userLayout" cpt ...@@ -198,52 +201,53 @@ userLayoutCpt = here.component "userLayout" cpt
, tasks , tasks
} }
userLayoutWithKey :: Record KeyLayoutProps -> R.Element userLayoutWithKey :: R2.Leaf KeyLayoutProps
userLayoutWithKey props = R.createElement userLayoutWithKeyCpt props [] userLayoutWithKey props = R.createElement userLayoutWithKeyCpt props []
userLayoutWithKeyCpt :: R.Component KeyLayoutProps userLayoutWithKeyCpt :: R.Component KeyLayoutProps
userLayoutWithKeyCpt = here.component "userLayoutWithKey" cpt userLayoutWithKeyCpt = here.component "userLayoutWithKey" cpt where
where cpt { errors
cpt { frontends , frontends
, nodeId , nodeId
, reloadForest , reloadForest
, reloadRoot , reloadRoot
, session , session
, sidePanel , sidePanel
, sidePanelState , sidePanelState
, tasks } _ = do , tasks } _ = do
reload <- T.useBox T2.newReload reload <- T.useBox T2.newReload
reload' <- T.useLive T.unequal reload reload' <- T.useLive T.unequal reload
cacheState <- T.useBox LT.CacheOn cacheState <- T.useBox LT.CacheOn
useLoader { errorHandler useLoader { errorHandler
, loader: getUserWithReload , loader: getUserWithReload
, path: { nodeId, reload: reload', session } , path: { nodeId, reload: reload', session }
, render: \contactData@{contactNode: Contact {name, hyperdata}} -> , render: \contactData@{contactNode: Contact {name, hyperdata}} ->
H.ul { className: "col-md-12 list-group" } [ H.ul { className: "col-md-12 list-group" } [
display { title: fromMaybe "no name" name } display { title: fromMaybe "no name" name }
(contactInfos hyperdata (onUpdateHyperdata reload)) (contactInfos hyperdata (onUpdateHyperdata reload))
, Tabs.tabs { , Tabs.tabs {
cacheState cacheState
, contactData , contactData
, frontends , errors
, nodeId , frontends
, reloadForest , nodeId
, reloadRoot , reloadForest
, session , reloadRoot
, sidePanel , session
, sidePanelState , sidePanel
, tasks , sidePanelState
} , tasks
}
] ]
} }
where where
errorHandler err = here.log2 "[userLayoutWithKey] RESTError" err errorHandler err = here.log2 "[userLayoutWithKey] RESTError" err
onUpdateHyperdata :: T2.ReloadS -> HyperdataUser -> Effect Unit onUpdateHyperdata :: T2.ReloadS -> HyperdataUser -> Effect Unit
onUpdateHyperdata reload hd = do onUpdateHyperdata reload hd = do
launchAff_ $ do launchAff_ $ do
_ <- saveContactHyperdata session nodeId hd _ <- saveContactHyperdata session nodeId hd
liftEffect $ T2.reload reload liftEffect $ T2.reload reload
-- | toUrl to get data XXX -- | toUrl to get data XXX
getContact :: Session -> Int -> Aff (Either RESTError ContactData) getContact :: Session -> Int -> Aff (Either RESTError ContactData)
......
...@@ -3,28 +3,18 @@ module Gargantext.Components.Nodes.Annuaire.User.Contact ...@@ -3,28 +3,18 @@ module Gargantext.Components.Nodes.Annuaire.User.Contact
, contactLayout , contactLayout
) where ) where
import Gargantext.Prelude
import Data.Either (Either) import Data.Either (Either)
import Data.Lens as L import Data.Lens as L
import Data.Maybe (Maybe(..), fromMaybe) import Data.Maybe (Maybe(..), fromMaybe)
import Effect (Effect) import Effect (Effect)
import Effect.Aff (Aff, launchAff_) import Effect.Aff (Aff, launchAff_)
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
import Gargantext.Prelude
import Gargantext.AsyncTasks as GAT import Gargantext.AsyncTasks as GAT
import Gargantext.Components.InputWithEnter (inputWithEnter) import Gargantext.Components.InputWithEnter (inputWithEnter)
import Gargantext.Components.Nodes.Annuaire.User.Contacts.Tabs as Tabs import Gargantext.Components.Nodes.Annuaire.User.Contacts.Tabs as Tabs
import Gargantext.Components.Nodes.Annuaire.User.Contacts.Types import Gargantext.Components.Nodes.Annuaire.User.Contacts.Types (Contact'(..), ContactData', ContactTouch(..), ContactWhere(..), ContactWho(..), HyperdataContact(..), HyperdataUser(..), _city, _country, _firstName, _labTeamDeptsJoinComma, _lastName, _mail, _office, _organizationJoinComma, _ouFirst, _phone, _role, _shared, _touch, _who, defaultContactTouch, defaultContactWhere, defaultContactWho, defaultHyperdataContact, defaultHyperdataUser)
( Contact'(..), ContactData', ContactTouch(..), ContactWhere(..)
, ContactWho(..), HyperdataContact(..), HyperdataUser(..)
, _city, _country, _firstName, _labTeamDeptsJoinComma, _lastName
, _mail, _office, _organizationJoinComma, _ouFirst, _phone, _role
, _shared, _touch, _who, defaultContactTouch, defaultContactWhere
, defaultContactWho, defaultHyperdataContact, defaultHyperdataUser )
import Gargantext.Components.Nodes.Lists.Types as LT import Gargantext.Components.Nodes.Lists.Types as LT
import Gargantext.Components.Nodes.Texts.Types as TT import Gargantext.Components.Nodes.Texts.Types as TT
import Gargantext.Config.REST (RESTError) import Gargantext.Config.REST (RESTError)
...@@ -32,9 +22,12 @@ import Gargantext.Ends (Frontends) ...@@ -32,9 +22,12 @@ import Gargantext.Ends (Frontends)
import Gargantext.Hooks.Loader (useLoader) import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Routes as Routes import Gargantext.Routes as Routes
import Gargantext.Sessions (Session, get, put, sessionId) import Gargantext.Sessions (Session, get, put, sessionId)
import Gargantext.Types (NodeType(..), SidePanelState) import Gargantext.Types (FrontendError, NodeType(..), SidePanelState)
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2 import Gargantext.Utils.Toestand as T2
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.Nodes.Annuaire.User.Contact" here = R2.here "Gargantext.Components.Nodes.Annuaire.User.Contact"
...@@ -43,7 +36,6 @@ type DisplayProps = ( title :: String ) ...@@ -43,7 +36,6 @@ type DisplayProps = ( title :: String )
display :: R2.Component DisplayProps display :: R2.Component DisplayProps
display = R.createElement displayCpt display = R.createElement displayCpt
displayCpt :: R.Component DisplayProps displayCpt :: R.Component DisplayProps
displayCpt = here.component "display" cpt displayCpt = here.component "display" cpt
where where
...@@ -140,7 +132,8 @@ contactInfoItemCpt = here.component "contactInfoItem" cpt ...@@ -140,7 +132,8 @@ contactInfoItemCpt = here.component "contactInfoItem" cpt
onUpdateHyperdata newHyperdata onUpdateHyperdata newHyperdata
type BasicProps = type BasicProps =
( frontends :: Frontends ( errors :: T.Box (Array FrontendError)
, frontends :: Frontends
, nodeId :: Int , nodeId :: Int
, sidePanelState :: T.Box SidePanelState , sidePanelState :: T.Box SidePanelState
, sidePanel :: T.Box (Maybe (Record TT.SidePanel)) , sidePanel :: T.Box (Maybe (Record TT.SidePanel))
...@@ -166,10 +159,10 @@ type AnnuaireKeyLayoutProps = ( annuaireId :: Int | KeyLayoutProps ) ...@@ -166,10 +159,10 @@ type AnnuaireKeyLayoutProps = ( annuaireId :: Int | KeyLayoutProps )
contactLayout :: R2.Component AnnuaireLayoutProps contactLayout :: R2.Component AnnuaireLayoutProps
contactLayout = R.createElement contactLayoutCpt contactLayout = R.createElement contactLayoutCpt
contactLayoutCpt :: R.Component AnnuaireLayoutProps contactLayoutCpt :: R.Component AnnuaireLayoutProps
contactLayoutCpt = here.component "contactLayout" cpt where contactLayoutCpt = here.component "contactLayout" cpt where
cpt { annuaireId cpt { annuaireId
, errors
, frontends , frontends
, nodeId , nodeId
, reloadForest , reloadForest
...@@ -182,6 +175,7 @@ contactLayoutCpt = here.component "contactLayout" cpt where ...@@ -182,6 +175,7 @@ contactLayoutCpt = here.component "contactLayout" cpt where
pure $ pure $
contactLayoutWithKey contactLayoutWithKey
{ annuaireId { annuaireId
, errors
, frontends , frontends
, key , key
, nodeId , nodeId
...@@ -198,6 +192,7 @@ contactLayoutWithKey props = R.createElement contactLayoutWithKeyCpt props [] ...@@ -198,6 +192,7 @@ contactLayoutWithKey props = R.createElement contactLayoutWithKeyCpt props []
contactLayoutWithKeyCpt :: R.Component AnnuaireKeyLayoutProps contactLayoutWithKeyCpt :: R.Component AnnuaireKeyLayoutProps
contactLayoutWithKeyCpt = here.component "contactLayoutWithKey" cpt where contactLayoutWithKeyCpt = here.component "contactLayoutWithKey" cpt where
cpt { annuaireId cpt { annuaireId
, errors
, frontends , frontends
, reloadForest , reloadForest
, reloadRoot , reloadRoot
...@@ -219,6 +214,7 @@ contactLayoutWithKeyCpt = here.component "contactLayoutWithKey" cpt where ...@@ -219,6 +214,7 @@ contactLayoutWithKeyCpt = here.component "contactLayoutWithKey" cpt where
, Tabs.tabs , Tabs.tabs
{ cacheState { cacheState
, contactData , contactData
, errors
, frontends , frontends
, nodeId , nodeId
, session , session
......
-- TODO copy of Gargantext.Components.Nodes.Corpus.Tabs.Specs -- TODO copy of Gargantext.Components.Nodes.Corpus.Tabs.Specs
module Gargantext.Components.Nodes.Annuaire.User.Contacts.Tabs where module Gargantext.Components.Nodes.Annuaire.User.Contacts.Tabs where
import Prelude hiding (div) import Gargantext.Prelude
import Data.Generic.Rep (class Generic) import Data.Generic.Rep (class Generic)
import Data.Show.Generic (genericShow)
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Data.Tuple (fst) import Data.Show.Generic (genericShow)
import Data.Tuple.Nested ((/\)) import Data.Tuple.Nested ((/\))
import Gargantext.AsyncTasks as GAT import Gargantext.AsyncTasks as GAT
import Gargantext.Components.DocsTable as DT import Gargantext.Components.DocsTable as DT
...@@ -19,7 +18,7 @@ import Gargantext.Components.Nodes.Texts.Types as TTypes ...@@ -19,7 +18,7 @@ import Gargantext.Components.Nodes.Texts.Types as TTypes
import Gargantext.Components.Tab as Tab import Gargantext.Components.Tab as Tab
import Gargantext.Ends (Frontends) import Gargantext.Ends (Frontends)
import Gargantext.Sessions (Session) import Gargantext.Sessions (Session)
import Gargantext.Types (CTabNgramType(..), PTabNgramType(..), SidePanelState, TabType(..), TabSubType(..)) import Gargantext.Types (CTabNgramType(..), FrontendError, PTabNgramType(..), SidePanelState, TabSubType(..), TabType(..))
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2 import Gargantext.Utils.Toestand as T2
import Reactix as R import Reactix as R
...@@ -52,6 +51,7 @@ modeTabType' Communication = CTabAuthors ...@@ -52,6 +51,7 @@ modeTabType' Communication = CTabAuthors
type TabsProps = ( type TabsProps = (
cacheState :: T.Box LTypes.CacheState cacheState :: T.Box LTypes.CacheState
, contactData :: ContactData' , contactData :: ContactData'
, errors :: T.Box (Array FrontendError)
, frontends :: Frontends , frontends :: Frontends
, nodeId :: Int , nodeId :: Int
, reloadForest :: T2.ReloadS , reloadForest :: T2.ReloadS
...@@ -62,22 +62,23 @@ type TabsProps = ( ...@@ -62,22 +62,23 @@ type TabsProps = (
, tasks :: T.Box GAT.Storage , tasks :: T.Box GAT.Storage
) )
tabs :: Record TabsProps -> R.Element tabs :: R2.Leaf TabsProps
tabs props = R.createElement tabsCpt props [] tabs props = R.createElement tabsCpt props []
tabsCpt :: R.Component TabsProps tabsCpt :: R.Component TabsProps
tabsCpt = here.component "tabs" cpt tabsCpt = here.component "tabs" cpt
where where
cpt { reloadRoot cpt { cacheState
, tasks
, cacheState
, contactData: {defaultListId} , contactData: {defaultListId}
, errors
, frontends , frontends
, nodeId , nodeId
, reloadRoot
, reloadForest
, session , session
, sidePanel , sidePanel
, sidePanelState , sidePanelState
, reloadForest } _ = do , tasks
} _ = do
activeTab <- T.useBox 0 activeTab <- T.useBox 0
yearFilter <- T.useBox (Nothing :: Maybe Year) yearFilter <- T.useBox (Nothing :: Maybe Year)
...@@ -119,6 +120,7 @@ tabsCpt = here.component "tabs" cpt ...@@ -119,6 +120,7 @@ tabsCpt = here.component "tabs" cpt
docs = DT.docViewLayout docs = DT.docViewLayout
{ cacheState { cacheState
, chart , chart
, errors
, frontends , frontends
, listId: defaultListId , listId: defaultListId
, mCorpusId: Nothing , mCorpusId: Nothing
......
module Gargantext.Components.Nodes.Corpus where module Gargantext.Components.Nodes.Corpus where
import DOM.Simple.Console (log2)
import Data.Array as A import Data.Array as A
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.Eq.Generic (genericEq) import Data.Eq.Generic (genericEq)
...@@ -7,16 +8,10 @@ import Data.Generic.Rep (class Generic) ...@@ -7,16 +8,10 @@ import Data.Generic.Rep (class Generic)
import Data.List as List import Data.List as List
import Data.Maybe (Maybe(..), fromMaybe) import Data.Maybe (Maybe(..), fromMaybe)
import Data.Show.Generic (genericShow) import Data.Show.Generic (genericShow)
import DOM.Simple.Console (log2)
import Effect (Effect) import Effect (Effect)
import Effect.Aff (Aff, launchAff_, throwError) import Effect.Aff (Aff, launchAff_, throwError)
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import Effect.Exception (error) import Effect.Exception (error)
import Reactix as R
import Reactix.DOM.HTML as H
import Simple.JSON as JSON
import Toestand as T
import Gargantext.AsyncTasks as GAT import Gargantext.AsyncTasks as GAT
import Gargantext.Components.CodeEditor as CE import Gargantext.Components.CodeEditor as CE
import Gargantext.Components.FolderView as FV import Gargantext.Components.FolderView as FV
...@@ -30,41 +25,49 @@ import Gargantext.Hooks.Loader (useLoader) ...@@ -30,41 +25,49 @@ import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Prelude (class Eq, class Show, Unit, bind, discard, pure, show, unit, ($), (+), (-), (<), (<$>), (<<<), (<>), (==), (>)) import Gargantext.Prelude (class Eq, class Show, Unit, bind, discard, pure, show, unit, ($), (+), (-), (<), (<$>), (<<<), (<>), (==), (>))
import Gargantext.Routes (SessionRoute(Children, NodeAPI)) import Gargantext.Routes (SessionRoute(Children, NodeAPI))
import Gargantext.Sessions (Session, get, put, sessionId) import Gargantext.Sessions (Session, get, put, sessionId)
import Gargantext.Types (AffETableResult, NodeType(..)) import Gargantext.Types (AffETableResult, FrontendError, NodeType(..))
import Gargantext.Utils.Crypto as Crypto import Gargantext.Utils.Crypto as Crypto
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2 import Gargantext.Utils.Toestand as T2
import Reactix as R
import Reactix.DOM.HTML as H
import Simple.JSON as JSON
import Toestand as T
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.Nodes.Corpus" here = R2.here "Gargantext.Components.Nodes.Corpus"
type Props = ( nodeId :: Int, session :: Session, tasks :: T.Box GAT.Storage, reloadForest :: T2.ReloadS ) type Props =
( errors :: T.Box (Array FrontendError)
, nodeId :: Int
, reloadForest :: T2.ReloadS
, session :: Session
, tasks :: T.Box GAT.Storage )
corpusLayout :: R2.Leaf Props corpusLayout :: R2.Leaf Props
corpusLayout props = R.createElement corpusLayoutCpt props [] corpusLayout props = R.createElement corpusLayoutCpt props []
corpusLayoutCpt :: R.Component Props corpusLayoutCpt :: R.Component Props
corpusLayoutCpt = here.component "corpusLayout" cpt where corpusLayoutCpt = here.component "corpusLayout" cpt where
cpt { nodeId, session, tasks, reloadForest } _ = do cpt { errors, nodeId, session, tasks, reloadForest } _ = do
pure $ corpusLayoutMain { key, nodeId, session, tasks, reloadForest } pure $ corpusLayoutMain { errors, key, nodeId, session, tasks, reloadForest }
where where
key = show (sessionId session) <> "-" <> show nodeId key = show (sessionId session) <> "-" <> show nodeId
type KeyProps = type KeyProps =
( nodeId :: Int ( errors :: T.Box (Array FrontendError)
, key :: String , key :: String
, nodeId :: Int
, reloadForest :: T2.ReloadS
, session :: Session , session :: Session
, tasks :: T.Box GAT.Storage , tasks :: T.Box GAT.Storage
, reloadForest :: T2.ReloadS
) )
corpusLayoutMain :: R2.Leaf KeyProps corpusLayoutMain :: R2.Leaf KeyProps
corpusLayoutMain props = R.createElement corpusLayoutMainCpt props [] corpusLayoutMain props = R.createElement corpusLayoutMainCpt props []
corpusLayoutMainCpt :: R.Component KeyProps corpusLayoutMainCpt :: R.Component KeyProps
corpusLayoutMainCpt = here.component "corpusLayoutMain" cpt corpusLayoutMainCpt = here.component "corpusLayoutMain" cpt
where where
cpt { nodeId, key, session, tasks, reloadForest } _ = do cpt { errors, nodeId, key, session, tasks, reloadForest } _ = do
viewType <- T.useBox Folders viewType <- T.useBox Folders
pure $ H.div {} [ pure $ H.div {} [
...@@ -74,11 +77,12 @@ corpusLayoutMainCpt = here.component "corpusLayoutMain" cpt ...@@ -74,11 +77,12 @@ corpusLayoutMainCpt = here.component "corpusLayoutMain" cpt
, H.div { className: "col-1" } [ FV.homeButton ] , H.div { className: "col-1" } [ FV.homeButton ]
] ]
] ]
, H.div {} [corpusLayoutSelection {state: viewType, key, session, nodeId, tasks, reloadForest}] , H.div {} [corpusLayoutSelection { errors, state: viewType, key, session, nodeId, tasks, reloadForest }]
] ]
type SelectionProps = type SelectionProps =
( nodeId :: Int ( errors :: T.Box (Array FrontendError)
, nodeId :: Int
, key :: String , key :: String
, session :: Session , session :: Session
, state :: T.Box ViewType , state :: T.Box ViewType
...@@ -88,17 +92,17 @@ type SelectionProps = ...@@ -88,17 +92,17 @@ type SelectionProps =
corpusLayoutSelection :: R2.Leaf SelectionProps corpusLayoutSelection :: R2.Leaf SelectionProps
corpusLayoutSelection props = R.createElement corpusLayoutSelectionCpt props [] corpusLayoutSelection props = R.createElement corpusLayoutSelectionCpt props []
corpusLayoutSelectionCpt :: R.Component SelectionProps corpusLayoutSelectionCpt :: R.Component SelectionProps
corpusLayoutSelectionCpt = here.component "corpusLayoutSelection" cpt where corpusLayoutSelectionCpt = here.component "corpusLayoutSelection" cpt where
cpt { nodeId, session, key, state, tasks, reloadForest} _ = do cpt { errors, nodeId, session, key, state, tasks, reloadForest} _ = do
state' <- T.useLive T.unequal state state' <- T.useLive T.unequal state
viewType <- T.read state viewType <- T.read state
pure $ renderContent viewType nodeId session key tasks reloadForest pure $ renderContent viewType nodeId session key tasks reloadForest errors
renderContent Folders nodeId session key tasks reloadForest = FV.folderView { nodeId, session, backFolder: true, tasks, reloadForest } renderContent Folders nodeId session key tasks reloadForest errors =
renderContent Code nodeId session key tasks _ = corpusLayoutWithKey { key, nodeId, session } FV.folderView { errors, nodeId, session, backFolder: true, tasks, reloadForest }
renderContent Code nodeId session key tasks _ _ = corpusLayoutWithKey { key, nodeId, session }
type CorpusKeyProps = type CorpusKeyProps =
( nodeId :: Int ( nodeId :: Int
...@@ -108,7 +112,6 @@ type CorpusKeyProps = ...@@ -108,7 +112,6 @@ type CorpusKeyProps =
corpusLayoutWithKey :: R2.Leaf CorpusKeyProps corpusLayoutWithKey :: R2.Leaf CorpusKeyProps
corpusLayoutWithKey props = R.createElement corpusLayoutWithKeyCpt props [] corpusLayoutWithKey props = R.createElement corpusLayoutWithKeyCpt props []
corpusLayoutWithKeyCpt :: R.Component CorpusKeyProps corpusLayoutWithKeyCpt :: R.Component CorpusKeyProps
corpusLayoutWithKeyCpt = here.component "corpusLayoutWithKey" cpt where corpusLayoutWithKeyCpt = here.component "corpusLayoutWithKey" cpt where
cpt { nodeId, session } _ = do cpt { nodeId, session } _ = do
......
module Gargantext.Components.Nodes.Corpus.Chart.Common where module Gargantext.Components.Nodes.Corpus.Chart.Common where
import Gargantext.Prelude
import Data.Array as A
import Data.Either (Either) import Data.Either (Either)
import Data.Tuple.Nested ((/\)) import Data.Tuple.Nested ((/\))
import Effect.Aff (Aff) import Effect.Aff (Aff)
import Reactix as R
import Simple.JSON as JSON
import Toestand as T
import Gargantext.Prelude
import Gargantext.Components.Nodes.Corpus.Chart.Types (MetricsProps, ReloadPath) import Gargantext.Components.Nodes.Corpus.Chart.Types (MetricsProps, ReloadPath)
import Gargantext.Config.REST (RESTError) import Gargantext.Config.REST (RESTError)
import Gargantext.Hooks.Loader (HashedResponse, useLoader, useLoaderWithCacheAPI) import Gargantext.Hooks.Loader (HashedResponse, useLoader, useLoaderWithCacheAPI)
import Gargantext.Utils.Crypto (Hash)
import Gargantext.Sessions (Session) import Gargantext.Sessions (Session)
import Gargantext.Types (FrontendError(..))
import Gargantext.Utils.CacheAPI as GUC import Gargantext.Utils.CacheAPI as GUC
import Gargantext.Utils.Crypto (Hash)
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Reactix as R
import Simple.JSON as JSON
import Toestand as T
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.Nodes.Corpus.Chart.Common" here = R2.here "Gargantext.Components.Nodes.Corpus.Chart.Common"
...@@ -34,21 +35,23 @@ metricsLoadView p = R.createElement metricsLoadViewCpt p [] ...@@ -34,21 +35,23 @@ metricsLoadView p = R.createElement metricsLoadViewCpt p []
metricsLoadViewCpt :: forall a. Eq a => R.Component (MetricsLoadViewProps a) metricsLoadViewCpt :: forall a. Eq a => R.Component (MetricsLoadViewProps a)
metricsLoadViewCpt = here.component "metricsLoadView" cpt metricsLoadViewCpt = here.component "metricsLoadView" cpt
where where
cpt { getMetrics, loaded, path, reload, session, onClick, onInit } _ = do cpt { errors, getMetrics, loaded, onClick, onInit, path, reload, session } _ = do
reload' <- T.useLive T.unequal reload reload' <- T.useLive T.unequal reload
useLoader { errorHandler useLoader { errorHandler
, loader: getMetrics session , loader: getMetrics session
, path: reload' /\ path , path: reload' /\ path
, render: \l -> loaded { path, reload, session, onClick, onInit } l } , render: \l -> loaded { errors, path, reload, session, onClick, onInit } l }
where where
errorHandler err = here.log2 "RESTError" err errorHandler error = do
T.modify_ (A.cons $ FRESTError { error }) errors
here.log2 "RESTError" error
type MetricsWithCacheLoadViewProps res ret = ( type MetricsWithCacheLoadViewProps res ret =
getMetricsHash :: Session -> ReloadPath -> Aff (Either RESTError Hash) ( getMetricsHash :: Session -> ReloadPath -> Aff (Either RESTError Hash)
, handleResponse :: HashedResponse res -> ret , handleResponse :: HashedResponse res -> ret
, loaded :: Record MetricsProps -> ret -> R.Element , loaded :: Record MetricsProps -> ret -> R.Element
, mkRequest :: ReloadPath -> GUC.Request , mkRequest :: ReloadPath -> GUC.Request
| MetricsProps | MetricsProps
) )
...@@ -61,11 +64,21 @@ metricsWithCacheLoadViewCpt :: forall res ret. ...@@ -61,11 +64,21 @@ metricsWithCacheLoadViewCpt :: forall res ret.
R.Component (MetricsWithCacheLoadViewProps res ret) R.Component (MetricsWithCacheLoadViewProps res ret)
metricsWithCacheLoadViewCpt = here.component "metricsWithCacheLoadView" cpt metricsWithCacheLoadViewCpt = here.component "metricsWithCacheLoadView" cpt
where where
cpt { getMetricsHash, handleResponse, loaded, mkRequest, path, reload, session, onClick, onInit } _ = do cpt { errors
, getMetricsHash
, handleResponse
, loaded
, mkRequest
, path
, reload
, session
, onClick
, onInit } _ = do
reload' <- T.useLive T.unequal reload reload' <- T.useLive T.unequal reload
useLoaderWithCacheAPI { cacheEndpoint: (getMetricsHash session) useLoaderWithCacheAPI { cacheEndpoint: (getMetricsHash session)
, errors
, handleResponse , handleResponse
, mkRequest , mkRequest
, path: (reload' /\ path) , path: (reload' /\ path)
, renderer: loaded { path, reload, session, onClick, onInit } } , renderer: loaded { errors, path, reload, session, onClick, onInit } }
...@@ -95,15 +95,15 @@ mkRequest session (_ /\ path) = GUC.makeGetRequest session $ chartUrl path ...@@ -95,15 +95,15 @@ mkRequest session (_ /\ path) = GUC.makeGetRequest session $ chartUrl path
histo :: Record Props -> R.Element histo :: Record Props -> R.Element
histo props = R.createElement histoCpt props [] histo props = R.createElement histoCpt props []
histoCpt :: R.Component Props histoCpt :: R.Component Props
histoCpt = here.component "histo" cpt histoCpt = here.component "histo" cpt
where where
cpt { path, session, onClick, onInit } _ = do cpt { errors, path, session, onClick, onInit } _ = do
reload <- T.useBox T2.newReload reload <- T.useBox T2.newReload
pure $ metricsWithCacheLoadView { pure $ metricsWithCacheLoadView {
getMetricsHash errors
, getMetricsHash
, handleResponse , handleResponse
, loaded , loaded
, mkRequest: mkRequest session , mkRequest: mkRequest session
......
...@@ -110,15 +110,15 @@ mkRequest session (_ /\ path) = GUC.makeGetRequest session $ chartUrl path ...@@ -110,15 +110,15 @@ mkRequest session (_ /\ path) = GUC.makeGetRequest session $ chartUrl path
metrics :: Record Props -> R.Element metrics :: Record Props -> R.Element
metrics props = R.createElement metricsCpt props [] metrics props = R.createElement metricsCpt props []
metricsCpt :: R.Component Props metricsCpt :: R.Component Props
metricsCpt = here.component "etrics" cpt metricsCpt = here.component "etrics" cpt
where where
cpt {path, session, onClick, onInit } _ = do cpt { errors, onClick, onInit, path, session } _ = do
reload <- T.useBox T2.newReload reload <- T.useBox T2.newReload
pure $ metricsWithCacheLoadView { pure $ metricsWithCacheLoadView {
getMetricsHash errors
, getMetricsHash
, handleResponse , handleResponse
, loaded , loaded
, mkRequest: mkRequest session , mkRequest: mkRequest session
......
...@@ -85,7 +85,7 @@ chartOptionsPie { onClick, onInit } (HistoMetrics { dates: dates', count: count' ...@@ -85,7 +85,7 @@ chartOptionsPie { onClick, onInit } (HistoMetrics { dates: dates', count: count'
} }
getMetricsHash :: Session -> ReloadPath -> Aff (Either RESTError String) getMetricsHash :: Session -> ReloadPath -> Aff (Either RESTError String)
getMetricsHash session (_ /\ { corpusId, limit, listId, tabType }) = do getMetricsHash session (_ /\ { corpusId, listId, tabType }) = do
get session $ ChartHash { chartType: ChartPie, listId: mListId, tabType } (Just corpusId) get session $ ChartHash { chartType: ChartPie, listId: mListId, tabType } (Just corpusId)
where where
mListId = if listId == 0 then Nothing else (Just listId) mListId = if listId == 0 then Nothing else (Just listId)
...@@ -99,19 +99,19 @@ handleResponse :: HashedResponse ChartMetrics -> HistoMetrics ...@@ -99,19 +99,19 @@ handleResponse :: HashedResponse ChartMetrics -> HistoMetrics
handleResponse (HashedResponse { value: ChartMetrics ms }) = ms."data" handleResponse (HashedResponse { value: ChartMetrics ms }) = ms."data"
mkRequest :: Session -> ReloadPath -> GUC.Request mkRequest :: Session -> ReloadPath -> GUC.Request
mkRequest session (_ /\ path@{ corpusId, limit, listId, tabType }) = GUC.makeGetRequest session $ chartUrl path mkRequest session (_ /\ path) = GUC.makeGetRequest session $ chartUrl path
pie :: R2.Leaf Props pie :: R2.Leaf Props
pie props = R.createElement pieCpt props [] pie props = R.createElement pieCpt props []
pieCpt :: R.Component Props pieCpt :: R.Component Props
pieCpt = here.component "pie" cpt pieCpt = here.component "pie" cpt
where where
cpt { path, session, onClick, onInit } _ = do cpt { errors, path, session, onClick, onInit } _ = do
reload <- T.useBox T2.newReload reload <- T.useBox T2.newReload
pure $ metricsWithCacheLoadView { pure $ metricsWithCacheLoadView {
getMetricsHash errors
, getMetricsHash
, handleResponse , handleResponse
, loaded: loadedPie , loaded: loadedPie
, mkRequest: mkRequest session , mkRequest: mkRequest session
...@@ -123,7 +123,7 @@ pieCpt = here.component "pie" cpt ...@@ -123,7 +123,7 @@ pieCpt = here.component "pie" cpt
} }
loadedPie :: Record MetricsProps -> HistoMetrics -> R.Element loadedPie :: Record MetricsProps -> HistoMetrics -> R.Element
loadedPie p@{ path, reload, session } loaded = loadedPie p loaded =
H.div {} [ H.div {} [
{- U.reloadButton reload {- U.reloadButton reload
, U.chartUpdateButton { chartType: ChartPie, path, reload, session } , U.chartUpdateButton { chartType: ChartPie, path, reload, session }
...@@ -133,15 +133,15 @@ loadedPie p@{ path, reload, session } loaded = ...@@ -133,15 +133,15 @@ loadedPie p@{ path, reload, session } loaded =
bar :: Record Props -> R.Element bar :: Record Props -> R.Element
bar props = R.createElement barCpt props [] bar props = R.createElement barCpt props []
barCpt :: R.Component Props barCpt :: R.Component Props
barCpt = here.component "bar" cpt barCpt = here.component "bar" cpt
where where
cpt {path, session, onClick, onInit} _ = do cpt { errors, path, session, onClick, onInit} _ = do
reload <- T.useBox T2.newReload reload <- T.useBox T2.newReload
pure $ metricsWithCacheLoadView { pure $ metricsWithCacheLoadView {
getMetricsHash errors
, getMetricsHash
, handleResponse , handleResponse
, loaded: loadedBar , loaded: loadedBar
, mkRequest: mkRequest session , mkRequest: mkRequest session
...@@ -153,7 +153,7 @@ barCpt = here.component "bar" cpt ...@@ -153,7 +153,7 @@ barCpt = here.component "bar" cpt
} }
loadedBar :: Record MetricsProps -> Loaded -> R.Element loadedBar :: Record MetricsProps -> Loaded -> R.Element
loadedBar p@{ path, reload, session } loaded = loadedBar p loaded =
H.div {} [ H.div {} [
{- U.reloadButton reload {- U.reloadButton reload
, U.chartUpdateButton { chartType: ChartBar, path, reload, session } , U.chartUpdateButton { chartType: ChartBar, path, reload, session }
......
module Gargantext.Components.Nodes.Corpus.Chart.Predefined where module Gargantext.Components.Nodes.Corpus.Chart.Predefined where
import Data.Argonaut (class DecodeJson, class EncodeJson, decodeJson, encodeJson) import Gargantext.Prelude
import Data.Generic.Rep (class Generic) import Data.Generic.Rep (class Generic)
import Data.Maybe (Maybe(..), fromMaybe) import Data.Maybe (Maybe(..), fromMaybe)
import Data.Nullable (Nullable)
import Data.Ord.Generic (genericCompare) import Data.Ord.Generic (genericCompare)
import Data.Show.Generic (genericShow) import Data.Show.Generic (genericShow)
import Effect (Effect) import Effect (Effect)
...@@ -12,13 +12,12 @@ import Gargantext.Components.Nodes.Corpus.Chart.Histo (histo) ...@@ -12,13 +12,12 @@ import Gargantext.Components.Nodes.Corpus.Chart.Histo (histo)
import Gargantext.Components.Nodes.Corpus.Chart.Metrics (metrics) import Gargantext.Components.Nodes.Corpus.Chart.Metrics (metrics)
import Gargantext.Components.Nodes.Corpus.Chart.Pie (pie) import Gargantext.Components.Nodes.Corpus.Chart.Pie (pie)
import Gargantext.Components.Nodes.Corpus.Chart.Tree (tree) import Gargantext.Components.Nodes.Corpus.Chart.Tree (tree)
import Gargantext.Prelude
import Gargantext.Sessions (Session) import Gargantext.Sessions (Session)
import Gargantext.Types (NodeID, Mode(..), TabSubType(..), TabType(..), modeTabType) import Gargantext.Types (FrontendError, Mode(..), NodeID, TabSubType(..), TabType(..), modeTabType)
import Reactix as R import Reactix as R
import Simple.JSON as JSON import Simple.JSON as JSON
import Simple.JSON.Generics as JSONG import Simple.JSON.Generics as JSONG
import Toestand as T
data PredefinedChart = data PredefinedChart =
CDocsHistogram CDocsHistogram
...@@ -57,44 +56,50 @@ allPredefinedCharts = ...@@ -57,44 +56,50 @@ allPredefinedCharts =
type Params = type Params =
( corpusId :: NodeID ( corpusId :: NodeID
, session :: Session
-- optinal params -- optinal params
, errors :: T.Box (Array FrontendError)
, limit :: Maybe Int , limit :: Maybe Int
, listId :: Maybe Int , listId :: Maybe Int
, onClick :: Maybe (MouseEvent -> Effect Unit) , onClick :: Maybe (MouseEvent -> Effect Unit)
, onInit :: Maybe (EChartsInstance -> Effect Unit) , onInit :: Maybe (EChartsInstance -> Effect Unit)
, session :: Session
) )
render :: PredefinedChart -> Record Params -> R.Element render :: PredefinedChart -> Record Params -> R.Element
render CDocsHistogram { corpusId, listId, session, onClick, onInit } = histo { path, session, onClick, onInit } render CDocsHistogram { corpusId, errors, listId, session, onClick, onInit } =
histo { errors, path, session, onClick, onInit }
where where
path = { corpusId path = { corpusId
, listId: fromMaybe 0 listId , listId: fromMaybe 0 listId
, limit: Nothing , limit: Nothing
, tabType: TabCorpus TabDocs , tabType: TabCorpus TabDocs
} }
render CAuthorsPie { corpusId, listId, session, onClick, onInit } = pie { path, session, onClick, onInit } render CAuthorsPie { corpusId, errors, listId, session, onClick, onInit } =
pie { errors, path, session, onClick, onInit }
where where
path = { corpusId path = { corpusId
, listId: fromMaybe 0 listId , listId: fromMaybe 0 listId
, limit: Nothing , limit: Nothing
, tabType: TabCorpus (TabNgramType $ modeTabType Authors) , tabType: TabCorpus (TabNgramType $ modeTabType Authors)
} }
render CInstitutesTree { corpusId, limit, listId, session, onClick, onInit } = tree { path, session, onClick, onInit } render CInstitutesTree { corpusId, errors, limit, listId, session, onClick, onInit } =
tree { errors, path, session, onClick, onInit }
where where
path = { corpusId path = { corpusId
, limit , limit
, listId: fromMaybe 0 listId , listId: fromMaybe 0 listId
, tabType: TabCorpus (TabNgramType $ modeTabType Institutes) , tabType: TabCorpus (TabNgramType $ modeTabType Institutes)
} }
render CTermsMetrics { corpusId, limit, listId, session, onClick, onInit } = metrics { path, session, onClick, onInit } render CTermsMetrics { corpusId, errors, limit, listId, session, onClick, onInit } =
metrics { errors, path, session, onClick, onInit }
where where
path = { corpusId path = { corpusId
, limit , limit
, listId: fromMaybe 0 listId , listId: fromMaybe 0 listId
, tabType: TabCorpus (TabNgramType $ modeTabType Terms) , tabType: TabCorpus (TabNgramType $ modeTabType Terms)
} }
render CSourcesBar { corpusId, limit, listId, session, onClick, onInit } = metrics { path, session, onClick, onInit } render CSourcesBar { corpusId, errors, limit, listId, session, onClick, onInit } =
metrics { errors, path, session, onClick, onInit }
where where
path = { corpusId path = { corpusId
, limit , limit
......
...@@ -75,15 +75,15 @@ mkRequest session (_ /\ path@{ corpusId, limit, listId, tabType }) = GUC.makeGet ...@@ -75,15 +75,15 @@ mkRequest session (_ /\ path@{ corpusId, limit, listId, tabType }) = GUC.makeGet
tree :: Record Props -> R.Element tree :: Record Props -> R.Element
tree props = R.createElement treeCpt props [] tree props = R.createElement treeCpt props []
treeCpt :: R.Component Props treeCpt :: R.Component Props
treeCpt = here.component "tree" cpt treeCpt = here.component "tree" cpt
where where
cpt {path, session, onClick, onInit} _ = do cpt { errors, path, session, onClick, onInit } _ = do
reload <- T.useBox T2.newReload reload <- T.useBox T2.newReload
pure $ metricsWithCacheLoadView { pure $ metricsWithCacheLoadView {
getMetricsHash errors
, getMetricsHash
, handleResponse , handleResponse
, loaded , loaded
, mkRequest: mkRequest session , mkRequest: mkRequest session
......
...@@ -6,8 +6,9 @@ import Effect (Effect) ...@@ -6,8 +6,9 @@ import Effect (Effect)
import Gargantext.Components.Charts.Options.Type (EChartsInstance, MouseEvent) import Gargantext.Components.Charts.Options.Type (EChartsInstance, MouseEvent)
import Gargantext.Prelude (Unit) import Gargantext.Prelude (Unit)
import Gargantext.Sessions (Session) import Gargantext.Sessions (Session)
import Gargantext.Types (TabType) import Gargantext.Types (FrontendError, TabType)
import Gargantext.Utils.Toestand as T2 import Gargantext.Utils.Toestand as T2
import Toestand as T
type Path = ( type Path = (
corpusId :: Int corpusId :: Int
...@@ -17,7 +18,8 @@ type Path = ( ...@@ -17,7 +18,8 @@ type Path = (
) )
type Props = ( type Props = (
path :: Record Path errors :: T.Box (Array FrontendError)
, path :: Record Path
, session :: Session , session :: Session
, onClick :: Maybe (MouseEvent -> Effect Unit) , onClick :: Maybe (MouseEvent -> Effect Unit)
, onInit :: Maybe (EChartsInstance -> Effect Unit) , onInit :: Maybe (EChartsInstance -> Effect Unit)
......
...@@ -4,15 +4,9 @@ import Data.Array as A ...@@ -4,15 +4,9 @@ import Data.Array as A
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.List as List import Data.List as List
import Data.Maybe (Maybe(..), fromMaybe) import Data.Maybe (Maybe(..), fromMaybe)
import DOM.Simple.Console (log, log2)
import Effect (Effect) import Effect (Effect)
import Effect.Aff (launchAff_) import Effect.Aff (launchAff_)
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
import Gargantext.Components.Forest.Tree (doSearch)
import Gargantext.Components.Nodes.Corpus (fieldsCodeEditor) import Gargantext.Components.Nodes.Corpus (fieldsCodeEditor)
import Gargantext.Components.Nodes.Corpus.Chart.Predefined as P import Gargantext.Components.Nodes.Corpus.Chart.Predefined as P
import Gargantext.Components.Nodes.Dashboard.Types as DT import Gargantext.Components.Nodes.Dashboard.Types as DT
...@@ -20,21 +14,28 @@ import Gargantext.Components.Nodes.Types (FTFieldList(..), FTFieldsWithIndex(..) ...@@ -20,21 +14,28 @@ import Gargantext.Components.Nodes.Types (FTFieldList(..), FTFieldsWithIndex(..)
import Gargantext.Hooks.Loader (useLoader) import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Prelude (Unit, bind, discard, pure, read, show, unit, ($), (<$>), (<>), (==)) import Gargantext.Prelude (Unit, bind, discard, pure, read, show, unit, ($), (<$>), (<>), (==))
import Gargantext.Sessions (Session, sessionId) import Gargantext.Sessions (Session, sessionId)
import Gargantext.Types (NodeID) import Gargantext.Types (FrontendError, NodeID)
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2 import Gargantext.Utils.Toestand as T2
import Reactix as R
import Reactix.DOM.HTML as H
import Record as Record
import Toestand as T
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.Nodes.Corpus.Dashboard" here = R2.here "Gargantext.Components.Nodes.Corpus.Dashboard"
type Props = ( nodeId :: NodeID, session :: Session ) type Props =
( errors :: T.Box (Array FrontendError)
, nodeId :: NodeID
, session :: Session )
dashboardLayout :: R2.Component Props dashboardLayout :: R2.Component Props
dashboardLayout = R.createElement dashboardLayoutCpt dashboardLayout = R.createElement dashboardLayoutCpt
dashboardLayoutCpt :: R.Component Props dashboardLayoutCpt :: R.Component Props
dashboardLayoutCpt = here.component "dashboardLayout" cpt where dashboardLayoutCpt = here.component "dashboardLayout" cpt where
cpt { nodeId, session } content = do cpt props@{ nodeId, session } content = do
pure $ dashboardLayoutWithKey { key, nodeId, session } content pure $ dashboardLayoutWithKey (Record.merge props { key }) content
where where
key = show (sessionId session) <> "-" <> show nodeId key = show (sessionId session) <> "-" <> show nodeId
...@@ -48,7 +49,7 @@ dashboardLayoutWithKey = R.createElement dashboardLayoutWithKeyCpt ...@@ -48,7 +49,7 @@ dashboardLayoutWithKey = R.createElement dashboardLayoutWithKeyCpt
dashboardLayoutWithKeyCpt :: R.Component KeyProps dashboardLayoutWithKeyCpt :: R.Component KeyProps
dashboardLayoutWithKeyCpt = here.component "dashboardLayoutWithKey" cpt dashboardLayoutWithKeyCpt = here.component "dashboardLayoutWithKey" cpt
where where
cpt { nodeId, session } _ = do cpt { errors, nodeId, session } _ = do
reload <- T.useBox T2.newReload reload <- T.useBox T2.newReload
reload' <- T.useLive T.unequal reload reload' <- T.useLive T.unequal reload
...@@ -60,6 +61,7 @@ dashboardLayoutWithKeyCpt = here.component "dashboardLayoutWithKey" cpt ...@@ -60,6 +61,7 @@ dashboardLayoutWithKeyCpt = here.component "dashboardLayoutWithKey" cpt
dashboardLayoutLoaded { charts dashboardLayoutLoaded { charts
, corpusId: parentId , corpusId: parentId
, defaultListId: 0 , defaultListId: 0
, errors
, fields , fields
, nodeId , nodeId
, onChange: onChange nodeId reload (DT.Hyperdata h) , onChange: onChange nodeId reload (DT.Hyperdata h)
...@@ -75,7 +77,7 @@ dashboardLayoutWithKeyCpt = here.component "dashboardLayoutWithKey" cpt ...@@ -75,7 +77,7 @@ dashboardLayoutWithKeyCpt = here.component "dashboardLayoutWithKey" cpt
, session } , session }
liftEffect $ do liftEffect $ do
_ <- case res of _ <- case res of
Left err -> log2 "[dashboardLayoutWithKey] onChange RESTError" err Left err -> here.log2 "[dashboardLayoutWithKey] onChange RESTError" err
_ -> pure unit _ -> pure unit
T2.reload reload T2.reload reload
...@@ -83,6 +85,7 @@ type LoadedProps = ...@@ -83,6 +85,7 @@ type LoadedProps =
( charts :: Array P.PredefinedChart ( charts :: Array P.PredefinedChart
, corpusId :: NodeID , corpusId :: NodeID
, defaultListId :: Int , defaultListId :: Int
, errors :: T.Box (Array FrontendError)
, fields :: FTFieldList , fields :: FTFieldList
, onChange :: { charts :: Array P.PredefinedChart , onChange :: { charts :: Array P.PredefinedChart
, fields :: FTFieldList } -> Effect Unit , fields :: FTFieldList } -> Effect Unit
...@@ -95,7 +98,7 @@ dashboardLayoutLoaded = R.createElement dashboardLayoutLoadedCpt ...@@ -95,7 +98,7 @@ dashboardLayoutLoaded = R.createElement dashboardLayoutLoadedCpt
dashboardLayoutLoadedCpt :: R.Component LoadedProps dashboardLayoutLoadedCpt :: R.Component LoadedProps
dashboardLayoutLoadedCpt = here.component "dashboardLayoutLoaded" cpt dashboardLayoutLoadedCpt = here.component "dashboardLayoutLoaded" cpt
where where
cpt { charts, corpusId, defaultListId, fields, nodeId, onChange, session } _ = do cpt { charts, corpusId, defaultListId, errors, fields, nodeId, onChange, session } _ = do
pure $ H.div {} pure $ H.div {}
[ dashboardCodeEditor { fields [ dashboardCodeEditor { fields
, nodeId , nodeId
...@@ -119,7 +122,13 @@ dashboardLayoutLoadedCpt = here.component "dashboardLayoutLoaded" cpt ...@@ -119,7 +122,13 @@ dashboardLayoutLoadedCpt = here.component "dashboardLayoutLoaded" cpt
, fields } , fields }
chartsEls = A.mapWithIndex chartIdx charts chartsEls = A.mapWithIndex chartIdx charts
chartIdx idx chart = chartIdx idx chart =
renderChart { chart, corpusId, defaultListId, onChange: onChangeChart, onRemove, session } [] renderChart { chart
, corpusId
, defaultListId
, errors
, onChange: onChangeChart
, onRemove
, session } []
where where
onChangeChart c = do onChangeChart c = do
onChange { charts: fromMaybe charts (A.modifyAt idx (\_ -> c) charts) onChange { charts: fromMaybe charts (A.modifyAt idx (\_ -> c) charts)
...@@ -193,6 +202,7 @@ type PredefinedChartProps = ...@@ -193,6 +202,7 @@ type PredefinedChartProps =
( chart :: P.PredefinedChart ( chart :: P.PredefinedChart
, corpusId :: NodeID , corpusId :: NodeID
, defaultListId :: Int , defaultListId :: Int
, errors :: T.Box (Array FrontendError)
, onChange :: P.PredefinedChart -> Effect Unit , onChange :: P.PredefinedChart -> Effect Unit
, onRemove :: Unit -> Effect Unit , onRemove :: Unit -> Effect Unit
, session :: Session , session :: Session
...@@ -203,7 +213,7 @@ renderChart = R.createElement renderChartCpt ...@@ -203,7 +213,7 @@ renderChart = R.createElement renderChartCpt
renderChartCpt :: R.Component PredefinedChartProps renderChartCpt :: R.Component PredefinedChartProps
renderChartCpt = here.component "renderChart" cpt renderChartCpt = here.component "renderChart" cpt
where where
cpt { chart, corpusId, defaultListId, onChange, onRemove, session } _ = do cpt { chart, corpusId, defaultListId, errors, onChange, onRemove, session } _ = do
pure $ H.div { className: "row chart card" } pure $ H.div { className: "row chart card" }
[ H.div { className: "card-header" } [ H.div { className: "card-header" }
[ H.div { className: "row" } [ H.div { className: "row" }
...@@ -234,6 +244,7 @@ renderChartCpt = here.component "renderChart" cpt ...@@ -234,6 +244,7 @@ renderChartCpt = here.component "renderChart" cpt
value = R.unsafeEventValue e value = R.unsafeEventValue e
onRemoveClick _ = onRemove unit onRemoveClick _ = onRemove unit
params = { corpusId params = { corpusId
, errors
, limit: Just 1000 , limit: Just 1000
, listId: Just defaultListId , listId: Just defaultListId
, session , session
......
module Gargantext.Components.Nodes.Home where module Gargantext.Components.Nodes.Home where
import Gargantext.Prelude
import Control.Bind ((=<<))
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Data.Newtype (class Newtype) import Data.Newtype (class Newtype)
import Effect (Effect) import Effect (Effect)
...@@ -13,10 +16,10 @@ import Gargantext.Components.Nodes.Home.Public (renderPublic) ...@@ -13,10 +16,10 @@ import Gargantext.Components.Nodes.Home.Public (renderPublic)
import Gargantext.Config as Config import Gargantext.Config as Config
import Gargantext.Ends (Backend(..)) import Gargantext.Ends (Backend(..))
import Gargantext.License (license) import Gargantext.License (license)
import Gargantext.Prelude
import Gargantext.Sessions (Sessions) import Gargantext.Sessions (Sessions)
import Gargantext.Sessions as Sessions import Gargantext.Sessions as Sessions
import Gargantext.Sessions.Types (Session(..)) import Gargantext.Sessions.Types (Session(..))
import Gargantext.Types (FrontendError)
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2 import Gargantext.Utils.Toestand as T2
import Reactix as R import Reactix as R
...@@ -53,7 +56,8 @@ langLandingData LL_EN = En.landingData ...@@ -53,7 +56,8 @@ langLandingData LL_EN = En.landingData
------------------------------------------------------------------------ ------------------------------------------------------------------------
type HomeProps s l = type HomeProps s l =
( backend :: T.Box (Maybe Backend) ( backend :: T.Box (Maybe Backend)
, errors :: T.Box (Array FrontendError)
, lang :: LandingLang , lang :: LandingLang
, sessions :: s , sessions :: s
, showLogin :: l , showLogin :: l
...@@ -68,7 +72,7 @@ homeLayoutCpt :: forall s l. T.Read s Sessions => T.ReadWrite l Boolean ...@@ -68,7 +72,7 @@ homeLayoutCpt :: forall s l. T.Read s Sessions => T.ReadWrite l Boolean
=> R.Component (HomeProps s l) => R.Component (HomeProps s l)
homeLayoutCpt = here.component "homeLayout" cpt homeLayoutCpt = here.component "homeLayout" cpt
where where
cpt { backend, lang, sessions, showLogin, tasks, reloadForest} _ = do cpt { backend, errors, lang, sessions, showLogin, tasks, reloadForest} _ = do
backend' <- T.useLive T.unequal backend backend' <- T.useLive T.unequal backend
sessions' <- T.useLive T.unequal sessions sessions' <- T.useLive T.unequal sessions
let landingData = langLandingData lang let landingData = langLandingData lang
...@@ -77,7 +81,7 @@ homeLayoutCpt = here.component "homeLayout" cpt ...@@ -77,7 +81,7 @@ homeLayoutCpt = here.component "homeLayout" cpt
[ H.div { className: "home-title container1" } [ H.div { className: "home-title container1" }
[ jumboTitle landingData ] [ jumboTitle landingData ]
, H.div { className: "home-research-form container1" } [] -- TODO , H.div { className: "home-research-form container1" } [] -- TODO
, joinButtonOrTutorial tasks reloadForest sessions' (click backend') , joinButtonOrTutorial errors tasks reloadForest sessions' (click backend')
, H.div { className: "home-public container1" } , H.div { className: "home-public container1" }
[ renderPublic { } [ renderPublic { }
, H.div { className:"col-12 d-flex justify-content-center" } , H.div { className:"col-12 d-flex justify-content-center" }
...@@ -98,11 +102,16 @@ homeLayoutCpt = here.component "homeLayout" cpt ...@@ -98,11 +102,16 @@ homeLayoutCpt = here.component "homeLayout" cpt
T.write_ true showLogin T.write_ true showLogin
Just _ -> T.write_ true showLogin Just _ -> T.write_ true showLogin
joinButtonOrTutorial :: forall e. T.Box GAT.Storage -> T2.ReloadS -> Sessions -> (e -> Effect Unit) -> R.Element joinButtonOrTutorial :: forall e. T.Box (Array FrontendError)
joinButtonOrTutorial tasks reloadForest sessions click = -> T.Box GAT.Storage
-> T2.ReloadS
-> Sessions
-> (e -> Effect Unit)
-> R.Element
joinButtonOrTutorial errors tasks reloadForest sessions click =
if Sessions.null sessions if Sessions.null sessions
then joinButton click then joinButton click
else tutorial {tasks, reloadForest, sessions: Sessions.unSessions sessions} else tutorial { errors, tasks, reloadForest, sessions: Sessions.unSessions sessions }
joinButton :: forall e. (e -> Effect Unit) -> R.Element joinButton :: forall e. (e -> Effect Unit) -> R.Element
joinButton click = joinButton click =
...@@ -148,11 +157,17 @@ summary = ...@@ -148,11 +157,17 @@ summary =
, H.ol {} (map toSummary tutos) ] ] , H.ol {} (map toSummary tutos) ] ]
toSummary (Tuto x) = H.li {} [ H.a {href: "#" <> x.id} [ H.text x.title ]] toSummary (Tuto x) = H.li {} [ H.a {href: "#" <> x.id} [ H.text x.title ]]
tutorial :: R2.Leaf (sessions :: Array Session, tasks :: T.Box GAT.Storage, reloadForest :: T.Box T2.Reload) type TutorialProps =
( errors :: T.Box (Array FrontendError)
, sessions :: Array Session
, tasks :: T.Box GAT.Storage
, reloadForest :: T.Box T2.Reload )
tutorial :: R2.Leaf TutorialProps
tutorial props = R.createElement tutorialCpt props [] tutorial props = R.createElement tutorialCpt props []
tutorialCpt :: R.Component (sessions :: Array Session, tasks :: T.Box GAT.Storage, reloadForest :: T.Box T2.Reload) tutorialCpt :: R.Component TutorialProps
tutorialCpt = here.component "tutorial" cpt where tutorialCpt = here.component "tutorial" cpt where
cpt {sessions, tasks, reloadForest} _ = do cpt { errors, sessions, tasks, reloadForest } _ = do
let folders = makeFolders sessions let folders = makeFolders sessions
pure $ H.div { className: "mx-auto container" } pure $ H.div { className: "mx-auto container" }
...@@ -178,7 +193,7 @@ tutorialCpt = here.component "tutorial" cpt where ...@@ -178,7 +193,7 @@ tutorialCpt = here.component "tutorial" cpt where
sessionToFolder session@(Session {treeId, username, backend: (Backend {name})}) = sessionToFolder session@(Session {treeId, username, backend: (Backend {name})}) =
H.span { className: "folder" } [ H.span { className: "folder" } [
H.div { className: "d-flex justify-content-center" } [ H.text (username <> "@" <> name) ] H.div { className: "d-flex justify-content-center" } [ H.text (username <> "@" <> name) ]
, H.div {} [ FV.folderView {session, tasks, reloadForest, nodeId: treeId, backFolder: false} ] ] , H.div {} [ FV.folderView { errors, session, tasks, reloadForest, nodeId: treeId, backFolder: false} ] ]
startTutos :: Array Tuto startTutos :: Array Tuto
startTutos = startTutos =
......
module Gargantext.Components.Nodes.Lists where module Gargantext.Components.Nodes.Lists where
import Gargantext.Prelude
import Data.Maybe (Maybe) import Data.Maybe (Maybe)
import Effect (Effect) import Effect (Effect)
import Effect.Aff (launchAff_) import Effect.Aff (launchAff_)
import Reactix as R
import Reactix.DOM.HTML as H
import Record as Record
import Toestand as T
import Gargantext.AsyncTasks as GAT import Gargantext.AsyncTasks as GAT
import Gargantext.Components.NgramsTable.Loader (clearCache) import Gargantext.Components.NgramsTable.Loader (clearCache)
import Gargantext.Components.Node (NodePoly(..)) import Gargantext.Components.Node (NodePoly(..))
...@@ -17,18 +14,23 @@ import Gargantext.Components.Nodes.Lists.Tabs as Tabs ...@@ -17,18 +14,23 @@ import Gargantext.Components.Nodes.Lists.Tabs as Tabs
import Gargantext.Components.Nodes.Lists.Types (CacheState(..), SidePanel) import Gargantext.Components.Nodes.Lists.Types (CacheState(..), SidePanel)
import Gargantext.Components.Table as Table import Gargantext.Components.Table as Table
import Gargantext.Hooks.Loader (useLoader) import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Prelude
import Gargantext.Sessions (WithSession, WithSessionContext, Session, sessionId, getCacheState, setCacheState) import Gargantext.Sessions (WithSession, WithSessionContext, Session, sessionId, getCacheState, setCacheState)
import Gargantext.Types (FrontendError)
import Gargantext.Types as GT import Gargantext.Types as GT
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2 import Gargantext.Utils.Toestand as T2
import Reactix as R
import Reactix.DOM.HTML as H
import Record as Record
import Toestand as T
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.Nodes.Lists" here = R2.here "Gargantext.Components.Nodes.Lists"
-------------------------------------------------------- --------------------------------------------------------
type CommonPropsNoSession = type CommonPropsNoSession =
( nodeId :: Int ( errors :: T.Box (Array FrontendError)
, nodeId :: Int
, reloadForest :: T2.ReloadS , reloadForest :: T2.ReloadS
, reloadMainPage :: T2.ReloadS , reloadMainPage :: T2.ReloadS
, reloadRoot :: T2.ReloadS , reloadRoot :: T2.ReloadS
...@@ -59,7 +61,8 @@ listsLayoutWithKey :: R2.Component KeyProps ...@@ -59,7 +61,8 @@ listsLayoutWithKey :: R2.Component KeyProps
listsLayoutWithKey = R.createElement listsLayoutWithKeyCpt listsLayoutWithKey = R.createElement listsLayoutWithKeyCpt
listsLayoutWithKeyCpt :: R.Component KeyProps listsLayoutWithKeyCpt :: R.Component KeyProps
listsLayoutWithKeyCpt = here.component "listsLayoutWithKey" cpt where listsLayoutWithKeyCpt = here.component "listsLayoutWithKey" cpt where
cpt { nodeId cpt { errors
, nodeId
, reloadForest , reloadForest
, reloadMainPage , reloadMainPage
, reloadRoot , reloadRoot
...@@ -98,6 +101,7 @@ listsLayoutWithKeyCpt = here.component "listsLayoutWithKey" cpt where ...@@ -98,6 +101,7 @@ listsLayoutWithKeyCpt = here.component "listsLayoutWithKey" cpt where
, cacheState , cacheState
, corpusData , corpusData
, corpusId , corpusId
, errors
, key: "listsLayoutWithKey-tabs-" <> (show cacheState') , key: "listsLayoutWithKey-tabs-" <> (show cacheState')
, reloadForest , reloadForest
, reloadRoot , reloadRoot
......
module Gargantext.Components.Nodes.Lists.Tabs where module Gargantext.Components.Nodes.Lists.Tabs where
import Gargantext.Components.Nodes.Lists.Types
import Data.Array as A import Data.Array as A
import Data.Maybe (Maybe(..), fromMaybe) import Data.Maybe (Maybe(..), fromMaybe)
import Data.Tuple (fst)
import Data.Tuple.Nested ((/\)) import Data.Tuple.Nested ((/\))
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import Gargantext.AsyncTasks as GAT import Gargantext.AsyncTasks as GAT
...@@ -15,11 +12,11 @@ import Gargantext.Components.Nodes.Corpus.Chart.Pie (pie, bar) ...@@ -15,11 +12,11 @@ import Gargantext.Components.Nodes.Corpus.Chart.Pie (pie, bar)
import Gargantext.Components.Nodes.Corpus.Chart.Tree (tree) import Gargantext.Components.Nodes.Corpus.Chart.Tree (tree)
import Gargantext.Components.Nodes.Corpus.Chart.Utils (mNgramsTypeFromTabType) import Gargantext.Components.Nodes.Corpus.Chart.Utils (mNgramsTypeFromTabType)
import Gargantext.Components.Nodes.Corpus.Types (CorpusData) import Gargantext.Components.Nodes.Corpus.Types (CorpusData)
import Gargantext.Components.Search as S import Gargantext.Components.Nodes.Lists.Types
import Gargantext.Components.Tab as Tab import Gargantext.Components.Tab as Tab
import Gargantext.Prelude (bind, pure, unit, ($), (<>)) import Gargantext.Prelude (bind, pure, unit, ($), (<>))
import Gargantext.Sessions (Session) import Gargantext.Sessions (Session)
import Gargantext.Types (ChartType(..), CTabNgramType(..), Mode(..), TabSubType(..), TabType(..), modeTabType) import Gargantext.Types (CTabNgramType(..), FrontendError, Mode(..), TabSubType(..), TabType(..), modeTabType)
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2 import Gargantext.Utils.Toestand as T2
import Reactix as R import Reactix as R
...@@ -36,6 +33,7 @@ type Props = ( ...@@ -36,6 +33,7 @@ type Props = (
, cacheState :: T.Box CacheState , cacheState :: T.Box CacheState
, corpusData :: CorpusData , corpusData :: CorpusData
, corpusId :: Int , corpusId :: Int
, errors :: T.Box (Array FrontendError)
, reloadForest :: T2.ReloadS , reloadForest :: T2.ReloadS
, reloadRoot :: T2.ReloadS , reloadRoot :: T2.ReloadS
, session :: Session , session :: Session
...@@ -64,12 +62,12 @@ type NgramsViewProps = ( mode :: Mode | Props ) ...@@ -64,12 +62,12 @@ type NgramsViewProps = ( mode :: Mode | Props )
ngramsView :: R2.Component NgramsViewProps ngramsView :: R2.Component NgramsViewProps
ngramsView = R.createElement ngramsViewCpt ngramsView = R.createElement ngramsViewCpt
ngramsViewCpt :: R.Component NgramsViewProps ngramsViewCpt :: R.Component NgramsViewProps
ngramsViewCpt = here.component "ngramsView" cpt where ngramsViewCpt = here.component "ngramsView" cpt where
cpt props@{ cacheState cpt props@{ cacheState
, corpusData: { defaultListId } , corpusData: { defaultListId }
, corpusId , corpusId
, errors
, reloadForest , reloadForest
, reloadRoot , reloadRoot
, mode , mode
...@@ -161,7 +159,7 @@ ngramsViewCpt = here.component "ngramsView" cpt where ...@@ -161,7 +159,7 @@ ngramsViewCpt = here.component "ngramsView" cpt where
] ]
charts params _ = [ chart params mode ] charts params _ = [ chart params mode ]
chart path Authors = pie { path, session, onClick: Nothing, onInit: Nothing } chart path Authors = pie { errors, path, session, onClick: Nothing, onInit: Nothing }
chart path Institutes = tree { path, session, onClick: Nothing, onInit: Nothing } chart path Institutes = tree { errors, path, session, onClick: Nothing, onInit: Nothing }
chart path Sources = bar { path, session, onClick: Nothing, onInit: Nothing } chart path Sources = bar { errors, path, session, onClick: Nothing, onInit: Nothing }
chart path Terms = metrics { path, session, onClick: Nothing, onInit: Nothing } chart path Terms = metrics { errors, path, session, onClick: Nothing, onInit: Nothing }
...@@ -7,10 +7,6 @@ import Data.Maybe (Maybe(..)) ...@@ -7,10 +7,6 @@ import Data.Maybe (Maybe(..))
import Data.Show.Generic (genericShow) import Data.Show.Generic (genericShow)
import Data.Tuple.Nested ((/\)) import Data.Tuple.Nested ((/\))
import Effect.Aff (launchAff_) import Effect.Aff (launchAff_)
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
import Gargantext.Components.Charts.Options.ECharts (dispatchAction) import Gargantext.Components.Charts.Options.ECharts (dispatchAction)
import Gargantext.Components.Charts.Options.Type (EChartsInstance, EChartActionData) import Gargantext.Components.Charts.Options.Type (EChartsInstance, EChartActionData)
import Gargantext.Components.DocsTable as DT import Gargantext.Components.DocsTable as DT
...@@ -28,8 +24,11 @@ import Gargantext.Components.Table as Table ...@@ -28,8 +24,11 @@ import Gargantext.Components.Table as Table
import Gargantext.Ends (Frontends) import Gargantext.Ends (Frontends)
import Gargantext.Hooks.Loader (useLoader) import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Sessions (WithSession, Session, getCacheState) import Gargantext.Sessions (WithSession, Session, getCacheState)
import Gargantext.Types (CTabNgramType(..), ListId, NodeID, SidePanelState(..), TabSubType(..), TabType(..)) import Gargantext.Types (CTabNgramType(..), FrontendError, ListId, NodeID, SidePanelState(..), TabSubType(..), TabType(..))
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.Nodes.Texts" here = R2.here "Gargantext.Components.Nodes.Texts"
...@@ -37,8 +36,9 @@ here = R2.here "Gargantext.Components.Nodes.Texts" ...@@ -37,8 +36,9 @@ here = R2.here "Gargantext.Components.Nodes.Texts"
-------------------------------------------------------- --------------------------------------------------------
type CommonPropsNoSession = ( type CommonPropsNoSession =
frontends :: Frontends ( errors :: T.Box (Array FrontendError)
, frontends :: Frontends
, nodeId :: NodeID , nodeId :: NodeID
, sidePanel :: T.Box (Maybe (Record TT.SidePanel)) , sidePanel :: T.Box (Maybe (Record TT.SidePanel))
, sidePanelState :: T.Box SidePanelState , sidePanelState :: T.Box SidePanelState
...@@ -49,12 +49,12 @@ type Props = WithSession CommonPropsNoSession ...@@ -49,12 +49,12 @@ type Props = WithSession CommonPropsNoSession
textsLayout :: R2.Component Props textsLayout :: R2.Component Props
textsLayout = R.createElement textsLayoutCpt textsLayout = R.createElement textsLayoutCpt
textsLayoutCpt :: R.Component Props textsLayoutCpt :: R.Component Props
textsLayoutCpt = here.component "textsLayout" cpt where textsLayoutCpt = here.component "textsLayout" cpt where
cpt { frontends, nodeId, session, sidePanel, sidePanelState } children = do cpt { errors, frontends, nodeId, session, sidePanel, sidePanelState } children = do
pure $ textsLayoutWithKey { frontends pure $ textsLayoutWithKey { key
, key , errors
, frontends
, nodeId , nodeId
, session , session
, sidePanel , sidePanel
...@@ -67,6 +67,7 @@ textsLayoutCpt = here.component "textsLayout" cpt where ...@@ -67,6 +67,7 @@ textsLayoutCpt = here.component "textsLayout" cpt where
type KeyProps = ( type KeyProps = (
key :: String key :: String
, errors :: T.Box (Array FrontendError)
, frontends :: Frontends , frontends :: Frontends
, nodeId :: NodeID , nodeId :: NodeID
, session :: Session , session :: Session
...@@ -79,7 +80,12 @@ textsLayoutWithKey = R.createElement textsLayoutWithKeyCpt ...@@ -79,7 +80,12 @@ textsLayoutWithKey = R.createElement textsLayoutWithKeyCpt
textsLayoutWithKeyCpt :: R.Component KeyProps textsLayoutWithKeyCpt :: R.Component KeyProps
textsLayoutWithKeyCpt = here.component "textsLayoutWithKey" cpt textsLayoutWithKeyCpt = here.component "textsLayoutWithKey" cpt
where where
cpt { frontends, nodeId, session, sidePanel, sidePanelState } _children = do cpt { errors
, frontends
, nodeId
, session
, sidePanel
, sidePanelState } _children = do
cacheState <- T.useBox $ getCacheState LT.CacheOff session nodeId cacheState <- T.useBox $ getCacheState LT.CacheOff session nodeId
cacheState' <- T.useLive T.unequal cacheState cacheState' <- T.useLive T.unequal cacheState
...@@ -109,6 +115,7 @@ textsLayoutWithKeyCpt = here.component "textsLayoutWithKey" cpt ...@@ -109,6 +115,7 @@ textsLayoutWithKeyCpt = here.component "textsLayoutWithKey" cpt
, tabs { cacheState , tabs { cacheState
, corpusData , corpusData
, corpusId , corpusId
, errors
, frontends , frontends
, session , session
, sidePanel , sidePanel
...@@ -143,6 +150,7 @@ type TabsProps = ...@@ -143,6 +150,7 @@ type TabsProps =
, corpusData :: CorpusData , corpusData :: CorpusData
, corpusId :: NodeID , corpusId :: NodeID
, eChartsInstance :: T.Box (Maybe EChartsInstance) , eChartsInstance :: T.Box (Maybe EChartsInstance)
, errors :: T.Box (Array FrontendError)
, frontends :: Frontends , frontends :: Frontends
, session :: Session , session :: Session
, sidePanel :: T.Box (Maybe (Record TT.SidePanel)) , sidePanel :: T.Box (Maybe (Record TT.SidePanel))
...@@ -159,6 +167,7 @@ tabsCpt = here.component "tabs" cpt ...@@ -159,6 +167,7 @@ tabsCpt = here.component "tabs" cpt
, corpusId , corpusId
, corpusData , corpusData
, eChartsInstance , eChartsInstance
, errors
, frontends , frontends
, session , session
, sidePanel , sidePanel
...@@ -197,7 +206,7 @@ tabsCpt = here.component "tabs" cpt ...@@ -197,7 +206,7 @@ tabsCpt = here.component "tabs" cpt
activeTab activeTab
, tabs: [ , tabs: [
"Documents" /\ R.fragment [ "Documents" /\ R.fragment [
histo { path, session, onClick, onInit } histo { errors, path, session, onClick, onInit }
, docView' path TabDocs , docView' path TabDocs
] ]
, "Trash" /\ docView' path TabTrash , "Trash" /\ docView' path TabTrash
...@@ -214,6 +223,7 @@ tabsCpt = here.component "tabs" cpt ...@@ -214,6 +223,7 @@ tabsCpt = here.component "tabs" cpt
docView' path tabType = docView { cacheState docView' path tabType = docView { cacheState
, corpusData , corpusData
, corpusId , corpusId
, errors
, frontends , frontends
, listId: path.listId , listId: path.listId
-- , path -- , path
...@@ -228,6 +238,7 @@ type DocViewProps a = ( ...@@ -228,6 +238,7 @@ type DocViewProps a = (
cacheState :: T.Box LT.CacheState cacheState :: T.Box LT.CacheState
, corpusData :: CorpusData , corpusData :: CorpusData
, corpusId :: NodeID , corpusId :: NodeID
, errors :: T.Box (Array FrontendError)
, frontends :: Frontends , frontends :: Frontends
, listId :: ListId , listId :: ListId
-- , path :: Record DT.Path -- , path :: Record DT.Path
...@@ -240,7 +251,6 @@ type DocViewProps a = ( ...@@ -240,7 +251,6 @@ type DocViewProps a = (
docView :: forall a. R2.Component (DocViewProps a) docView :: forall a. R2.Component (DocViewProps a)
docView = R.createElement docViewCpt docView = R.createElement docViewCpt
docViewCpt :: forall a. R.Component (DocViewProps a) docViewCpt :: forall a. R.Component (DocViewProps a)
docViewCpt = here.component "docView" cpt docViewCpt = here.component "docView" cpt
where where
...@@ -250,6 +260,7 @@ docViewCpt = here.component "docView" cpt ...@@ -250,6 +260,7 @@ docViewCpt = here.component "docView" cpt
-- docViewLayoutRec :: forall a. DocViewProps a -> Record DT.LayoutProps -- docViewLayoutRec :: forall a. DocViewProps a -> Record DT.LayoutProps
docViewLayoutRec { cacheState docViewLayoutRec { cacheState
, corpusId , corpusId
, errors
, frontends , frontends
, listId , listId
, session , session
...@@ -260,6 +271,7 @@ docViewLayoutRec { cacheState ...@@ -260,6 +271,7 @@ docViewLayoutRec { cacheState
} = } =
{ cacheState { cacheState
, chart : H.div {} [] , chart : H.div {} []
, errors
, frontends , frontends
, listId , listId
, mCorpusId: Just corpusId , mCorpusId: Just corpusId
...@@ -275,6 +287,7 @@ docViewLayoutRec { cacheState ...@@ -275,6 +287,7 @@ docViewLayoutRec { cacheState
} }
docViewLayoutRec { cacheState docViewLayoutRec { cacheState
, corpusId , corpusId
, errors
, frontends , frontends
, listId , listId
, session , session
...@@ -285,6 +298,7 @@ docViewLayoutRec { cacheState ...@@ -285,6 +298,7 @@ docViewLayoutRec { cacheState
} = } =
{ cacheState { cacheState
, chart : H.div {} [] , chart : H.div {} []
, errors
, frontends , frontends
, listId , listId
, mCorpusId: Just corpusId , mCorpusId: Just corpusId
...@@ -300,6 +314,7 @@ docViewLayoutRec { cacheState ...@@ -300,6 +314,7 @@ docViewLayoutRec { cacheState
} }
docViewLayoutRec { cacheState docViewLayoutRec { cacheState
, corpusId , corpusId
, errors
, frontends , frontends
, listId , listId
, session , session
...@@ -310,6 +325,7 @@ docViewLayoutRec { cacheState ...@@ -310,6 +325,7 @@ docViewLayoutRec { cacheState
} = } =
{ cacheState { cacheState
, chart : H.div {} [] , chart : H.div {} []
, errors
, frontends , frontends
, listId , listId
, mCorpusId: Just corpusId , mCorpusId: Just corpusId
...@@ -325,6 +341,7 @@ docViewLayoutRec { cacheState ...@@ -325,6 +341,7 @@ docViewLayoutRec { cacheState
} }
docViewLayoutRec { cacheState docViewLayoutRec { cacheState
, corpusId , corpusId
, errors
, frontends , frontends
, listId , listId
, session , session
...@@ -335,6 +352,7 @@ docViewLayoutRec { cacheState ...@@ -335,6 +352,7 @@ docViewLayoutRec { cacheState
} = } =
{ cacheState { cacheState
, chart : H.div {} [] , chart : H.div {} []
, errors
, frontends , frontends
, listId , listId
, mCorpusId: Just corpusId , mCorpusId: Just corpusId
...@@ -351,6 +369,7 @@ docViewLayoutRec { cacheState ...@@ -351,6 +369,7 @@ docViewLayoutRec { cacheState
-- DUMMY -- DUMMY
docViewLayoutRec { cacheState docViewLayoutRec { cacheState
, corpusId , corpusId
, errors
, frontends , frontends
, listId , listId
, session , session
...@@ -361,6 +380,7 @@ docViewLayoutRec { cacheState ...@@ -361,6 +380,7 @@ docViewLayoutRec { cacheState
} = } =
{ cacheState { cacheState
, chart : H.div {} [] , chart : H.div {} []
, errors
, frontends , frontends
, listId , listId
, mCorpusId: Just corpusId , mCorpusId: Just corpusId
......
...@@ -5,12 +5,6 @@ import Gargantext.Prelude ...@@ -5,12 +5,6 @@ import Gargantext.Prelude
import Data.Array as A import Data.Array as A
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Data.Tuple.Nested ((/\)) import Data.Tuple.Nested ((/\))
import Reactix as R
import Reactix.DOM.HTML as H
import Record as Record
import Record.Extra as RE
import Toestand as T
import Gargantext.Components.App.Data (Boxes) import Gargantext.Components.App.Data (Boxes)
import Gargantext.Components.ErrorsView (errorsView) import Gargantext.Components.ErrorsView (errorsView)
import Gargantext.Components.Footer (footer) import Gargantext.Components.Footer (footer)
...@@ -43,6 +37,11 @@ import Gargantext.Sessions (Session, WithSession) ...@@ -43,6 +37,11 @@ import Gargantext.Sessions (Session, WithSession)
import Gargantext.Sessions as Sessions import Gargantext.Sessions as Sessions
import Gargantext.Types (CorpusId, Handed(..), ListId, NodeID, NodeType(..), SessionId, SidePanelState(..), reverseHanded) import Gargantext.Types (CorpusId, Handed(..), ListId, NodeID, NodeType(..), SessionId, SidePanelState(..), reverseHanded)
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
import Record as Record
import Record.Extra as RE
import Toestand as T
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.Router" here = R2.here "Gargantext.Components.Router"
...@@ -114,6 +113,7 @@ forest p = R.createElement forestCpt p [] ...@@ -114,6 +113,7 @@ forest p = R.createElement forestCpt p []
forestCpt :: R.Component Props forestCpt :: R.Component Props
forestCpt = here.component "forest" cpt where forestCpt = here.component "forest" cpt where
cpt { boxes: { backend cpt { boxes: { backend
, errors
, forestOpen , forestOpen
, handed , handed
, reloadForest , reloadForest
...@@ -133,6 +133,7 @@ forestCpt = here.component "forest" cpt where ...@@ -133,6 +133,7 @@ forestCpt = here.component "forest" cpt where
then mempty then mempty
else Forest.forestLayout else Forest.forestLayout
{ backend { backend
, errors
, forestOpen , forestOpen
, frontends: defaultFrontends , frontends: defaultFrontends
, handed , handed
...@@ -284,7 +285,11 @@ corpusCpt = here.component "corpus" cpt where ...@@ -284,7 +285,11 @@ corpusCpt = here.component "corpus" cpt where
cpt props@{ boxes, nodeId } _ = do cpt props@{ boxes, nodeId } _ = do
let sessionProps = RE.pick props :: Record SessionProps let sessionProps = RE.pick props :: Record SessionProps
pure $ authed (Record.merge { content: \session -> pure $ authed (Record.merge { content: \session ->
corpusLayout { nodeId, session, tasks: boxes.tasks, reloadForest: boxes.reloadForest } } sessionProps) [] corpusLayout { errors: boxes.errors
, nodeId
, session
, tasks: boxes.tasks
, reloadForest: boxes.reloadForest } } sessionProps) []
type CorpusDocumentProps = type CorpusDocumentProps =
( corpusId :: CorpusId ( corpusId :: CorpusId
...@@ -310,10 +315,10 @@ dashboard = R.createElement dashboardCpt ...@@ -310,10 +315,10 @@ dashboard = R.createElement dashboardCpt
dashboardCpt :: R.Component SessionNodeProps dashboardCpt :: R.Component SessionNodeProps
dashboardCpt = here.component "dashboard" cpt dashboardCpt = here.component "dashboard" cpt
where where
cpt props@{ nodeId } _ = do cpt props@{ boxes: { errors }, nodeId } _ = do
let sessionProps = RE.pick props :: Record SessionProps let sessionProps = RE.pick props :: Record SessionProps
pure $ authed (Record.merge { content: \session -> pure $ authed (Record.merge { content: \session ->
dashboardLayout { nodeId, session } [] } sessionProps) [] dashboardLayout { errors, nodeId, session } [] } sessionProps) []
type DocumentProps = ( listId :: ListId | SessionNodeProps ) type DocumentProps = ( listId :: ListId | SessionNodeProps )
...@@ -356,14 +361,15 @@ home :: R2.Component Props ...@@ -356,14 +361,15 @@ home :: R2.Component Props
home = R.createElement homeCpt home = R.createElement homeCpt
homeCpt :: R.Component Props homeCpt :: R.Component Props
homeCpt = here.component "home" cpt where homeCpt = here.component "home" cpt where
cpt { boxes: { backend, sessions, showLogin, tasks, reloadForest} } _ = do cpt { boxes: { backend, errors, sessions, showLogin, tasks, reloadForest} } _ = do
pure $ homeLayout { backend, lang: LL_EN, sessions, showLogin, tasks, reloadForest } pure $ homeLayout { backend, errors, lang: LL_EN, sessions, showLogin, tasks, reloadForest }
lists :: R2.Component SessionNodeProps lists :: R2.Component SessionNodeProps
lists = R.createElement listsCpt lists = R.createElement listsCpt
listsCpt :: R.Component SessionNodeProps listsCpt :: R.Component SessionNodeProps
listsCpt = here.component "lists" cpt where listsCpt = here.component "lists" cpt where
cpt props@{ boxes: { reloadForest cpt props@{ boxes: { errors
, reloadForest
, reloadMainPage , reloadMainPage
, reloadRoot , reloadRoot
, sidePanelState , sidePanelState
...@@ -372,7 +378,8 @@ listsCpt = here.component "lists" cpt where ...@@ -372,7 +378,8 @@ listsCpt = here.component "lists" cpt where
, nodeId } _ = do , nodeId } _ = do
let sessionProps = RE.pick props :: Record SessionProps let sessionProps = RE.pick props :: Record SessionProps
pure $ authed (Record.merge { content: \session -> pure $ authed (Record.merge { content: \session ->
Lists.listsLayout { nodeId Lists.listsLayout { errors
, nodeId
, reloadForest , reloadForest
, reloadMainPage , reloadMainPage
, reloadRoot , reloadRoot
...@@ -420,22 +427,25 @@ teamCpt = here.component "team" cpt where ...@@ -420,22 +427,25 @@ teamCpt = here.component "team" cpt where
cpt props@{ boxes, nodeId } _ = do cpt props@{ boxes, nodeId } _ = do
let sessionProps = RE.pick props :: Record SessionProps let sessionProps = RE.pick props :: Record SessionProps
pure $ authed (Record.merge { content: \session -> pure $ authed (Record.merge { content: \session ->
corpusLayout { nodeId corpusLayout { errors: boxes.errors
, nodeId
, reloadForest: boxes.reloadForest
, session , session
, tasks: boxes.tasks , tasks: boxes.tasks } } sessionProps) []
, reloadForest: boxes.reloadForest } } sessionProps) []
texts :: R2.Component SessionNodeProps texts :: R2.Component SessionNodeProps
texts = R.createElement textsCpt texts = R.createElement textsCpt
textsCpt :: R.Component SessionNodeProps textsCpt :: R.Component SessionNodeProps
textsCpt = here.component "texts" cpt textsCpt = here.component "texts" cpt
where where
cpt props@{ boxes: { sidePanelState cpt props@{ boxes: { errors
, sidePanelState
, sidePanelTexts } , sidePanelTexts }
, nodeId } _ = do , nodeId } _ = do
let sessionProps = RE.pick props :: Record SessionProps let sessionProps = RE.pick props :: Record SessionProps
pure $ authed (Record.merge { content: \session -> pure $ authed (Record.merge { content: \session ->
Texts.textsLayout { frontends: defaultFrontends Texts.textsLayout { errors
, frontends: defaultFrontends
, nodeId , nodeId
, session , session
, sidePanel: sidePanelTexts , sidePanel: sidePanelTexts
...@@ -445,7 +455,8 @@ user :: R2.Component SessionNodeProps ...@@ -445,7 +455,8 @@ user :: R2.Component SessionNodeProps
user = R.createElement userCpt user = R.createElement userCpt
userCpt :: R.Component SessionNodeProps userCpt :: R.Component SessionNodeProps
userCpt = here.component "user" cpt where userCpt = here.component "user" cpt where
cpt props@{ boxes: { reloadForest cpt props@{ boxes: { errors
, reloadForest
, reloadRoot , reloadRoot
, sidePanelState , sidePanelState
, sidePanelTexts , sidePanelTexts
...@@ -453,7 +464,8 @@ userCpt = here.component "user" cpt where ...@@ -453,7 +464,8 @@ userCpt = here.component "user" cpt where
, nodeId } _ = do , nodeId } _ = do
let sessionProps = RE.pick props :: Record SessionProps let sessionProps = RE.pick props :: Record SessionProps
pure $ authed (Record.merge { content: \session -> pure $ authed (Record.merge { content: \session ->
userLayout { frontends: defaultFrontends userLayout { errors
, frontends: defaultFrontends
, nodeId , nodeId
, reloadForest , reloadForest
, reloadRoot , reloadRoot
...@@ -469,7 +481,8 @@ contact = R.createElement contactCpt ...@@ -469,7 +481,8 @@ contact = R.createElement contactCpt
contactCpt :: R.Component ContactProps contactCpt :: R.Component ContactProps
contactCpt = here.component "contact" cpt where contactCpt = here.component "contact" cpt where
cpt props@{ annuaireId cpt props@{ annuaireId
, boxes: { reloadForest , boxes: { errors
, reloadForest
, reloadRoot , reloadRoot
, sidePanelTexts , sidePanelTexts
, sidePanelState , sidePanelState
...@@ -479,6 +492,7 @@ contactCpt = here.component "contact" cpt where ...@@ -479,6 +492,7 @@ contactCpt = here.component "contact" cpt where
-- let forestedProps = RE.pick props :: Record Props -- let forestedProps = RE.pick props :: Record Props
pure $ authed (Record.merge { content: \session -> pure $ authed (Record.merge { content: \session ->
contactLayout { annuaireId contactLayout { annuaireId
, errors
, frontends: defaultFrontends , frontends: defaultFrontends
, nodeId , nodeId
, reloadForest , reloadForest
......
...@@ -2,12 +2,11 @@ module Gargantext.Config.REST where ...@@ -2,12 +2,11 @@ module Gargantext.Config.REST where
import Gargantext.Prelude import Gargantext.Prelude
import Affjax (defaultRequest, request) import Affjax (Error(..), defaultRequest, request)
import Affjax as Affjax import Affjax as Affjax
import Affjax.RequestBody (formData, formURLEncoded, string) import Affjax.RequestBody (formData, formURLEncoded, string)
import Affjax.RequestHeader as ARH import Affjax.RequestHeader as ARH
import Affjax.ResponseFormat as ResponseFormat import Affjax.ResponseFormat as ResponseFormat
import DOM.Simple.Console (log2)
import Data.Argonaut.Core as AC import Data.Argonaut.Core as AC
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.Foldable (foldMap) import Data.Foldable (foldMap)
...@@ -20,11 +19,10 @@ import Data.Tuple (Tuple) ...@@ -20,11 +19,10 @@ import Data.Tuple (Tuple)
import Effect.Aff (Aff) import Effect.Aff (Aff)
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import Foreign as Foreign import Foreign as Foreign
import Gargantext.Utils.Reactix as R2
import Simple.JSON as JSON import Simple.JSON as JSON
import Web.XHR.FormData as XHRFormData import Web.XHR.FormData as XHRFormData
import Gargantext.Utils.Reactix as R2
type Token = String type Token = String
data RESTError = data RESTError =
...@@ -32,10 +30,20 @@ data RESTError = ...@@ -32,10 +30,20 @@ data RESTError =
| ReadJSONError Foreign.MultipleErrors | ReadJSONError Foreign.MultipleErrors
derive instance Generic RESTError _ derive instance Generic RESTError _
instance Show RESTError where
show (SendResponseError e) = "SendResponseError " <> showError e
where
showError (RequestContentError e') = "(RequestContentError " <> show e' <> ")"
showError (ResponseBodyError fe rf) = "(ResponseBodyError " <> show fe <> " (rf)" -- <> show rf <> ")"
showError (TimeoutError) = "(TimeoutError)"
showError (RequestFailedError) = "(RequestFailedError)"
showError (XHROtherError e') = "(XHROtherError " <> show e' <> ")"
show (ReadJSONError e) = "ReadJSONError " <> show e
instance Eq RESTError where instance Eq RESTError where
-- this is crude but we need it only because of useLoader -- this is crude but we need it only because of useLoader
eq _ _ = false eq _ _ = false
readJSON :: forall a b. JSON.ReadForeign a => readJSON :: forall a b. JSON.ReadForeign a =>
Either Affjax.Error Either Affjax.Error
{ body :: AC.Json { body :: AC.Json
......
module Gargantext.Config.Utils where
import Gargantext.Prelude
import Data.Array as A
import Data.Either (Either(..))
import Effect.Aff (Aff)
import Effect.Class (liftEffect)
import Gargantext.Config.REST (RESTError)
import Gargantext.Types (FrontendError(..))
import Gargantext.Utils.Reactix as R2
import Toestand as T
here :: R2.Here
here = R2.here "Gargantext.Config.Utils"
handleRESTError :: forall a. T.Box (Array FrontendError)
-> Either RESTError a
-> (a -> Aff Unit)
-> Aff Unit
handleRESTError errors (Left error) _ = liftEffect $ do
T.modify_ (A.cons $ FRESTError { error }) errors
here.log2 "[handleTaskError] RESTError" error
handleRESTError _ (Right task) handler = handler task
...@@ -2,6 +2,7 @@ module Gargantext.Hooks.Loader where ...@@ -2,6 +2,7 @@ module Gargantext.Hooks.Loader where
import Gargantext.Prelude import Gargantext.Prelude
import Data.Array as A
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.Generic.Rep (class Generic) import Data.Generic.Rep (class Generic)
import Data.Maybe (Maybe(..), isJust, maybe) import Data.Maybe (Maybe(..), isJust, maybe)
...@@ -10,15 +11,16 @@ import Effect (Effect) ...@@ -10,15 +11,16 @@ import Effect (Effect)
import Effect.Aff (Aff, launchAff_, throwError) import Effect.Aff (Aff, launchAff_, throwError)
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import Effect.Exception (error) import Effect.Exception (error)
import Reactix as R
import Simple.JSON as JSON
import Toestand as T
import Gargantext.Components.LoadingSpinner (loadingSpinner) import Gargantext.Components.LoadingSpinner (loadingSpinner)
import Gargantext.Config.REST (RESTError) import Gargantext.Config.REST (RESTError)
import Gargantext.Config.Utils (handleRESTError)
import Gargantext.Types (FrontendError(..))
import Gargantext.Utils.CacheAPI as GUC import Gargantext.Utils.CacheAPI as GUC
import Gargantext.Utils.Crypto (Hash) import Gargantext.Utils.Crypto (Hash)
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Reactix as R
import Simple.JSON as JSON
import Toestand as T
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Hooks.Loader" here = R2.here "Gargantext.Hooks.Loader"
...@@ -96,22 +98,24 @@ derive newtype instance JSON.ReadForeign a => JSON.ReadForeign (HashedResponse a ...@@ -96,22 +98,24 @@ derive newtype instance JSON.ReadForeign a => JSON.ReadForeign (HashedResponse a
derive newtype instance JSON.WriteForeign a => JSON.WriteForeign (HashedResponse a) derive newtype instance JSON.WriteForeign a => JSON.WriteForeign (HashedResponse a)
type LoaderWithCacheAPIProps path res ret = ( type LoaderWithCacheAPIProps path res ret = (
cacheEndpoint :: path -> Aff (Either RESTError Hash) cacheEndpoint :: path -> Aff (Either RESTError Hash)
, errors :: T.Box (Array FrontendError)
, handleResponse :: HashedResponse res -> ret , handleResponse :: HashedResponse res -> ret
, mkRequest :: path -> GUC.Request , mkRequest :: path -> GUC.Request
, path :: path , path :: path
, renderer :: ret -> R.Element , renderer :: ret -> R.Element
) )
useLoaderWithCacheAPI :: forall path res ret. useLoaderWithCacheAPI :: forall path res ret.
Eq ret => Eq path => JSON.ReadForeign res => Eq ret => Eq path => JSON.ReadForeign res =>
Record (LoaderWithCacheAPIProps path res ret) Record (LoaderWithCacheAPIProps path res ret)
-> R.Hooks R.Element -> R.Hooks R.Element
useLoaderWithCacheAPI { cacheEndpoint, handleResponse, mkRequest, path, renderer } = do useLoaderWithCacheAPI { cacheEndpoint, errors, handleResponse, mkRequest, path, renderer } = do
state <- T.useBox Nothing state <- T.useBox Nothing
state' <- T.useLive T.unequal state state' <- T.useLive T.unequal state
useCachedAPILoaderEffect { cacheEndpoint useCachedAPILoaderEffect { cacheEndpoint
, errors
, handleResponse , handleResponse
, mkRequest , mkRequest
, path , path
...@@ -120,6 +124,7 @@ useLoaderWithCacheAPI { cacheEndpoint, handleResponse, mkRequest, path, renderer ...@@ -120,6 +124,7 @@ useLoaderWithCacheAPI { cacheEndpoint, handleResponse, mkRequest, path, renderer
type LoaderWithCacheAPIEffectProps path res ret = ( type LoaderWithCacheAPIEffectProps path res ret = (
cacheEndpoint :: path -> Aff (Either RESTError Hash) cacheEndpoint :: path -> Aff (Either RESTError Hash)
, errors :: T.Box (Array FrontendError)
, handleResponse :: HashedResponse res -> ret , handleResponse :: HashedResponse res -> ret
, mkRequest :: path -> GUC.Request , mkRequest :: path -> GUC.Request
, path :: path , path :: path
...@@ -131,6 +136,7 @@ useCachedAPILoaderEffect :: forall path res ret. ...@@ -131,6 +136,7 @@ useCachedAPILoaderEffect :: forall path res ret.
Record (LoaderWithCacheAPIEffectProps path res ret) Record (LoaderWithCacheAPIEffectProps path res ret)
-> R.Hooks Unit -> R.Hooks Unit
useCachedAPILoaderEffect { cacheEndpoint useCachedAPILoaderEffect { cacheEndpoint
, errors
, handleResponse , handleResponse
, mkRequest , mkRequest
, path , path
...@@ -150,18 +156,18 @@ useCachedAPILoaderEffect { cacheEndpoint ...@@ -150,18 +156,18 @@ useCachedAPILoaderEffect { cacheEndpoint
cache <- GUC.openCache $ GUC.CacheName cacheName cache <- GUC.openCache $ GUC.CacheName cacheName
-- TODO Parallelize? -- TODO Parallelize?
hr@(HashedResponse { hash }) <- GUC.cachedJson cache req hr@(HashedResponse { hash }) <- GUC.cachedJson cache req
cacheReal <- cacheEndpoint path eCacheReal <- cacheEndpoint path
case cacheReal of handleRESTError errors eCacheReal $ \cacheReal -> do
Left _err -> throwError $ error $ "[useCachedAPILoaderEffect] RESTError" val <- if hash == cacheReal then
Right cacheReal' -> do pure hr
val <- if hash == cacheReal' then else do
pure hr _ <- GUC.deleteReq cache req
hr'@(HashedResponse { hash: h }) <- GUC.cachedJson cache req
if h == cacheReal then
pure hr'
else do else do
_ <- GUC.deleteReq cache req let err = "[Hooks.Loader] Fetched clean cache but hashes don't match: " <> h <> " != " <> cacheReal
hr'@(HashedResponse { hash: h }) <- GUC.cachedJson cache req liftEffect $ T.modify_ (A.cons $ FStringError { error: err }) errors
if h == cacheReal' then throwError $ error err
pure hr' liftEffect $ do
else T.write_ (Just $ handleResponse val) state
throwError $ error $ "[Hooks.Loader] Fetched clean cache but hashes don't match: " <> h <> " != " <> cacheReal'
liftEffect $ do
T.write_ (Just $ handleResponse val) state
...@@ -677,7 +677,7 @@ asyncTaskTypePath AddNode = "async/nobody/" ...@@ -677,7 +677,7 @@ asyncTaskTypePath AddNode = "async/nobody/"
asyncTaskTypePath Form = "add/form/async/" asyncTaskTypePath Form = "add/form/async/"
asyncTaskTypePath GraphRecompute = "async/recompute/" asyncTaskTypePath GraphRecompute = "async/recompute/"
asyncTaskTypePath ListUpload = "add/form/async/" asyncTaskTypePath ListUpload = "add/form/async/"
asyncTaskTypePath ListCSVUpload = "csv/add/form/async/" asyncTaskTypePath ListCSVUpload = "add/form/async/"
asyncTaskTypePath Query = "query/" asyncTaskTypePath Query = "query/"
asyncTaskTypePath UpdateNgramsCharts = "ngrams/async/charts/update/" asyncTaskTypePath UpdateNgramsCharts = "ngrams/async/charts/update/"
asyncTaskTypePath UpdateNode = "update/" asyncTaskTypePath UpdateNode = "update/"
...@@ -779,9 +779,10 @@ toggleSidePanelState Opened = Closed ...@@ -779,9 +779,10 @@ toggleSidePanelState Opened = Closed
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
newtype FrontendError = FrontendError data FrontendError = FStringError
{ error :: String { error :: String
} } | FRESTError
{ error :: RESTError }
derive instance Generic FrontendError _ derive instance Generic FrontendError _
instance Eq FrontendError where eq = genericEq instance Eq FrontendError where eq = genericEq
...@@ -86,7 +86,7 @@ cached cache req = do ...@@ -86,7 +86,7 @@ cached cache req = do
mResFresh <- match cache req mResFresh <- match cache req
case mResFresh of case mResFresh of
Just res -> pure res Just res -> pure res
Nothing -> throwError $ error $ "Cannot add to cache" Nothing -> throwError $ error $ "[cached] Cannot add to cache"
cachedJson :: forall a. JSON.ReadForeign a => Cache -> Request -> Aff a cachedJson :: forall a. JSON.ReadForeign a => Cache -> Request -> Aff a
cachedJson cache req = do cachedJson cache req = do
......
module Gargantext.Utils.Either where
import Gargantext.Prelude
import Data.Array (cons, uncons)
import Data.Either (Either(..))
import Data.Map as Map
import Data.Maybe (Maybe(..))
import Data.Tuple (Tuple(..))
eitherList :: forall l r. Array (Either l r) -> Either l (Array r)
eitherList xs = case uncons xs of
Nothing -> Right []
Just { head: Left x } -> Left x
Just { head: Right x, tail } ->
case eitherList tail of
Left err -> Left err
Right ds -> Right (cons x ds)
eitherMap :: forall k l r. Ord k => Map.Map k (Either l r) -> Either l (Map.Map k r)
eitherMap m = case eitherList (helper <$> Map.toUnfoldable m) of
Left err -> Left err
Right lst -> Right $ Map.fromFoldable lst
where
helper (Tuple _ (Left err)) = Left err
helper (Tuple k (Right v)) = Right (Tuple k v)
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