Commit 208bdfdf authored by Alexandre Delanoë's avatar Alexandre Delanoë

Merge remote-tracking branch 'origin/382-dev-plane-navigation' into dev-merge

parents 36df4cc8 38615b10
...@@ -23,7 +23,8 @@ import Gargantext.Components.Forest.Tree.Node.Action.Update (updateRequest) ...@@ -23,7 +23,8 @@ import Gargantext.Components.Forest.Tree.Node.Action.Update (updateRequest)
import Gargantext.Components.Forest.Tree.Node.Action.Upload (uploadArbitraryFile, uploadFile) import Gargantext.Components.Forest.Tree.Node.Action.Upload (uploadArbitraryFile, uploadFile)
import Gargantext.Components.Forest.Tree.Node.Box (nodePopupView) import Gargantext.Components.Forest.Tree.Node.Box (nodePopupView)
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree.Types (SubTreeOut(..)) import Gargantext.Components.Forest.Tree.Node.Tools.SubTree.Types (SubTreeOut(..))
import Gargantext.Components.GraphQL.Endpoints (getTreeFirstLevel) import Gargantext.Components.GraphQL.Endpoints (getNode, getTreeFirstLevel)
import Gargantext.Components.GraphQL.Node (Node)
import Gargantext.Components.GraphQL.Tree (TreeFirstLevel, TreeNode) import Gargantext.Components.GraphQL.Tree (TreeFirstLevel, TreeNode)
import Gargantext.Config.REST (AffRESTError, logRESTError) import Gargantext.Config.REST (AffRESTError, logRESTError)
import Gargantext.Config.Utils (handleRESTError) import Gargantext.Config.Utils (handleRESTError)
...@@ -32,7 +33,7 @@ import Gargantext.Hooks.Loader (useLoader) ...@@ -32,7 +33,7 @@ import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Prelude (Ordering, Unit, bind, compare, discard, otherwise, pure, unit, void, ($), (<$>), (<>)) import Gargantext.Prelude (Ordering, Unit, bind, compare, discard, otherwise, pure, unit, void, ($), (<$>), (<>))
import Gargantext.Routes (AppRoute(Home), nodeTypeAppRoute) import Gargantext.Routes (AppRoute(Home), nodeTypeAppRoute)
import Gargantext.Sessions (Session(..), sessionId) import Gargantext.Sessions (Session(..), sessionId)
import Gargantext.Types (NodeType(..)) import Gargantext.Types (NodeType(..), SessionId)
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
...@@ -86,82 +87,58 @@ folderViewMain :: R2.Component FolderViewProps ...@@ -86,82 +87,58 @@ folderViewMain :: R2.Component FolderViewProps
folderViewMain = R.createElement folderViewMainCpt folderViewMain = R.createElement folderViewMainCpt
folderViewMainCpt :: R.Component FolderViewProps folderViewMainCpt :: R.Component FolderViewProps
folderViewMainCpt = here.component "folderViewMainCpt" cpt where folderViewMainCpt = here.component "folderViewMainCpt" cpt where
cpt { boxes cpt props@{ folders: {parent: parentNode, children, root} } _ = do
, folders: {parent: parentNode, children} let folders' = A.sortBy sortFolders children
, nodeId let parent = makeParentFolder root parentNode props
, reload let childrenEl = makeFolderElements folders' props
, session
, setPopoverRef } _ = do
let foldersS = A.sortBy sortFolders children
let parent = makeParentFolder parentNode session
let childrenEl = makeFolderElements foldersS { boxes, nodeId, reload, session, setPopoverRef }
pure $ H.div {className: "fv folders"} $ parent <> childrenEl pure $ H.div {className: "fv folders"} $ parent <> childrenEl
makeFolderElements foldersS props = makeFolderElementsMap <$> foldersS where makeFolderElements :: Array TreeNode -> Record FolderViewProps -> Array R.Element
makeFolderElements folders' props = makeFolderElementsMap <$> folders' where
makeFolderElementsMap :: TreeNode -> R.Element makeFolderElementsMap :: TreeNode -> R.Element
makeFolderElementsMap node = folder { boxes: props.boxes makeFolderElementsMap node = folder { boxes: props.boxes
, nodeId: node.id , nodeId: node.id
, nodeType: node.node_type , linkId: node.id
, parentId: props.nodeId , nodeType: node.node_type
, reload: props.reload , linkNodeType: node.node_type
, session: props.session , parentId: props.nodeId
, setPopoverRef: props.setPopoverRef , reload: props.reload
, style: FolderChild , session: props.session
, text: node.name } [] , setPopoverRef: props.setPopoverRef
, style: FolderChild
makeParentFolder :: Maybe TreeNode -> Session -> Array R.Element , text: node.name } []
makeParentFolder (Just parent) session =
[ folderSimple {style: FolderUp, text: "..", nodeId: parent.id, nodeType: parent.node_type, session: session} [] ] makeParentFolder :: TreeNode -> Maybe TreeNode -> Record FolderViewProps -> Array R.Element
makeParentFolder Nothing _ = [] makeParentFolder root (Just parent) props =
[ folder { boxes: props.boxes
, nodeId: root.id
, linkId: parent.id
, linkNodeType: parent.node_type
, nodeType: root.node_type
, parentId: parent.id
, reload: props.reload
, session: props.session
, setPopoverRef: props.setPopoverRef
, style: FolderUp
, text: root.name } [] ]
makeParentFolder _ Nothing _ = []
sortFolders :: TreeNode-> TreeNode -> Ordering sortFolders :: TreeNode-> TreeNode -> Ordering
sortFolders a b = compare a.id b.id sortFolders a b = compare a.id b.id
type FolderSimpleProps =
(
style :: FolderStyle
, text :: String
, nodeType :: GT.NodeType
, nodeId :: Int
, session :: Session
)
folderSimple :: R2.Component FolderSimpleProps
folderSimple = R.createElement folderSimpleCpt
folderSimpleCpt :: R.Component FolderSimpleProps
folderSimpleCpt = here.component "folderSimpleCpt" cpt where
cpt {style, text, nodeId, session, nodeType} _ = do
{ goToRoute } <- useLinkHandler
let sid = sessionId session
let rootId = treeId session
pure $ H.button { className: "btn btn-primary"
, on: {click: \_ -> goToRoute $ route nodeId rootId nodeType sid} }
[ H.i { className: icon style nodeType } []
, H.br {}
, H.text text ]
where
treeId (Session {treeId: tId}) = tId
route nId rootId nType sid
| rootId == nodeId = Home
| otherwise = getFolderPath nType sid nId
icon :: FolderStyle -> GT.NodeType -> String
icon FolderUp _ = "fa fa-folder-open"
icon _ nodeType = GT.fldr nodeType false
getFolderPath :: GT.NodeType -> GT.SessionId -> Int -> AppRoute
getFolderPath nodeType sid nodeId = fromMaybe Home $ nodeTypeAppRoute nodeType sid nodeId
type FolderProps = type FolderProps =
( boxes :: Boxes ( style :: FolderStyle
, text :: String
, nodeType :: GT.NodeType
, nodeId :: Int
, linkNodeType :: GT.NodeType
, linkId :: Int
, session :: Session
, boxes :: Boxes
, parentId :: Int , parentId :: Int
, reload :: T.Box T2.Reload , reload :: T.Box T2.Reload
, setPopoverRef :: R.Ref (Maybe (Boolean -> Effect Unit)) , setPopoverRef :: R.Ref (Maybe (Boolean -> Effect Unit))
| FolderSimpleProps
) )
folder :: R2.Component FolderProps folder :: R2.Component FolderProps
...@@ -171,6 +148,8 @@ folderCpt = here.component "folderCpt" cpt where ...@@ -171,6 +148,8 @@ folderCpt = here.component "folderCpt" cpt where
cpt props@{ boxes cpt props@{ boxes
, nodeId , nodeId
, nodeType , nodeType
, linkId
, linkNodeType
, parentId , parentId
, reload , reload
, session , session
...@@ -178,6 +157,7 @@ folderCpt = here.component "folderCpt" cpt where ...@@ -178,6 +157,7 @@ folderCpt = here.component "folderCpt" cpt where
, style , style
, text } _ = do , text } _ = do
let sid = sessionId session let sid = sessionId session
let rootId = treeId session
let dispatch a = performAction a { boxes, nodeId, parentId, reload, session, setPopoverRef } let dispatch a = performAction a { boxes, nodeId, parentId, reload, session, setPopoverRef }
popoverRef <- R.useRef null popoverRef <- R.useRef null
{ goToRoute } <- useLinkHandler { goToRoute } <- useLinkHandler
...@@ -197,19 +177,11 @@ folderCpt = here.component "folderCpt" cpt where ...@@ -197,19 +177,11 @@ folderCpt = here.component "folderCpt" cpt where
popOverIcon popOverIcon
, mNodePopupView (Record.merge props { dispatch }) (onPopoverClose popoverRef) , mNodePopupView (Record.merge props { dispatch }) (onPopoverClose popoverRef)
]] ]]
, H.button {on: {click: \_ -> goToRoute $ getFolderPath nodeType sid nodeId }, className: "btn btn-primary fv btn" } [ , H.button {on: {click: \_ -> goToRoute $ route linkId rootId linkNodeType sid }, className: "btn btn-primary fv btn" } [
H.i {className: icon style nodeType} [] H.i {className: icon style nodeType} []
, H.br {} , H.br {}
, H.text text]] , H.text text]]
icon :: FolderStyle -> GT.NodeType -> String
icon FolderUp _ = "fa fa-folder-open"
icon _ nodeType = GT.fldr nodeType false
getFolderPath :: GT.NodeType -> GT.SessionId -> Int -> AppRoute
getFolderPath nodeType sid nodeId = fromMaybe Home $ nodeTypeAppRoute nodeType sid nodeId
onPopoverClose popoverRef _ = Popover.setOpen popoverRef false onPopoverClose popoverRef _ = Popover.setOpen popoverRef false
popOverIcon = H.span { className: "fv action" } [ popOverIcon = H.span { className: "fv action" } [
...@@ -226,11 +198,22 @@ folderCpt = here.component "folderCpt" cpt where ...@@ -226,11 +198,22 @@ folderCpt = here.component "folderCpt" cpt where
, name: props.text , name: props.text
, session: props.session , session: props.session
} }
route :: Int -> Int -> NodeType -> SessionId -> AppRoute
route lId rootId nType sid
| rootId == lId = Home
| otherwise = getFolderPath nType sid lId
icon :: FolderStyle -> GT.NodeType -> String
icon FolderUp _ = "fa fa-folder-open"
icon _ nodeType = GT.fldr nodeType false
getFolderPath :: GT.NodeType -> GT.SessionId -> Int -> AppRoute
getFolderPath nodeType sid nodeId = fromMaybe Home $ nodeTypeAppRoute nodeType sid nodeId
backButton :: R2.Component () backButton :: R2.Component ()
backButton = R.createElement backButtonCpt backButton = R.createElement backButtonCpt
backButtonCpt :: R.Component () backButtonCpt :: R.Component ()
backButtonCpt = R.hooksComponent "backButton" cpt where backButtonCpt = here.component "backButton" cpt where
cpt _ _ = do cpt _ _ = do
{ goToPreviousPage } <- useLinkHandler { goToPreviousPage } <- useLinkHandler
...@@ -242,6 +225,46 @@ backButtonCpt = R.hooksComponent "backButton" cpt where ...@@ -242,6 +225,46 @@ backButtonCpt = R.hooksComponent "backButton" cpt where
H.i { className: "fa fa-arrow-left", title: "Previous view"} [] H.i { className: "fa fa-arrow-left", title: "Previous view"} []
] ]
backButtonSmart :: R2.Component (nodeId :: Int, session :: Session)
backButtonSmart = R.createElement backButtonSmartCpt
backButtonSmartCpt :: R.Component (nodeId :: Int, session :: Session)
backButtonSmartCpt = here.component "backButtonSmart" cpt where
cpt {nodeId, session} _ = do
reload <- T.useBox T2.newReload
reload' <- T.useLive T.unequal reload
useLoader { errorHandler
, loader: loadNode
, path: { nodeId, session, reload: reload' }
, render: \node -> backButtonSmartMain { node, session } []
}
where
errorHandler = logRESTError here "[folderView]"
backButtonSmartMain :: R2.Component (node :: Node, session :: Session)
backButtonSmartMain = R.createElement backButtonSmartMainCpt
backButtonSmartMainCpt :: R.Component (node :: Node, session :: Session)
backButtonSmartMainCpt = here.component "backButtonSmartMain" cpt where
cpt { node, session } _ = do
handlers <- useLinkHandler
let rootId = treeId session
pure $
H.button {
className: "btn btn-primary"
, on: { click: action rootId node.parent_id handlers }
} [
H.i { className: "fa fa-arrow-left", title: "Previous view"} []
]
where
action rootId pId handlers
| rootId == pId = handlers.goToRoute Home
| otherwise = handlers.goToPreviousPage unit
treeId :: Session -> Int
treeId (Session {treeId: tId}) = tId
type LoadProps = type LoadProps =
( (
session :: Session, session :: Session,
...@@ -252,6 +275,9 @@ type LoadProps = ...@@ -252,6 +275,9 @@ type LoadProps =
loadFolders :: Record LoadProps -> AffRESTError TreeFirstLevel loadFolders :: Record LoadProps -> AffRESTError TreeFirstLevel
loadFolders {nodeId, session} = getTreeFirstLevel session nodeId loadFolders {nodeId, session} = getTreeFirstLevel session nodeId
loadNode :: Record LoadProps -> AffRESTError Node
loadNode {nodeId, session} = getNode session nodeId
type PerformActionProps = type PerformActionProps =
( boxes :: Boxes ( boxes :: Boxes
, nodeId :: Int , nodeId :: Int
......
...@@ -71,6 +71,7 @@ queryGql session name q = do ...@@ -71,6 +71,7 @@ queryGql session name q = do
-- Schema -- Schema
type Schema type Schema
= { imt_schools :: {} ==> Array GQLIMT.School = { imt_schools :: {} ==> Array GQLIMT.School
, nodes :: { node_id :: Int } ==> Array Node
, node_parent :: { node_id :: Int, parent_type :: String } ==> Array Node -- TODO: parent_type :: NodeType , node_parent :: { node_id :: Int, parent_type :: String } ==> Array Node -- TODO: parent_type :: NodeType
, user_infos :: { user_id :: Int } ==> Array UserInfo , user_infos :: { user_id :: Int } ==> Array UserInfo
, users :: { user_id :: Int } ==> Array User , users :: { user_id :: Int } ==> Array User
......
...@@ -2,7 +2,7 @@ module Gargantext.Components.GraphQL.Endpoints where ...@@ -2,7 +2,7 @@ module Gargantext.Components.GraphQL.Endpoints where
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Components.GraphQL.Node (Node, nodeParentQuery) import Gargantext.Components.GraphQL.Node (Node, nodeParentQuery, nodesQuery)
import Gargantext.Components.GraphQL.Tree (TreeFirstLevel, treeFirstLevelQuery) import Gargantext.Components.GraphQL.Tree (TreeFirstLevel, treeFirstLevelQuery)
import Gargantext.Components.GraphQL.User (UserInfo, userInfoQuery) import Gargantext.Components.GraphQL.User (UserInfo, userInfoQuery)
...@@ -30,6 +30,15 @@ getIMTSchools session = do ...@@ -30,6 +30,15 @@ getIMTSchools session = do
liftEffect $ here.log2 "[getIMTSchools] imt_schools" imt_schools liftEffect $ here.log2 "[getIMTSchools] imt_schools" imt_schools
pure $ Right imt_schools pure $ Right imt_schools
getNode :: Session -> Int -> AffRESTError Node
getNode session nodeId = do
{ nodes } <- queryGql session "get nodes" $
nodesQuery `withVars` { id: nodeId }
liftEffect $ here.log2 "[getNode] node" nodes
pure $ case A.head nodes of
Nothing -> Left (CustomError $ "node with id" <> show nodeId <>" not found")
Just node -> Right node
getNodeParent :: Session -> Int -> NodeType -> Aff (Array Node) getNodeParent :: Session -> Int -> NodeType -> Aff (Array Node)
getNodeParent session nodeId parentType = do getNodeParent session nodeId parentType = do
{ node_parent } <- queryGql session "get node parent" $ { node_parent } <- queryGql session "get node parent" $
......
...@@ -11,6 +11,7 @@ type TreeNode = ...@@ -11,6 +11,7 @@ type TreeNode =
{ name :: String { name :: String
, id :: Int , id :: Int
, node_type :: NodeType , node_type :: NodeType
, parent_id :: Maybe Int
} }
type TreeFirstLevel = type TreeFirstLevel =
{ root :: TreeNode { root :: TreeNode
...@@ -22,14 +23,17 @@ treeFirstLevelQuery = { tree: { root_id: Var :: _ "id" Int} =>> ...@@ -22,14 +23,17 @@ treeFirstLevelQuery = { tree: { root_id: Var :: _ "id" Int} =>>
{ root: { name: unit { root: { name: unit
, node_type: unit , node_type: unit
, id: unit , id: unit
, parent_id: unit
} }
, children: { name: unit , children: { name: unit
, node_type: unit , node_type: unit
, id: unit , id: unit
, parent_id: unit
} }
, parent: { name: unit , parent: { name: unit
, node_type: unit , node_type: unit
, id: unit , id: unit
, parent_id: unit
} }
} }
} }
...@@ -68,20 +68,22 @@ corpusLayoutMainCpt = here.component "corpusLayoutMain" cpt ...@@ -68,20 +68,22 @@ corpusLayoutMainCpt = here.component "corpusLayoutMain" cpt
pure $ GR.CorpusCode (sessionId session) nodeId pure $ GR.CorpusCode (sessionId session) nodeId
-- Render -- Render
pure $ pure $
H.div {} H.div {}
[ [
tileMenu R2.row [
{ boxes FV.backButtonSmart { nodeId, session } []
, currentTile: Just corpusCodeRoute , tileMenu
, xTile: Just corpusCodeRoute { boxes
, yTile: Just corpusCodeRoute , currentTile: Just corpusCodeRoute
} , xTile: Just corpusCodeRoute
[ , yTile: Just corpusCodeRoute
H.button }
{ className: "btn btn-primary" }
[ [
H.i { className: "fa fa-code" } [] H.button
{ className: "btn btn-primary" }
[
H.i { className: "fa fa-code" } []
]
] ]
] ]
, ,
......
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