{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DuplicateRecordFields #-} module Gargantext.API.GraphQL.TreeFirstLevel where import Gargantext.Prelude import Data.Morpheus.Types (GQLType, lift, Resolver, QUERY) import GHC.Generics (Generic) import Data.Text (Text) import Gargantext.API.Prelude (GargM, GargError) import Gargantext.Database.Prelude (HasConnectionPool, HasConfig) import Gargantext.Core.Mail.Types (HasMail) import qualified Gargantext.Database.Query.Tree as T import qualified Gargantext.Database.Schema.Node as N import qualified Gargantext.Database.Admin.Types.Node as NN import Gargantext.Database.Admin.Types.Node (allNodeTypes, NodeId (NodeId)) import Gargantext.Core.Types (Tree, NodeTree, NodeType) import Gargantext.Core.Types.Main ( Tree(TreeN), _tn_node, _tn_children, NodeTree(NodeTree, _nt_id, _nt_type), _nt_name ) import Gargantext.Database.Query.Table.Node (getNode) import Gargantext.Database.Admin.Config (fromNodeTypeId) import Gargantext.Database.Schema.Node (NodePoly(_node_parent_id)) data TreeArgs = TreeArgs { root_id :: Int } deriving (Generic, GQLType) data TreeNode = TreeNode { name :: Text , id :: Int , node_type :: NodeType , parent_id :: Maybe Int } deriving (Generic, GQLType) data TreeFirstLevel m = TreeFirstLevel { root :: TreeNode , parent :: m (Maybe TreeNode) , children :: [TreeNode] } deriving (Generic, GQLType) type GqlM e env = Resolver QUERY e (GargM env GargError) type ParentId = Maybe NodeId resolveTree :: (HasConnectionPool env, HasConfig env, HasMail env) => TreeArgs -> GqlM e env (TreeFirstLevel (GqlM e env)) resolveTree TreeArgs { root_id } = dbTree root_id dbTree :: (HasConnectionPool env, HasConfig env, HasMail env) => Int -> GqlM e env (TreeFirstLevel (GqlM e env)) dbTree root_id = do let rId = NodeId root_id t <- lift $ T.tree T.TreeFirstLevel rId allNodeTypes n <- lift $ getNode $ NodeId root_id let pId = toParentId n pure $ toTree rId pId t where toParentId N.Node { _node_parent_id } = _node_parent_id toTree :: (HasConnectionPool env, HasConfig env, HasMail env) => NodeId -> ParentId -> Tree NodeTree -> TreeFirstLevel (GqlM e env) toTree rId pId TreeN { _tn_node, _tn_children } = TreeFirstLevel { parent = resolveParent pId , root = toTreeNode pId _tn_node , children = map childrenToTreeNodes $ zip _tn_children $ repeat rId } toTreeNode :: ParentId -> NodeTree -> TreeNode toTreeNode pId NodeTree { _nt_name, _nt_id, _nt_type } = TreeNode { name = _nt_name, id = id2int _nt_id, node_type = _nt_type, parent_id = id2int <$> pId} where id2int :: NodeId -> Int id2int (NodeId n) = n childrenToTreeNodes :: (Tree NodeTree, NodeId) -> TreeNode childrenToTreeNodes (TreeN {_tn_node}, rId) = toTreeNode (Just rId) _tn_node resolveParent :: (HasConnectionPool env, HasConfig env, HasMail env) => Maybe NodeId -> GqlM e env (Maybe TreeNode) resolveParent (Just pId) = do node <- lift $ getNode pId pure $ Just $ nodeToTreeNode node resolveParent Nothing = pure Nothing nodeToTreeNode :: NN.Node json -> TreeNode nodeToTreeNode N.Node {..} = TreeNode { id = NN.unNodeId _node_id , name = _node_name , node_type = fromNodeTypeId _node_typename , parent_id = NN.unNodeId <$> _node_parent_id }